From dabf075f82781ca258e57302ed1d961d7aff7729 Mon Sep 17 00:00:00 2001 From: Expand-sys Date: Wed, 28 Apr 2021 16:19:22 +1000 Subject: [PATCH] basic bot --- commands/moderation/kick.js | 15 + commands/moderation/prune.js | 19 + commands/moderation/rolekick.js | 23 + commands/utility/args-info.js | 12 + commands/utility/help.js | 46 + commands/utility/reload.js | 30 + commands/utility/server.js | 7 + commands/utility/user-info.js | 7 + config.json | 4 + helpers/ai.js | 61 + helpers/leetspeak.js | 91 + helpers/makecard.js | 65 + helpers/steamer.js | 168 + helpers/urbaner.js | 47 + index.js | 106 + node_modules/.package-lock.json | 448 + node_modules/@discordjs/collection/LICENSE | 190 + node_modules/@discordjs/collection/README.md | 3 + .../@discordjs/collection/dist/index.d.ts | 319 + .../@discordjs/collection/dist/index.js | 392 + .../@discordjs/collection/package.json | 49 + node_modules/@discordjs/form-data/License | 19 + node_modules/@discordjs/form-data/Readme.md | 353 + node_modules/@discordjs/form-data/index.d.ts | 61 + .../@discordjs/form-data/lib/browser.js | 2 + .../@discordjs/form-data/lib/form_data.js | 497 + .../@discordjs/form-data/lib/populate.js | 10 + .../@discordjs/form-data/package.json | 64 + node_modules/@sindresorhus/is/dist/index.d.ts | 220 + node_modules/@sindresorhus/is/dist/index.js | 418 + node_modules/@sindresorhus/is/dist/types.d.ts | 24 + node_modules/@sindresorhus/is/dist/types.js | 3 + node_modules/@sindresorhus/is/license | 9 + node_modules/@sindresorhus/is/package.json | 96 + node_modules/@sindresorhus/is/readme.md | 602 ++ node_modules/@szmarczak/http-timer/LICENSE | 21 + node_modules/@szmarczak/http-timer/README.md | 89 + .../http-timer/dist/source/index.d.ts | 32 + .../http-timer/dist/source/index.js | 117 + .../@szmarczak/http-timer/package.json | 74 + node_modules/@types/cacheable-request/LICENSE | 21 + .../@types/cacheable-request/README.md | 16 + .../@types/cacheable-request/index.d.ts | 137 + .../@types/cacheable-request/package.json | 34 + .../@types/http-cache-semantics/LICENSE | 21 + .../@types/http-cache-semantics/README.md | 16 + .../@types/http-cache-semantics/index.d.ts | 170 + .../@types/http-cache-semantics/package.json | 23 + node_modules/@types/keyv/LICENSE | 21 + node_modules/@types/keyv/README.md | 16 + node_modules/@types/keyv/index.d.ts | 70 + node_modules/@types/keyv/package.json | 31 + node_modules/@types/node/LICENSE | 21 + node_modules/@types/node/README.md | 16 + node_modules/@types/node/assert.d.ts | 129 + node_modules/@types/node/assert/strict.d.ts | 4 + node_modules/@types/node/async_hooks.d.ts | 233 + node_modules/@types/node/base.d.ts | 19 + node_modules/@types/node/buffer.d.ts | 26 + node_modules/@types/node/child_process.d.ts | 514 + node_modules/@types/node/cluster.d.ts | 266 + node_modules/@types/node/console.d.ts | 137 + node_modules/@types/node/constants.d.ts | 19 + node_modules/@types/node/crypto.d.ts | 1274 +++ node_modules/@types/node/dgram.d.ts | 145 + node_modules/@types/node/dns.d.ts | 326 + node_modules/@types/node/dns/promises.d.ts | 101 + node_modules/@types/node/domain.d.ts | 28 + node_modules/@types/node/events.d.ts | 87 + node_modules/@types/node/fs.d.ts | 2261 +++++ node_modules/@types/node/fs/promises.d.ts | 561 ++ node_modules/@types/node/globals.d.ts | 649 ++ node_modules/@types/node/globals.global.d.ts | 1 + node_modules/@types/node/http.d.ts | 428 + node_modules/@types/node/http2.d.ts | 968 ++ node_modules/@types/node/https.d.ts | 40 + node_modules/@types/node/index.d.ts | 58 + node_modules/@types/node/inspector.d.ts | 3048 ++++++ node_modules/@types/node/module.d.ts | 57 + node_modules/@types/node/net.d.ts | 328 + node_modules/@types/node/os.d.ts | 243 + node_modules/@types/node/package.json | 231 + node_modules/@types/node/path.d.ts | 158 + node_modules/@types/node/perf_hooks.d.ts | 275 + node_modules/@types/node/process.d.ts | 453 + node_modules/@types/node/punycode.d.ts | 86 + node_modules/@types/node/querystring.d.ts | 32 + node_modules/@types/node/readline.d.ts | 174 + node_modules/@types/node/repl.d.ts | 399 + node_modules/@types/node/stream.d.ts | 468 + node_modules/@types/node/stream/promises.d.ts | 71 + node_modules/@types/node/string_decoder.d.ts | 11 + node_modules/@types/node/timers.d.ts | 34 + node_modules/@types/node/timers/promises.d.ts | 17 + node_modules/@types/node/tls.d.ts | 783 ++ node_modules/@types/node/trace_events.d.ts | 65 + node_modules/@types/node/ts3.6/assert.d.ts | 103 + node_modules/@types/node/ts3.6/base.d.ts | 66 + node_modules/@types/node/ts3.6/index.d.ts | 7 + node_modules/@types/node/tty.d.ts | 70 + node_modules/@types/node/url.d.ts | 120 + node_modules/@types/node/util.d.ts | 211 + node_modules/@types/node/v8.d.ts | 191 + node_modules/@types/node/vm.d.ts | 156 + node_modules/@types/node/wasi.d.ts | 90 + node_modules/@types/node/worker_threads.d.ts | 245 + node_modules/@types/node/zlib.d.ts | 365 + node_modules/@types/responselike/LICENSE | 21 + node_modules/@types/responselike/README.md | 16 + node_modules/@types/responselike/index.d.ts | 34 + node_modules/@types/responselike/package.json | 25 + node_modules/abort-controller/LICENSE | 21 + node_modules/abort-controller/README.md | 98 + node_modules/abort-controller/browser.js | 13 + node_modules/abort-controller/browser.mjs | 11 + .../dist/abort-controller.d.ts | 43 + .../abort-controller/dist/abort-controller.js | 127 + .../dist/abort-controller.js.map | 1 + .../dist/abort-controller.mjs | 118 + .../dist/abort-controller.mjs.map | 1 + .../dist/abort-controller.umd.js | 5 + .../dist/abort-controller.umd.js.map | 1 + node_modules/abort-controller/package.json | 97 + node_modules/abort-controller/polyfill.js | 21 + node_modules/abort-controller/polyfill.mjs | 19 + node_modules/asynckit/LICENSE | 21 + node_modules/asynckit/README.md | 233 + node_modules/asynckit/bench.js | 76 + node_modules/asynckit/index.js | 6 + node_modules/asynckit/lib/abort.js | 29 + node_modules/asynckit/lib/async.js | 34 + node_modules/asynckit/lib/defer.js | 26 + node_modules/asynckit/lib/iterate.js | 75 + .../asynckit/lib/readable_asynckit.js | 91 + .../asynckit/lib/readable_parallel.js | 25 + node_modules/asynckit/lib/readable_serial.js | 25 + .../asynckit/lib/readable_serial_ordered.js | 29 + node_modules/asynckit/lib/state.js | 37 + node_modules/asynckit/lib/streamify.js | 141 + node_modules/asynckit/lib/terminator.js | 29 + node_modules/asynckit/package.json | 63 + node_modules/asynckit/parallel.js | 43 + node_modules/asynckit/serial.js | 17 + node_modules/asynckit/serialOrdered.js | 75 + node_modules/asynckit/stream.js | 21 + node_modules/cacheable-lookup/LICENSE | 21 + node_modules/cacheable-lookup/README.md | 240 + node_modules/cacheable-lookup/index.d.ts | 139 + node_modules/cacheable-lookup/package.json | 45 + node_modules/cacheable-lookup/source/index.js | 436 + node_modules/cacheable-request/LICENSE | 21 + node_modules/cacheable-request/README.md | 206 + node_modules/cacheable-request/package.json | 56 + node_modules/cacheable-request/src/index.js | 251 + node_modules/clone-response/LICENSE | 21 + node_modules/clone-response/README.md | 62 + node_modules/clone-response/package.json | 44 + node_modules/clone-response/src/index.js | 17 + node_modules/combined-stream/License | 19 + node_modules/combined-stream/Readme.md | 138 + .../combined-stream/lib/combined_stream.js | 208 + node_modules/combined-stream/package.json | 25 + node_modules/combined-stream/yarn.lock | 17 + node_modules/decompress-response/index.d.ts | 22 + node_modules/decompress-response/index.js | 58 + node_modules/decompress-response/license | 9 + .../node_modules/mimic-response/index.d.ts | 17 + .../node_modules/mimic-response/index.js | 77 + .../node_modules/mimic-response/license | 9 + .../node_modules/mimic-response/package.json | 42 + .../node_modules/mimic-response/readme.md | 78 + node_modules/decompress-response/package.json | 56 + node_modules/decompress-response/readme.md | 48 + node_modules/defer-to-connect/LICENSE | 21 + node_modules/defer-to-connect/README.md | 38 + .../defer-to-connect/dist/source/index.d.ts | 10 + .../defer-to-connect/dist/source/index.js | 47 + node_modules/defer-to-connect/package.json | 71 + node_modules/delayed-stream/.npmignore | 1 + node_modules/delayed-stream/License | 19 + node_modules/delayed-stream/Makefile | 7 + node_modules/delayed-stream/Readme.md | 141 + .../delayed-stream/lib/delayed_stream.js | 107 + node_modules/delayed-stream/package.json | 27 + node_modules/discord.js/.tern-project | 17 + node_modules/discord.js/LICENSE | 190 + node_modules/discord.js/README.md | 111 + node_modules/discord.js/esm/discord.mjs | 95 + node_modules/discord.js/jsdoc.json | 3 + node_modules/discord.js/package.json | 163 + node_modules/discord.js/src/WebSocket.js | 49 + .../discord.js/src/client/BaseClient.js | 169 + node_modules/discord.js/src/client/Client.js | 504 + .../discord.js/src/client/WebhookClient.js | 31 + .../discord.js/src/client/actions/Action.js | 105 + .../src/client/actions/ActionsManager.js | 47 + .../src/client/actions/ChannelCreate.js | 23 + .../src/client/actions/ChannelDelete.js | 37 + .../src/client/actions/ChannelUpdate.js | 33 + .../src/client/actions/GuildBanRemove.js | 21 + .../actions/GuildChannelsPositionUpdate.js | 21 + .../src/client/actions/GuildDelete.js | 67 + .../src/client/actions/GuildEmojiCreate.js | 20 + .../src/client/actions/GuildEmojiDelete.js | 20 + .../src/client/actions/GuildEmojiUpdate.js | 20 + .../src/client/actions/GuildEmojisUpdate.js | 34 + .../client/actions/GuildIntegrationsUpdate.js | 19 + .../src/client/actions/GuildMemberRemove.js | 30 + .../src/client/actions/GuildMemberUpdate.js | 44 + .../src/client/actions/GuildRoleCreate.js | 25 + .../src/client/actions/GuildRoleDelete.js | 30 + .../src/client/actions/GuildRoleUpdate.js | 39 + .../actions/GuildRolesPositionUpdate.js | 21 + .../src/client/actions/GuildUpdate.js | 33 + .../src/client/actions/InviteCreate.js | 28 + .../src/client/actions/InviteDelete.js | 29 + .../src/client/actions/MessageCreate.js | 39 + .../src/client/actions/MessageDelete.js | 29 + .../src/client/actions/MessageDeleteBulk.js | 43 + .../src/client/actions/MessageReactionAdd.js | 55 + .../client/actions/MessageReactionRemove.js | 45 + .../actions/MessageReactionRemoveAll.js | 29 + .../actions/MessageReactionRemoveEmoji.js | 28 + .../src/client/actions/MessageUpdate.js | 24 + .../src/client/actions/PresenceUpdate.js | 44 + .../src/client/actions/TypingStart.js | 58 + .../src/client/actions/UserUpdate.js | 35 + .../src/client/actions/VoiceStateUpdate.js | 45 + .../src/client/actions/WebhooksUpdate.js | 19 + .../src/client/voice/ClientVoiceManager.js | 116 + .../src/client/voice/VoiceBroadcast.js | 111 + .../src/client/voice/VoiceConnection.js | 526 ++ .../voice/dispatcher/BroadcastDispatcher.js | 46 + .../voice/dispatcher/StreamDispatcher.js | 354 + .../client/voice/networking/VoiceUDPClient.js | 154 + .../client/voice/networking/VoiceWebSocket.js | 268 + .../src/client/voice/player/AudioPlayer.js | 27 + .../src/client/voice/player/BasePlayer.js | 92 + .../voice/player/BroadcastAudioPlayer.js | 28 + .../client/voice/receiver/PacketHandler.js | 143 + .../src/client/voice/receiver/Receiver.js | 58 + .../src/client/voice/util/PlayInterface.js | 94 + .../src/client/voice/util/Secretbox.js | 32 + .../src/client/voice/util/Silence.js | 15 + .../src/client/voice/util/VolumeInterface.js | 103 + .../src/client/websocket/WebSocketManager.js | 437 + .../src/client/websocket/WebSocketShard.js | 771 ++ .../websocket/handlers/CHANNEL_CREATE.js | 5 + .../websocket/handlers/CHANNEL_DELETE.js | 5 + .../websocket/handlers/CHANNEL_PINS_UPDATE.js | 22 + .../websocket/handlers/CHANNEL_UPDATE.js | 16 + .../websocket/handlers/GUILD_BAN_ADD.js | 16 + .../websocket/handlers/GUILD_BAN_REMOVE.js | 5 + .../client/websocket/handlers/GUILD_CREATE.js | 36 + .../client/websocket/handlers/GUILD_DELETE.js | 5 + .../websocket/handlers/GUILD_EMOJIS_UPDATE.js | 5 + .../handlers/GUILD_INTEGRATIONS_UPDATE.js | 5 + .../websocket/handlers/GUILD_MEMBERS_CHUNK.js | 30 + .../websocket/handlers/GUILD_MEMBER_ADD.js | 19 + .../websocket/handlers/GUILD_MEMBER_REMOVE.js | 5 + .../websocket/handlers/GUILD_MEMBER_UPDATE.js | 5 + .../websocket/handlers/GUILD_ROLE_CREATE.js | 5 + .../websocket/handlers/GUILD_ROLE_DELETE.js | 5 + .../websocket/handlers/GUILD_ROLE_UPDATE.js | 5 + .../client/websocket/handlers/GUILD_UPDATE.js | 5 + .../websocket/handlers/INVITE_CREATE.js | 5 + .../websocket/handlers/INVITE_DELETE.js | 5 + .../websocket/handlers/MESSAGE_CREATE.js | 5 + .../websocket/handlers/MESSAGE_DELETE.js | 5 + .../websocket/handlers/MESSAGE_DELETE_BULK.js | 5 + .../handlers/MESSAGE_REACTION_ADD.js | 5 + .../handlers/MESSAGE_REACTION_REMOVE.js | 5 + .../handlers/MESSAGE_REACTION_REMOVE_ALL.js | 5 + .../handlers/MESSAGE_REACTION_REMOVE_EMOJI.js | 5 + .../websocket/handlers/MESSAGE_UPDATE.js | 16 + .../websocket/handlers/PRESENCE_UPDATE.js | 5 + .../src/client/websocket/handlers/READY.js | 21 + .../src/client/websocket/handlers/RESUMED.js | 14 + .../client/websocket/handlers/TYPING_START.js | 5 + .../client/websocket/handlers/USER_UPDATE.js | 5 + .../websocket/handlers/VOICE_SERVER_UPDATE.js | 6 + .../websocket/handlers/VOICE_STATE_UPDATE.js | 5 + .../websocket/handlers/WEBHOOKS_UPDATE.js | 5 + .../src/client/websocket/handlers/index.js | 13 + .../discord.js/src/errors/DJSError.js | 61 + .../discord.js/src/errors/Messages.js | 111 + node_modules/discord.js/src/errors/index.js | 4 + node_modules/discord.js/src/index.js | 108 + .../discord.js/src/managers/BaseManager.js | 81 + .../discord.js/src/managers/ChannelManager.js | 96 + .../src/managers/GuildChannelManager.js | 131 + .../src/managers/GuildEmojiManager.js | 135 + .../src/managers/GuildEmojiRoleManager.js | 119 + .../discord.js/src/managers/GuildManager.js | 252 + .../src/managers/GuildMemberManager.js | 325 + .../src/managers/GuildMemberRoleManager.js | 161 + .../discord.js/src/managers/MessageManager.js | 147 + .../src/managers/PresenceManager.js | 59 + .../src/managers/ReactionManager.js | 69 + .../src/managers/ReactionUserManager.js | 66 + .../discord.js/src/managers/RoleManager.js | 146 + .../discord.js/src/managers/UserManager.js | 72 + .../src/managers/VoiceStateManager.js | 35 + .../discord.js/src/rest/APIRequest.js | 67 + node_modules/discord.js/src/rest/APIRouter.js | 53 + .../discord.js/src/rest/AsyncQueue.js | 95 + .../discord.js/src/rest/DiscordAPIError.js | 68 + node_modules/discord.js/src/rest/HTTPError.js | 37 + .../discord.js/src/rest/RESTManager.js | 59 + .../discord.js/src/rest/RequestHandler.js | 173 + node_modules/discord.js/src/sharding/Shard.js | 396 + .../src/sharding/ShardClientUtil.js | 243 + .../src/sharding/ShardingManager.js | 290 + .../discord.js/src/structures/APIMessage.js | 396 + .../discord.js/src/structures/Base.js | 43 + .../src/structures/BaseGuildEmoji.js | 66 + .../src/structures/CategoryChannel.js | 33 + .../discord.js/src/structures/Channel.js | 161 + .../src/structures/ClientApplication.js | 46 + .../src/structures/ClientPresence.js | 87 + .../discord.js/src/structures/ClientUser.js | 178 + .../discord.js/src/structures/DMChannel.js | 99 + .../discord.js/src/structures/Emoji.js | 104 + .../discord.js/src/structures/Guild.js | 1583 ++++ .../src/structures/GuildAuditLogs.js | 509 + .../discord.js/src/structures/GuildChannel.js | 624 ++ .../discord.js/src/structures/GuildEmoji.js | 168 + .../discord.js/src/structures/GuildMember.js | 414 + .../discord.js/src/structures/GuildPreview.js | 157 + .../src/structures/GuildPreviewEmoji.js | 26 + .../src/structures/GuildTemplate.js | 225 + .../discord.js/src/structures/Integration.js | 186 + .../src/structures/IntegrationApplication.js | 25 + .../discord.js/src/structures/Invite.js | 194 + .../discord.js/src/structures/Message.js | 700 ++ .../src/structures/MessageAttachment.js | 98 + .../src/structures/MessageCollector.js | 129 + .../discord.js/src/structures/MessageEmbed.js | 461 + .../src/structures/MessageMentions.js | 225 + .../src/structures/MessageReaction.js | 136 + .../discord.js/src/structures/NewsChannel.js | 38 + .../src/structures/PartialGroupDMChannel.js | 46 + .../src/structures/PermissionOverwrites.js | 189 + .../discord.js/src/structures/Presence.js | 336 + .../src/structures/ReactionCollector.js | 188 + .../src/structures/ReactionEmoji.js | 31 + .../discord.js/src/structures/Role.js | 403 + .../discord.js/src/structures/StoreChannel.js | 32 + .../discord.js/src/structures/Team.js | 109 + .../discord.js/src/structures/TeamMember.js | 65 + .../discord.js/src/structures/TextChannel.js | 153 + .../discord.js/src/structures/User.js | 343 + .../discord.js/src/structures/VoiceChannel.js | 150 + .../discord.js/src/structures/VoiceRegion.js | 52 + .../discord.js/src/structures/VoiceState.js | 213 + .../discord.js/src/structures/Webhook.js | 273 + .../src/structures/interfaces/Application.js | 125 + .../src/structures/interfaces/Collector.js | 281 + .../structures/interfaces/TextBasedChannel.js | 393 + .../discord.js/src/util/ActivityFlags.js | 38 + node_modules/discord.js/src/util/BitField.js | 164 + .../discord.js/src/util/Collection.js | 17 + node_modules/discord.js/src/util/Constants.js | 678 ++ .../discord.js/src/util/DataResolver.js | 153 + node_modules/discord.js/src/util/Intents.js | 83 + .../discord.js/src/util/LimitedCollection.js | 34 + .../discord.js/src/util/MessageFlags.js | 36 + .../discord.js/src/util/Permissions.js | 131 + node_modules/discord.js/src/util/Snowflake.js | 93 + node_modules/discord.js/src/util/Speaking.js | 33 + .../discord.js/src/util/Structures.js | 112 + .../discord.js/src/util/SystemChannelFlags.js | 40 + node_modules/discord.js/src/util/UserFlags.js | 55 + node_modules/discord.js/src/util/Util.js | 625 ++ node_modules/discord.js/typings/index.d.ts | 3255 +++++++ node_modules/discord.js/typings/index.ts | 53 + .../discord.js/webpack/discord.min.js | 2 + .../webpack/discord.min.js.LICENSE.txt | 6 + node_modules/end-of-stream/LICENSE | 21 + node_modules/end-of-stream/README.md | 54 + node_modules/end-of-stream/index.js | 94 + node_modules/end-of-stream/package.json | 37 + node_modules/event-target-shim/LICENSE | 22 + node_modules/event-target-shim/README.md | 293 + .../dist/event-target-shim.js | 871 ++ .../dist/event-target-shim.js.map | 1 + .../dist/event-target-shim.mjs | 862 ++ .../dist/event-target-shim.mjs.map | 1 + .../dist/event-target-shim.umd.js | 6 + .../dist/event-target-shim.umd.js.map | 1 + node_modules/event-target-shim/index.d.ts | 399 + node_modules/event-target-shim/package.json | 82 + node_modules/get-stream/buffer-stream.js | 52 + node_modules/get-stream/index.d.ts | 108 + node_modules/get-stream/index.js | 60 + node_modules/get-stream/license | 9 + node_modules/get-stream/package.json | 50 + node_modules/get-stream/readme.md | 124 + .../source/as-promise/create-rejection.d.ts | 2 + .../source/as-promise/create-rejection.js | 30 + .../got/dist/source/as-promise/index.d.ts | 3 + .../got/dist/source/as-promise/index.js | 175 + .../as-promise/normalize-arguments.d.ts | 3 + .../source/as-promise/normalize-arguments.js | 78 + .../dist/source/as-promise/parse-body.d.ts | 3 + .../got/dist/source/as-promise/parse-body.js | 25 + .../got/dist/source/as-promise/types.d.ts | 256 + .../got/dist/source/as-promise/types.js | 40 + .../source/core/calculate-retry-delay.d.ts | 5 + .../dist/source/core/calculate-retry-delay.js | 29 + node_modules/got/dist/source/core/index.d.ts | 1124 +++ node_modules/got/dist/source/core/index.js | 1491 +++ .../source/core/utils/dns-ip-version.d.ts | 5 + .../dist/source/core/utils/dns-ip-version.js | 17 + .../dist/source/core/utils/get-body-size.d.ts | 3 + .../dist/source/core/utils/get-body-size.js | 32 + .../dist/source/core/utils/get-buffer.d.ts | 4 + .../got/dist/source/core/utils/get-buffer.js | 16 + .../dist/source/core/utils/is-form-data.d.ts | 8 + .../dist/source/core/utils/is-form-data.js | 4 + .../source/core/utils/is-response-ok.d.ts | 2 + .../dist/source/core/utils/is-response-ok.js | 8 + .../source/core/utils/options-to-url.d.ts | 14 + .../dist/source/core/utils/options-to-url.js | 53 + .../dist/source/core/utils/proxy-events.d.ts | 3 + .../dist/source/core/utils/proxy-events.js | 17 + .../got/dist/source/core/utils/timed-out.d.ts | 29 + .../got/dist/source/core/utils/timed-out.js | 121 + .../got/dist/source/core/utils/unhandle.d.ts | 11 + .../got/dist/source/core/utils/unhandle.js | 22 + .../source/core/utils/url-to-options.d.ts | 15 + .../dist/source/core/utils/url-to-options.js | 24 + .../dist/source/core/utils/weakable-map.d.ts | 8 + .../dist/source/core/utils/weakable-map.js | 29 + node_modules/got/dist/source/create.d.ts | 5 + node_modules/got/dist/source/create.js | 240 + node_modules/got/dist/source/index.d.ts | 4 + node_modules/got/dist/source/index.js | 132 + node_modules/got/dist/source/types.d.ts | 342 + node_modules/got/dist/source/types.js | 2 + .../got/dist/source/utils/deep-freeze.d.ts | 1 + .../got/dist/source/utils/deep-freeze.js | 12 + .../source/utils/deprecation-warning.d.ts | 2 + .../dist/source/utils/deprecation-warning.js | 13 + node_modules/got/license | 9 + node_modules/got/package.json | 130 + node_modules/got/readme.md | 2476 +++++ node_modules/http-cache-semantics/LICENSE | 9 + node_modules/http-cache-semantics/README.md | 203 + node_modules/http-cache-semantics/index.js | 673 ++ .../http-cache-semantics/package.json | 24 + node_modules/http2-wrapper/LICENSE | 21 + node_modules/http2-wrapper/README.md | 470 + node_modules/http2-wrapper/package.json | 54 + node_modules/http2-wrapper/source/agent.js | 670 ++ node_modules/http2-wrapper/source/auto.js | 149 + .../http2-wrapper/source/client-request.js | 445 + .../http2-wrapper/source/incoming-message.js | 58 + node_modules/http2-wrapper/source/index.js | 28 + .../source/utils/calculate-server-name.js | 27 + .../http2-wrapper/source/utils/errors.js | 45 + .../source/utils/is-request-pseudo-header.js | 13 + .../source/utils/proxy-events.js | 7 + .../source/utils/url-to-options.js | 25 + node_modules/json-buffer/.travis.yml | 3 + node_modules/json-buffer/LICENSE | 22 + node_modules/json-buffer/README.md | 24 + node_modules/json-buffer/index.js | 58 + node_modules/json-buffer/package.json | 34 + node_modules/json-buffer/test/index.js | 63 + node_modules/keyv/LICENSE | 21 + node_modules/keyv/README.md | 288 + node_modules/keyv/package.json | 49 + node_modules/keyv/src/index.js | 111 + node_modules/lowercase-keys/index.d.ts | 16 + node_modules/lowercase-keys/index.js | 10 + node_modules/lowercase-keys/license | 9 + node_modules/lowercase-keys/package.json | 38 + node_modules/lowercase-keys/readme.md | 32 + node_modules/mime-db/HISTORY.md | 473 + node_modules/mime-db/LICENSE | 22 + node_modules/mime-db/README.md | 100 + node_modules/mime-db/db.json | 8323 +++++++++++++++++ node_modules/mime-db/index.js | 11 + node_modules/mime-db/package.json | 59 + node_modules/mime-types/HISTORY.md | 363 + node_modules/mime-types/LICENSE | 23 + node_modules/mime-types/README.md | 113 + node_modules/mime-types/index.js | 188 + node_modules/mime-types/package.json | 44 + node_modules/mimic-response/index.js | 32 + node_modules/mimic-response/license | 9 + node_modules/mimic-response/package.json | 37 + node_modules/mimic-response/readme.md | 54 + node_modules/node-fetch/CHANGELOG.md | 272 + node_modules/node-fetch/LICENSE.md | 22 + node_modules/node-fetch/README.md | 590 ++ node_modules/node-fetch/browser.js | 25 + node_modules/node-fetch/lib/index.es.js | 1640 ++++ node_modules/node-fetch/lib/index.js | 1649 ++++ node_modules/node-fetch/lib/index.mjs | 1638 ++++ node_modules/node-fetch/package.json | 66 + node_modules/normalize-url/index.d.ts | 216 + node_modules/normalize-url/index.js | 221 + node_modules/normalize-url/license | 9 + node_modules/normalize-url/package.json | 44 + node_modules/normalize-url/readme.md | 232 + node_modules/once/LICENSE | 15 + node_modules/once/README.md | 79 + node_modules/once/once.js | 42 + node_modules/once/package.json | 33 + node_modules/p-cancelable/index.d.ts | 176 + node_modules/p-cancelable/index.js | 111 + node_modules/p-cancelable/license | 9 + node_modules/p-cancelable/package.json | 49 + node_modules/p-cancelable/readme.md | 153 + node_modules/prism-media/LICENSE | 190 + node_modules/prism-media/README.md | 69 + node_modules/prism-media/package.json | 63 + node_modules/prism-media/src/core/FFmpeg.js | 160 + .../prism-media/src/core/VolumeTransformer.js | 128 + node_modules/prism-media/src/core/WebmBase.js | 218 + node_modules/prism-media/src/core/index.js | 9 + node_modules/prism-media/src/index.js | 5 + .../prism-media/src/opus/OggDemuxer.js | 138 + node_modules/prism-media/src/opus/Opus.js | 212 + .../prism-media/src/opus/WebmDemuxer.js | 24 + node_modules/prism-media/src/opus/index.js | 10 + node_modules/prism-media/src/util/loader.js | 13 + .../prism-media/src/vorbis/WebmDemuxer.js | 22 + node_modules/prism-media/src/vorbis/index.js | 8 + node_modules/prism-media/typings/index.d.ts | 43 + node_modules/prism-media/typings/opus.d.ts | 30 + node_modules/prism-media/typings/vorbis.d.ts | 5 + node_modules/pump/.travis.yml | 5 + node_modules/pump/LICENSE | 21 + node_modules/pump/README.md | 65 + node_modules/pump/index.js | 82 + node_modules/pump/package.json | 24 + node_modules/pump/test-browser.js | 66 + node_modules/pump/test-node.js | 53 + node_modules/quick-lru/index.d.ts | 97 + node_modules/quick-lru/index.js | 123 + node_modules/quick-lru/license | 9 + node_modules/quick-lru/package.json | 43 + node_modules/quick-lru/readme.md | 111 + node_modules/resolve-alpn/LICENSE | 22 + node_modules/resolve-alpn/README.md | 53 + node_modules/resolve-alpn/index.js | 33 + node_modules/resolve-alpn/package.json | 34 + node_modules/responselike/LICENSE | 19 + node_modules/responselike/README.md | 77 + node_modules/responselike/package.json | 38 + node_modules/responselike/src/index.js | 34 + node_modules/setimmediate/LICENSE.txt | 20 + node_modules/setimmediate/package.json | 30 + node_modules/setimmediate/setImmediate.js | 186 + node_modules/tweetnacl/AUTHORS.md | 27 + node_modules/tweetnacl/CHANGELOG.md | 283 + node_modules/tweetnacl/LICENSE | 24 + .../tweetnacl/PULL_REQUEST_TEMPLATE.md | 20 + node_modules/tweetnacl/README.md | 494 + node_modules/tweetnacl/nacl-fast.js | 2391 +++++ node_modules/tweetnacl/nacl-fast.min.js | 1 + node_modules/tweetnacl/nacl.d.ts | 98 + node_modules/tweetnacl/nacl.js | 1178 +++ node_modules/tweetnacl/nacl.min.js | 1 + node_modules/tweetnacl/package.json | 56 + node_modules/wrappy/LICENSE | 15 + node_modules/wrappy/README.md | 36 + node_modules/wrappy/package.json | 29 + node_modules/wrappy/wrappy.js | 33 + node_modules/ws/LICENSE | 21 + node_modules/ws/README.md | 496 + node_modules/ws/browser.js | 8 + node_modules/ws/index.js | 10 + node_modules/ws/lib/buffer-util.js | 129 + node_modules/ws/lib/constants.js | 10 + node_modules/ws/lib/event-target.js | 184 + node_modules/ws/lib/extension.js | 223 + node_modules/ws/lib/limiter.js | 55 + node_modules/ws/lib/permessage-deflate.js | 517 + node_modules/ws/lib/receiver.js | 507 + node_modules/ws/lib/sender.js | 405 + node_modules/ws/lib/stream.js | 165 + node_modules/ws/lib/validation.js | 104 + node_modules/ws/lib/websocket-server.js | 406 + node_modules/ws/lib/websocket.js | 943 ++ node_modules/ws/package.json | 56 + package-lock.json | 777 ++ package.json | 19 + 591 files changed, 96319 insertions(+) create mode 100644 commands/moderation/kick.js create mode 100644 commands/moderation/prune.js create mode 100644 commands/moderation/rolekick.js create mode 100644 commands/utility/args-info.js create mode 100644 commands/utility/help.js create mode 100644 commands/utility/reload.js create mode 100644 commands/utility/server.js create mode 100644 commands/utility/user-info.js create mode 100644 config.json create mode 100644 helpers/ai.js create mode 100644 helpers/leetspeak.js create mode 100644 helpers/makecard.js create mode 100644 helpers/steamer.js create mode 100644 helpers/urbaner.js create mode 100644 index.js create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/@discordjs/collection/LICENSE create mode 100644 node_modules/@discordjs/collection/README.md create mode 100644 node_modules/@discordjs/collection/dist/index.d.ts create mode 100644 node_modules/@discordjs/collection/dist/index.js create mode 100644 node_modules/@discordjs/collection/package.json create mode 100644 node_modules/@discordjs/form-data/License create mode 100644 node_modules/@discordjs/form-data/Readme.md create mode 100644 node_modules/@discordjs/form-data/index.d.ts create mode 100644 node_modules/@discordjs/form-data/lib/browser.js create mode 100644 node_modules/@discordjs/form-data/lib/form_data.js create mode 100644 node_modules/@discordjs/form-data/lib/populate.js create mode 100644 node_modules/@discordjs/form-data/package.json create mode 100644 node_modules/@sindresorhus/is/dist/index.d.ts create mode 100644 node_modules/@sindresorhus/is/dist/index.js create mode 100644 node_modules/@sindresorhus/is/dist/types.d.ts create mode 100644 node_modules/@sindresorhus/is/dist/types.js create mode 100644 node_modules/@sindresorhus/is/license create mode 100644 node_modules/@sindresorhus/is/package.json create mode 100644 node_modules/@sindresorhus/is/readme.md create mode 100644 node_modules/@szmarczak/http-timer/LICENSE create mode 100644 node_modules/@szmarczak/http-timer/README.md create mode 100644 node_modules/@szmarczak/http-timer/dist/source/index.d.ts create mode 100644 node_modules/@szmarczak/http-timer/dist/source/index.js create mode 100644 node_modules/@szmarczak/http-timer/package.json create mode 100644 node_modules/@types/cacheable-request/LICENSE create mode 100644 node_modules/@types/cacheable-request/README.md create mode 100644 node_modules/@types/cacheable-request/index.d.ts create mode 100644 node_modules/@types/cacheable-request/package.json create mode 100644 node_modules/@types/http-cache-semantics/LICENSE create mode 100644 node_modules/@types/http-cache-semantics/README.md create mode 100644 node_modules/@types/http-cache-semantics/index.d.ts create mode 100644 node_modules/@types/http-cache-semantics/package.json create mode 100644 node_modules/@types/keyv/LICENSE create mode 100644 node_modules/@types/keyv/README.md create mode 100644 node_modules/@types/keyv/index.d.ts create mode 100644 node_modules/@types/keyv/package.json create mode 100755 node_modules/@types/node/LICENSE create mode 100755 node_modules/@types/node/README.md create mode 100755 node_modules/@types/node/assert.d.ts create mode 100755 node_modules/@types/node/assert/strict.d.ts create mode 100755 node_modules/@types/node/async_hooks.d.ts create mode 100755 node_modules/@types/node/base.d.ts create mode 100755 node_modules/@types/node/buffer.d.ts create mode 100755 node_modules/@types/node/child_process.d.ts create mode 100755 node_modules/@types/node/cluster.d.ts create mode 100755 node_modules/@types/node/console.d.ts create mode 100755 node_modules/@types/node/constants.d.ts create mode 100755 node_modules/@types/node/crypto.d.ts create mode 100755 node_modules/@types/node/dgram.d.ts create mode 100755 node_modules/@types/node/dns.d.ts create mode 100755 node_modules/@types/node/dns/promises.d.ts create mode 100755 node_modules/@types/node/domain.d.ts create mode 100755 node_modules/@types/node/events.d.ts create mode 100755 node_modules/@types/node/fs.d.ts create mode 100755 node_modules/@types/node/fs/promises.d.ts create mode 100755 node_modules/@types/node/globals.d.ts create mode 100755 node_modules/@types/node/globals.global.d.ts create mode 100755 node_modules/@types/node/http.d.ts create mode 100755 node_modules/@types/node/http2.d.ts create mode 100755 node_modules/@types/node/https.d.ts create mode 100755 node_modules/@types/node/index.d.ts create mode 100755 node_modules/@types/node/inspector.d.ts create mode 100755 node_modules/@types/node/module.d.ts create mode 100755 node_modules/@types/node/net.d.ts create mode 100755 node_modules/@types/node/os.d.ts create mode 100755 node_modules/@types/node/package.json create mode 100755 node_modules/@types/node/path.d.ts create mode 100755 node_modules/@types/node/perf_hooks.d.ts create mode 100755 node_modules/@types/node/process.d.ts create mode 100755 node_modules/@types/node/punycode.d.ts create mode 100755 node_modules/@types/node/querystring.d.ts create mode 100755 node_modules/@types/node/readline.d.ts create mode 100755 node_modules/@types/node/repl.d.ts create mode 100755 node_modules/@types/node/stream.d.ts create mode 100755 node_modules/@types/node/stream/promises.d.ts create mode 100755 node_modules/@types/node/string_decoder.d.ts create mode 100755 node_modules/@types/node/timers.d.ts create mode 100755 node_modules/@types/node/timers/promises.d.ts create mode 100755 node_modules/@types/node/tls.d.ts create mode 100755 node_modules/@types/node/trace_events.d.ts create mode 100755 node_modules/@types/node/ts3.6/assert.d.ts create mode 100755 node_modules/@types/node/ts3.6/base.d.ts create mode 100755 node_modules/@types/node/ts3.6/index.d.ts create mode 100755 node_modules/@types/node/tty.d.ts create mode 100755 node_modules/@types/node/url.d.ts create mode 100755 node_modules/@types/node/util.d.ts create mode 100755 node_modules/@types/node/v8.d.ts create mode 100755 node_modules/@types/node/vm.d.ts create mode 100755 node_modules/@types/node/wasi.d.ts create mode 100755 node_modules/@types/node/worker_threads.d.ts create mode 100755 node_modules/@types/node/zlib.d.ts create mode 100644 node_modules/@types/responselike/LICENSE create mode 100644 node_modules/@types/responselike/README.md create mode 100644 node_modules/@types/responselike/index.d.ts create mode 100644 node_modules/@types/responselike/package.json create mode 100644 node_modules/abort-controller/LICENSE create mode 100644 node_modules/abort-controller/README.md create mode 100644 node_modules/abort-controller/browser.js create mode 100644 node_modules/abort-controller/browser.mjs create mode 100644 node_modules/abort-controller/dist/abort-controller.d.ts create mode 100644 node_modules/abort-controller/dist/abort-controller.js create mode 100644 node_modules/abort-controller/dist/abort-controller.js.map create mode 100644 node_modules/abort-controller/dist/abort-controller.mjs create mode 100644 node_modules/abort-controller/dist/abort-controller.mjs.map create mode 100644 node_modules/abort-controller/dist/abort-controller.umd.js create mode 100644 node_modules/abort-controller/dist/abort-controller.umd.js.map create mode 100644 node_modules/abort-controller/package.json create mode 100644 node_modules/abort-controller/polyfill.js create mode 100644 node_modules/abort-controller/polyfill.mjs create mode 100644 node_modules/asynckit/LICENSE create mode 100644 node_modules/asynckit/README.md create mode 100644 node_modules/asynckit/bench.js create mode 100644 node_modules/asynckit/index.js create mode 100644 node_modules/asynckit/lib/abort.js create mode 100644 node_modules/asynckit/lib/async.js create mode 100644 node_modules/asynckit/lib/defer.js create mode 100644 node_modules/asynckit/lib/iterate.js create mode 100644 node_modules/asynckit/lib/readable_asynckit.js create mode 100644 node_modules/asynckit/lib/readable_parallel.js create mode 100644 node_modules/asynckit/lib/readable_serial.js create mode 100644 node_modules/asynckit/lib/readable_serial_ordered.js create mode 100644 node_modules/asynckit/lib/state.js create mode 100644 node_modules/asynckit/lib/streamify.js create mode 100644 node_modules/asynckit/lib/terminator.js create mode 100644 node_modules/asynckit/package.json create mode 100644 node_modules/asynckit/parallel.js create mode 100644 node_modules/asynckit/serial.js create mode 100644 node_modules/asynckit/serialOrdered.js create mode 100644 node_modules/asynckit/stream.js create mode 100755 node_modules/cacheable-lookup/LICENSE create mode 100755 node_modules/cacheable-lookup/README.md create mode 100755 node_modules/cacheable-lookup/index.d.ts create mode 100755 node_modules/cacheable-lookup/package.json create mode 100755 node_modules/cacheable-lookup/source/index.js create mode 100644 node_modules/cacheable-request/LICENSE create mode 100644 node_modules/cacheable-request/README.md create mode 100644 node_modules/cacheable-request/package.json create mode 100644 node_modules/cacheable-request/src/index.js create mode 100644 node_modules/clone-response/LICENSE create mode 100644 node_modules/clone-response/README.md create mode 100644 node_modules/clone-response/package.json create mode 100644 node_modules/clone-response/src/index.js create mode 100644 node_modules/combined-stream/License create mode 100644 node_modules/combined-stream/Readme.md create mode 100644 node_modules/combined-stream/lib/combined_stream.js create mode 100644 node_modules/combined-stream/package.json create mode 100644 node_modules/combined-stream/yarn.lock create mode 100644 node_modules/decompress-response/index.d.ts create mode 100644 node_modules/decompress-response/index.js create mode 100644 node_modules/decompress-response/license create mode 100644 node_modules/decompress-response/node_modules/mimic-response/index.d.ts create mode 100644 node_modules/decompress-response/node_modules/mimic-response/index.js create mode 100644 node_modules/decompress-response/node_modules/mimic-response/license create mode 100644 node_modules/decompress-response/node_modules/mimic-response/package.json create mode 100644 node_modules/decompress-response/node_modules/mimic-response/readme.md create mode 100644 node_modules/decompress-response/package.json create mode 100644 node_modules/decompress-response/readme.md create mode 100644 node_modules/defer-to-connect/LICENSE create mode 100644 node_modules/defer-to-connect/README.md create mode 100644 node_modules/defer-to-connect/dist/source/index.d.ts create mode 100644 node_modules/defer-to-connect/dist/source/index.js create mode 100644 node_modules/defer-to-connect/package.json create mode 100644 node_modules/delayed-stream/.npmignore create mode 100644 node_modules/delayed-stream/License create mode 100644 node_modules/delayed-stream/Makefile create mode 100644 node_modules/delayed-stream/Readme.md create mode 100644 node_modules/delayed-stream/lib/delayed_stream.js create mode 100644 node_modules/delayed-stream/package.json create mode 100644 node_modules/discord.js/.tern-project create mode 100644 node_modules/discord.js/LICENSE create mode 100644 node_modules/discord.js/README.md create mode 100644 node_modules/discord.js/esm/discord.mjs create mode 100644 node_modules/discord.js/jsdoc.json create mode 100644 node_modules/discord.js/package.json create mode 100644 node_modules/discord.js/src/WebSocket.js create mode 100644 node_modules/discord.js/src/client/BaseClient.js create mode 100644 node_modules/discord.js/src/client/Client.js create mode 100644 node_modules/discord.js/src/client/WebhookClient.js create mode 100644 node_modules/discord.js/src/client/actions/Action.js create mode 100644 node_modules/discord.js/src/client/actions/ActionsManager.js create mode 100644 node_modules/discord.js/src/client/actions/ChannelCreate.js create mode 100644 node_modules/discord.js/src/client/actions/ChannelDelete.js create mode 100644 node_modules/discord.js/src/client/actions/ChannelUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildBanRemove.js create mode 100644 node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildDelete.js create mode 100644 node_modules/discord.js/src/client/actions/GuildEmojiCreate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildEmojiDelete.js create mode 100644 node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildMemberRemove.js create mode 100644 node_modules/discord.js/src/client/actions/GuildMemberUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildRoleCreate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildRoleDelete.js create mode 100644 node_modules/discord.js/src/client/actions/GuildRoleUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/GuildUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/InviteCreate.js create mode 100644 node_modules/discord.js/src/client/actions/InviteDelete.js create mode 100644 node_modules/discord.js/src/client/actions/MessageCreate.js create mode 100644 node_modules/discord.js/src/client/actions/MessageDelete.js create mode 100644 node_modules/discord.js/src/client/actions/MessageDeleteBulk.js create mode 100644 node_modules/discord.js/src/client/actions/MessageReactionAdd.js create mode 100644 node_modules/discord.js/src/client/actions/MessageReactionRemove.js create mode 100644 node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js create mode 100644 node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js create mode 100644 node_modules/discord.js/src/client/actions/MessageUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/PresenceUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/TypingStart.js create mode 100644 node_modules/discord.js/src/client/actions/UserUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/VoiceStateUpdate.js create mode 100644 node_modules/discord.js/src/client/actions/WebhooksUpdate.js create mode 100644 node_modules/discord.js/src/client/voice/ClientVoiceManager.js create mode 100644 node_modules/discord.js/src/client/voice/VoiceBroadcast.js create mode 100644 node_modules/discord.js/src/client/voice/VoiceConnection.js create mode 100644 node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js create mode 100644 node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js create mode 100644 node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js create mode 100644 node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js create mode 100644 node_modules/discord.js/src/client/voice/player/AudioPlayer.js create mode 100644 node_modules/discord.js/src/client/voice/player/BasePlayer.js create mode 100644 node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js create mode 100644 node_modules/discord.js/src/client/voice/receiver/PacketHandler.js create mode 100644 node_modules/discord.js/src/client/voice/receiver/Receiver.js create mode 100644 node_modules/discord.js/src/client/voice/util/PlayInterface.js create mode 100644 node_modules/discord.js/src/client/voice/util/Secretbox.js create mode 100644 node_modules/discord.js/src/client/voice/util/Silence.js create mode 100644 node_modules/discord.js/src/client/voice/util/VolumeInterface.js create mode 100644 node_modules/discord.js/src/client/websocket/WebSocketManager.js create mode 100644 node_modules/discord.js/src/client/websocket/WebSocketShard.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/READY.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/RESUMED.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js create mode 100644 node_modules/discord.js/src/client/websocket/handlers/index.js create mode 100644 node_modules/discord.js/src/errors/DJSError.js create mode 100644 node_modules/discord.js/src/errors/Messages.js create mode 100644 node_modules/discord.js/src/errors/index.js create mode 100644 node_modules/discord.js/src/index.js create mode 100644 node_modules/discord.js/src/managers/BaseManager.js create mode 100644 node_modules/discord.js/src/managers/ChannelManager.js create mode 100644 node_modules/discord.js/src/managers/GuildChannelManager.js create mode 100644 node_modules/discord.js/src/managers/GuildEmojiManager.js create mode 100644 node_modules/discord.js/src/managers/GuildEmojiRoleManager.js create mode 100644 node_modules/discord.js/src/managers/GuildManager.js create mode 100644 node_modules/discord.js/src/managers/GuildMemberManager.js create mode 100644 node_modules/discord.js/src/managers/GuildMemberRoleManager.js create mode 100644 node_modules/discord.js/src/managers/MessageManager.js create mode 100644 node_modules/discord.js/src/managers/PresenceManager.js create mode 100644 node_modules/discord.js/src/managers/ReactionManager.js create mode 100644 node_modules/discord.js/src/managers/ReactionUserManager.js create mode 100644 node_modules/discord.js/src/managers/RoleManager.js create mode 100644 node_modules/discord.js/src/managers/UserManager.js create mode 100644 node_modules/discord.js/src/managers/VoiceStateManager.js create mode 100644 node_modules/discord.js/src/rest/APIRequest.js create mode 100644 node_modules/discord.js/src/rest/APIRouter.js create mode 100644 node_modules/discord.js/src/rest/AsyncQueue.js create mode 100644 node_modules/discord.js/src/rest/DiscordAPIError.js create mode 100644 node_modules/discord.js/src/rest/HTTPError.js create mode 100644 node_modules/discord.js/src/rest/RESTManager.js create mode 100644 node_modules/discord.js/src/rest/RequestHandler.js create mode 100644 node_modules/discord.js/src/sharding/Shard.js create mode 100644 node_modules/discord.js/src/sharding/ShardClientUtil.js create mode 100644 node_modules/discord.js/src/sharding/ShardingManager.js create mode 100644 node_modules/discord.js/src/structures/APIMessage.js create mode 100644 node_modules/discord.js/src/structures/Base.js create mode 100644 node_modules/discord.js/src/structures/BaseGuildEmoji.js create mode 100644 node_modules/discord.js/src/structures/CategoryChannel.js create mode 100644 node_modules/discord.js/src/structures/Channel.js create mode 100644 node_modules/discord.js/src/structures/ClientApplication.js create mode 100644 node_modules/discord.js/src/structures/ClientPresence.js create mode 100644 node_modules/discord.js/src/structures/ClientUser.js create mode 100644 node_modules/discord.js/src/structures/DMChannel.js create mode 100644 node_modules/discord.js/src/structures/Emoji.js create mode 100644 node_modules/discord.js/src/structures/Guild.js create mode 100644 node_modules/discord.js/src/structures/GuildAuditLogs.js create mode 100644 node_modules/discord.js/src/structures/GuildChannel.js create mode 100644 node_modules/discord.js/src/structures/GuildEmoji.js create mode 100644 node_modules/discord.js/src/structures/GuildMember.js create mode 100644 node_modules/discord.js/src/structures/GuildPreview.js create mode 100644 node_modules/discord.js/src/structures/GuildPreviewEmoji.js create mode 100644 node_modules/discord.js/src/structures/GuildTemplate.js create mode 100644 node_modules/discord.js/src/structures/Integration.js create mode 100644 node_modules/discord.js/src/structures/IntegrationApplication.js create mode 100644 node_modules/discord.js/src/structures/Invite.js create mode 100644 node_modules/discord.js/src/structures/Message.js create mode 100644 node_modules/discord.js/src/structures/MessageAttachment.js create mode 100644 node_modules/discord.js/src/structures/MessageCollector.js create mode 100644 node_modules/discord.js/src/structures/MessageEmbed.js create mode 100644 node_modules/discord.js/src/structures/MessageMentions.js create mode 100644 node_modules/discord.js/src/structures/MessageReaction.js create mode 100644 node_modules/discord.js/src/structures/NewsChannel.js create mode 100644 node_modules/discord.js/src/structures/PartialGroupDMChannel.js create mode 100644 node_modules/discord.js/src/structures/PermissionOverwrites.js create mode 100644 node_modules/discord.js/src/structures/Presence.js create mode 100644 node_modules/discord.js/src/structures/ReactionCollector.js create mode 100644 node_modules/discord.js/src/structures/ReactionEmoji.js create mode 100644 node_modules/discord.js/src/structures/Role.js create mode 100644 node_modules/discord.js/src/structures/StoreChannel.js create mode 100644 node_modules/discord.js/src/structures/Team.js create mode 100644 node_modules/discord.js/src/structures/TeamMember.js create mode 100644 node_modules/discord.js/src/structures/TextChannel.js create mode 100644 node_modules/discord.js/src/structures/User.js create mode 100644 node_modules/discord.js/src/structures/VoiceChannel.js create mode 100644 node_modules/discord.js/src/structures/VoiceRegion.js create mode 100644 node_modules/discord.js/src/structures/VoiceState.js create mode 100644 node_modules/discord.js/src/structures/Webhook.js create mode 100644 node_modules/discord.js/src/structures/interfaces/Application.js create mode 100644 node_modules/discord.js/src/structures/interfaces/Collector.js create mode 100644 node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js create mode 100644 node_modules/discord.js/src/util/ActivityFlags.js create mode 100644 node_modules/discord.js/src/util/BitField.js create mode 100644 node_modules/discord.js/src/util/Collection.js create mode 100644 node_modules/discord.js/src/util/Constants.js create mode 100644 node_modules/discord.js/src/util/DataResolver.js create mode 100644 node_modules/discord.js/src/util/Intents.js create mode 100644 node_modules/discord.js/src/util/LimitedCollection.js create mode 100644 node_modules/discord.js/src/util/MessageFlags.js create mode 100644 node_modules/discord.js/src/util/Permissions.js create mode 100644 node_modules/discord.js/src/util/Snowflake.js create mode 100644 node_modules/discord.js/src/util/Speaking.js create mode 100644 node_modules/discord.js/src/util/Structures.js create mode 100644 node_modules/discord.js/src/util/SystemChannelFlags.js create mode 100644 node_modules/discord.js/src/util/UserFlags.js create mode 100644 node_modules/discord.js/src/util/Util.js create mode 100644 node_modules/discord.js/typings/index.d.ts create mode 100644 node_modules/discord.js/typings/index.ts create mode 100644 node_modules/discord.js/webpack/discord.min.js create mode 100644 node_modules/discord.js/webpack/discord.min.js.LICENSE.txt create mode 100644 node_modules/end-of-stream/LICENSE create mode 100644 node_modules/end-of-stream/README.md create mode 100644 node_modules/end-of-stream/index.js create mode 100644 node_modules/end-of-stream/package.json create mode 100644 node_modules/event-target-shim/LICENSE create mode 100644 node_modules/event-target-shim/README.md create mode 100644 node_modules/event-target-shim/dist/event-target-shim.js create mode 100644 node_modules/event-target-shim/dist/event-target-shim.js.map create mode 100644 node_modules/event-target-shim/dist/event-target-shim.mjs create mode 100644 node_modules/event-target-shim/dist/event-target-shim.mjs.map create mode 100644 node_modules/event-target-shim/dist/event-target-shim.umd.js create mode 100644 node_modules/event-target-shim/dist/event-target-shim.umd.js.map create mode 100644 node_modules/event-target-shim/index.d.ts create mode 100644 node_modules/event-target-shim/package.json create mode 100644 node_modules/get-stream/buffer-stream.js create mode 100644 node_modules/get-stream/index.d.ts create mode 100644 node_modules/get-stream/index.js create mode 100644 node_modules/get-stream/license create mode 100644 node_modules/get-stream/package.json create mode 100644 node_modules/get-stream/readme.md create mode 100644 node_modules/got/dist/source/as-promise/create-rejection.d.ts create mode 100644 node_modules/got/dist/source/as-promise/create-rejection.js create mode 100644 node_modules/got/dist/source/as-promise/index.d.ts create mode 100644 node_modules/got/dist/source/as-promise/index.js create mode 100644 node_modules/got/dist/source/as-promise/normalize-arguments.d.ts create mode 100644 node_modules/got/dist/source/as-promise/normalize-arguments.js create mode 100644 node_modules/got/dist/source/as-promise/parse-body.d.ts create mode 100644 node_modules/got/dist/source/as-promise/parse-body.js create mode 100644 node_modules/got/dist/source/as-promise/types.d.ts create mode 100644 node_modules/got/dist/source/as-promise/types.js create mode 100644 node_modules/got/dist/source/core/calculate-retry-delay.d.ts create mode 100644 node_modules/got/dist/source/core/calculate-retry-delay.js create mode 100644 node_modules/got/dist/source/core/index.d.ts create mode 100644 node_modules/got/dist/source/core/index.js create mode 100644 node_modules/got/dist/source/core/utils/dns-ip-version.d.ts create mode 100644 node_modules/got/dist/source/core/utils/dns-ip-version.js create mode 100644 node_modules/got/dist/source/core/utils/get-body-size.d.ts create mode 100644 node_modules/got/dist/source/core/utils/get-body-size.js create mode 100644 node_modules/got/dist/source/core/utils/get-buffer.d.ts create mode 100644 node_modules/got/dist/source/core/utils/get-buffer.js create mode 100644 node_modules/got/dist/source/core/utils/is-form-data.d.ts create mode 100644 node_modules/got/dist/source/core/utils/is-form-data.js create mode 100644 node_modules/got/dist/source/core/utils/is-response-ok.d.ts create mode 100644 node_modules/got/dist/source/core/utils/is-response-ok.js create mode 100644 node_modules/got/dist/source/core/utils/options-to-url.d.ts create mode 100644 node_modules/got/dist/source/core/utils/options-to-url.js create mode 100644 node_modules/got/dist/source/core/utils/proxy-events.d.ts create mode 100644 node_modules/got/dist/source/core/utils/proxy-events.js create mode 100644 node_modules/got/dist/source/core/utils/timed-out.d.ts create mode 100644 node_modules/got/dist/source/core/utils/timed-out.js create mode 100644 node_modules/got/dist/source/core/utils/unhandle.d.ts create mode 100644 node_modules/got/dist/source/core/utils/unhandle.js create mode 100644 node_modules/got/dist/source/core/utils/url-to-options.d.ts create mode 100644 node_modules/got/dist/source/core/utils/url-to-options.js create mode 100644 node_modules/got/dist/source/core/utils/weakable-map.d.ts create mode 100644 node_modules/got/dist/source/core/utils/weakable-map.js create mode 100644 node_modules/got/dist/source/create.d.ts create mode 100644 node_modules/got/dist/source/create.js create mode 100644 node_modules/got/dist/source/index.d.ts create mode 100644 node_modules/got/dist/source/index.js create mode 100644 node_modules/got/dist/source/types.d.ts create mode 100644 node_modules/got/dist/source/types.js create mode 100644 node_modules/got/dist/source/utils/deep-freeze.d.ts create mode 100644 node_modules/got/dist/source/utils/deep-freeze.js create mode 100644 node_modules/got/dist/source/utils/deprecation-warning.d.ts create mode 100644 node_modules/got/dist/source/utils/deprecation-warning.js create mode 100644 node_modules/got/license create mode 100644 node_modules/got/package.json create mode 100644 node_modules/got/readme.md create mode 100644 node_modules/http-cache-semantics/LICENSE create mode 100644 node_modules/http-cache-semantics/README.md create mode 100644 node_modules/http-cache-semantics/index.js create mode 100644 node_modules/http-cache-semantics/package.json create mode 100644 node_modules/http2-wrapper/LICENSE create mode 100644 node_modules/http2-wrapper/README.md create mode 100644 node_modules/http2-wrapper/package.json create mode 100644 node_modules/http2-wrapper/source/agent.js create mode 100644 node_modules/http2-wrapper/source/auto.js create mode 100644 node_modules/http2-wrapper/source/client-request.js create mode 100644 node_modules/http2-wrapper/source/incoming-message.js create mode 100644 node_modules/http2-wrapper/source/index.js create mode 100644 node_modules/http2-wrapper/source/utils/calculate-server-name.js create mode 100644 node_modules/http2-wrapper/source/utils/errors.js create mode 100644 node_modules/http2-wrapper/source/utils/is-request-pseudo-header.js create mode 100644 node_modules/http2-wrapper/source/utils/proxy-events.js create mode 100644 node_modules/http2-wrapper/source/utils/url-to-options.js create mode 100644 node_modules/json-buffer/.travis.yml create mode 100644 node_modules/json-buffer/LICENSE create mode 100644 node_modules/json-buffer/README.md create mode 100644 node_modules/json-buffer/index.js create mode 100644 node_modules/json-buffer/package.json create mode 100644 node_modules/json-buffer/test/index.js create mode 100644 node_modules/keyv/LICENSE create mode 100644 node_modules/keyv/README.md create mode 100644 node_modules/keyv/package.json create mode 100644 node_modules/keyv/src/index.js create mode 100644 node_modules/lowercase-keys/index.d.ts create mode 100644 node_modules/lowercase-keys/index.js create mode 100644 node_modules/lowercase-keys/license create mode 100644 node_modules/lowercase-keys/package.json create mode 100644 node_modules/lowercase-keys/readme.md create mode 100644 node_modules/mime-db/HISTORY.md create mode 100644 node_modules/mime-db/LICENSE create mode 100644 node_modules/mime-db/README.md create mode 100644 node_modules/mime-db/db.json create mode 100644 node_modules/mime-db/index.js create mode 100644 node_modules/mime-db/package.json create mode 100644 node_modules/mime-types/HISTORY.md create mode 100644 node_modules/mime-types/LICENSE create mode 100644 node_modules/mime-types/README.md create mode 100644 node_modules/mime-types/index.js create mode 100644 node_modules/mime-types/package.json create mode 100644 node_modules/mimic-response/index.js create mode 100644 node_modules/mimic-response/license create mode 100644 node_modules/mimic-response/package.json create mode 100644 node_modules/mimic-response/readme.md create mode 100644 node_modules/node-fetch/CHANGELOG.md create mode 100644 node_modules/node-fetch/LICENSE.md create mode 100644 node_modules/node-fetch/README.md create mode 100644 node_modules/node-fetch/browser.js create mode 100644 node_modules/node-fetch/lib/index.es.js create mode 100644 node_modules/node-fetch/lib/index.js create mode 100644 node_modules/node-fetch/lib/index.mjs create mode 100644 node_modules/node-fetch/package.json create mode 100644 node_modules/normalize-url/index.d.ts create mode 100644 node_modules/normalize-url/index.js create mode 100644 node_modules/normalize-url/license create mode 100644 node_modules/normalize-url/package.json create mode 100644 node_modules/normalize-url/readme.md create mode 100644 node_modules/once/LICENSE create mode 100644 node_modules/once/README.md create mode 100644 node_modules/once/once.js create mode 100644 node_modules/once/package.json create mode 100644 node_modules/p-cancelable/index.d.ts create mode 100644 node_modules/p-cancelable/index.js create mode 100644 node_modules/p-cancelable/license create mode 100644 node_modules/p-cancelable/package.json create mode 100644 node_modules/p-cancelable/readme.md create mode 100644 node_modules/prism-media/LICENSE create mode 100644 node_modules/prism-media/README.md create mode 100644 node_modules/prism-media/package.json create mode 100644 node_modules/prism-media/src/core/FFmpeg.js create mode 100644 node_modules/prism-media/src/core/VolumeTransformer.js create mode 100644 node_modules/prism-media/src/core/WebmBase.js create mode 100644 node_modules/prism-media/src/core/index.js create mode 100644 node_modules/prism-media/src/index.js create mode 100644 node_modules/prism-media/src/opus/OggDemuxer.js create mode 100644 node_modules/prism-media/src/opus/Opus.js create mode 100644 node_modules/prism-media/src/opus/WebmDemuxer.js create mode 100644 node_modules/prism-media/src/opus/index.js create mode 100644 node_modules/prism-media/src/util/loader.js create mode 100644 node_modules/prism-media/src/vorbis/WebmDemuxer.js create mode 100644 node_modules/prism-media/src/vorbis/index.js create mode 100644 node_modules/prism-media/typings/index.d.ts create mode 100644 node_modules/prism-media/typings/opus.d.ts create mode 100644 node_modules/prism-media/typings/vorbis.d.ts create mode 100644 node_modules/pump/.travis.yml create mode 100644 node_modules/pump/LICENSE create mode 100644 node_modules/pump/README.md create mode 100644 node_modules/pump/index.js create mode 100644 node_modules/pump/package.json create mode 100644 node_modules/pump/test-browser.js create mode 100644 node_modules/pump/test-node.js create mode 100644 node_modules/quick-lru/index.d.ts create mode 100644 node_modules/quick-lru/index.js create mode 100644 node_modules/quick-lru/license create mode 100644 node_modules/quick-lru/package.json create mode 100644 node_modules/quick-lru/readme.md create mode 100644 node_modules/resolve-alpn/LICENSE create mode 100644 node_modules/resolve-alpn/README.md create mode 100644 node_modules/resolve-alpn/index.js create mode 100644 node_modules/resolve-alpn/package.json create mode 100644 node_modules/responselike/LICENSE create mode 100644 node_modules/responselike/README.md create mode 100644 node_modules/responselike/package.json create mode 100644 node_modules/responselike/src/index.js create mode 100644 node_modules/setimmediate/LICENSE.txt create mode 100644 node_modules/setimmediate/package.json create mode 100644 node_modules/setimmediate/setImmediate.js create mode 100644 node_modules/tweetnacl/AUTHORS.md create mode 100644 node_modules/tweetnacl/CHANGELOG.md create mode 100644 node_modules/tweetnacl/LICENSE create mode 100644 node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md create mode 100644 node_modules/tweetnacl/README.md create mode 100644 node_modules/tweetnacl/nacl-fast.js create mode 100644 node_modules/tweetnacl/nacl-fast.min.js create mode 100644 node_modules/tweetnacl/nacl.d.ts create mode 100644 node_modules/tweetnacl/nacl.js create mode 100644 node_modules/tweetnacl/nacl.min.js create mode 100644 node_modules/tweetnacl/package.json create mode 100644 node_modules/wrappy/LICENSE create mode 100644 node_modules/wrappy/README.md create mode 100644 node_modules/wrappy/package.json create mode 100644 node_modules/wrappy/wrappy.js create mode 100644 node_modules/ws/LICENSE create mode 100644 node_modules/ws/README.md create mode 100644 node_modules/ws/browser.js create mode 100644 node_modules/ws/index.js create mode 100644 node_modules/ws/lib/buffer-util.js create mode 100644 node_modules/ws/lib/constants.js create mode 100644 node_modules/ws/lib/event-target.js create mode 100644 node_modules/ws/lib/extension.js create mode 100644 node_modules/ws/lib/limiter.js create mode 100644 node_modules/ws/lib/permessage-deflate.js create mode 100644 node_modules/ws/lib/receiver.js create mode 100644 node_modules/ws/lib/sender.js create mode 100644 node_modules/ws/lib/stream.js create mode 100644 node_modules/ws/lib/validation.js create mode 100644 node_modules/ws/lib/websocket-server.js create mode 100644 node_modules/ws/lib/websocket.js create mode 100644 node_modules/ws/package.json create mode 100644 package-lock.json create mode 100644 package.json diff --git a/commands/moderation/kick.js b/commands/moderation/kick.js new file mode 100644 index 0000000..5e76497 --- /dev/null +++ b/commands/moderation/kick.js @@ -0,0 +1,15 @@ +module.exports = { + name: 'kick', + description: 'Tag a member and kick them (but not really).', + guildOnly: true, + permissions: 'KICK_MEMBERS', + execute(message) { + if (!message.mentions.users.size) { + return message.reply('you need to tag a user in order to kick them!'); + } + + const taggedUser = message.mentions.users.first(); + + message.channel.send(`You wanted to kick: ${taggedUser.username}`); + }, +}; diff --git a/commands/moderation/prune.js b/commands/moderation/prune.js new file mode 100644 index 0000000..fde6851 --- /dev/null +++ b/commands/moderation/prune.js @@ -0,0 +1,19 @@ +module.exports = { + name: 'prune', + description: 'Prune up to 99 messages.', + permissions: 'MANAGE_MESSAGES', + execute(message, args) { + const amount = parseInt(args[0]) + 1; + + if (isNaN(amount)) { + return message.reply('that doesn\'t seem to be a valid number.'); + } else if (amount <= 1 || amount > 100) { + return message.reply('you need to input a number between 1 and 99.'); + } + + message.channel.bulkDelete(amount, true).catch(err => { + console.error(err); + message.channel.send('there was an error trying to prune messages in this channel!'); + }); + }, +}; diff --git a/commands/moderation/rolekick.js b/commands/moderation/rolekick.js new file mode 100644 index 0000000..c52c828 --- /dev/null +++ b/commands/moderation/rolekick.js @@ -0,0 +1,23 @@ +module.exports = { + name: 'rolekick', + description: 'kick an entire role worth of peeps.', + guildOnly: true, + permissions: 'KICK_MEMBERS', + execute(message, args) { + console.log('fetching roles') + message.guild.roles.fetch({cache: true}) + console.log('fetching members') + message.guild.members.fetch({cache: true}) + .then() + const roleID = message.content.slice(13, message.content.length-1) + console.log(roleID) + let membersWithRole = message.guild.roles.cache.get(roleID).members.map(member => member.id); + for(i=0;i command.name).join(', ')); + data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`); + + return message.author.send(data, { split: true }) + .then(() => { + if (message.channel.type === 'dm') return; + message.reply('I\'ve sent you a DM with all my commands!'); + }) + .catch(error => { + console.error(`Could not send help DM to ${message.author.tag}.\n`, error); + message.reply('it seems like I can\'t DM you!'); + }); + } + + const name = args[0].toLowerCase(); + const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name)); + + if (!command) { + return message.reply('that\'s not a valid command!'); + } + + data.push(`**Name:** ${command.name}`); + + if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`); + if (command.description) data.push(`**Description:** ${command.description}`); + if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`); + + data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`); + + message.channel.send(data, { split: true }); + }, +}; diff --git a/commands/utility/reload.js b/commands/utility/reload.js new file mode 100644 index 0000000..ae79965 --- /dev/null +++ b/commands/utility/reload.js @@ -0,0 +1,30 @@ +const fs = require('fs'); + +module.exports = { + name: 'reload', + description: 'Reloads a command', + args: true, + execute(message, args) { + const commandName = args[0].toLowerCase(); + const command = message.client.commands.get(commandName) + || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + if (!command) { + return message.channel.send(`There is no command with name or alias \`${commandName}\`, ${message.author}!`); + } + + const commandFolders = fs.readdirSync('./commands'); + const folderName = commandFolders.find(folder => fs.readdirSync(`./commands/${folder}`).includes(`${commandName}.js`)); + + delete require.cache[require.resolve(`../${folderName}/${command.name}.js`)]; + + try { + const newCommand = require(`../${folderName}/${command.name}.js`); + message.client.commands.set(newCommand.name, newCommand); + message.channel.send(`Command \`${command.name}\` was reloaded!`); + } catch (error) { + console.error(error); + message.channel.send(`There was an error while reloading a command \`${command.name}\`:\n\`${error.message}\``); + } + }, +}; diff --git a/commands/utility/server.js b/commands/utility/server.js new file mode 100644 index 0000000..d8e6de8 --- /dev/null +++ b/commands/utility/server.js @@ -0,0 +1,7 @@ +module.exports = { + name: 'server', + description: 'Display info about this server.', + execute(message) { + message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); + }, +}; diff --git a/commands/utility/user-info.js b/commands/utility/user-info.js new file mode 100644 index 0000000..a1f5664 --- /dev/null +++ b/commands/utility/user-info.js @@ -0,0 +1,7 @@ +module.exports = { + name: 'user-info', + description: 'Display info about yourself.', + execute(message) { + message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); + }, +}; diff --git a/config.json b/config.json new file mode 100644 index 0000000..b800693 --- /dev/null +++ b/config.json @@ -0,0 +1,4 @@ +{ + "prefix": "!", + "token": "ODE5ODE2NTI3MTc1NjE0NDY1.YEsHow.NXPPlrryk19LIisKD8GF58ejzH8" +} diff --git a/helpers/ai.js b/helpers/ai.js new file mode 100644 index 0000000..048acd2 --- /dev/null +++ b/helpers/ai.js @@ -0,0 +1,61 @@ +const tf = require('@tensorflow/tfjs') +const tfn = require('@tensorflow/tfjs-node') +const mobilenet = require('@tensorflow-models/mobilenet'); +const canvasAPP = require('canvas'); +const cocoSsd = require('@tensorflow-models/coco-ssd'); + + +async function drawBoxes(img){ + var image = await canvasAPP.loadImage(img) + const canvas = await canvasAPP.createCanvas(image.width, image.height) + const ctx = await canvas.getContext('2d') + await ctx.drawImage(image, 0, 0) + const model = await cocoSsd.load(); + var imgPixel = await tf.browser.fromPixels(canvas) + const predictions = await model.detect(imgPixel, 20, 0.1) + const font = "16px sans-serif"; + ctx.font = font; + ctx.textBaseline = "top"; + predictions.forEach(prediction => { + const x = prediction.bbox[0]; + const y = prediction.bbox[1]; + const width = prediction.bbox[2]; + const height = prediction.bbox[3]; + // Bounding box + ctx.strokeStyle = "#00FFFF"; + ctx.lineWidth = 2; + ctx.strokeRect(x, y, width, height); + // Label background + ctx.fillStyle = "#00FFFF"; + const textWidth = ctx.measureText(prediction.class).width; + const textHeight = parseInt(font, 10); // base 10 + ctx.fillRect(x, y, textWidth + 4, textHeight + 4); + }); + predictions.forEach(prediction => { + const x = prediction.bbox[0]; + const y = prediction.bbox[1]; + ctx.fillStyle = "#000000"; + ctx.fillText(prediction.class, x, y); + }); + const buffer = canvas.toBuffer('image/png') + return buffer +}; +async function catdetector(imagePath){ + let result + var image = await canvasAPP.loadImage(imagePath) + const canvas = await canvasAPP.createCanvas(image.width, image.height) + const ctx = await canvas.getContext('2d') + + await ctx.drawImage(image, 0, 0) + //const decodedImage = await tfn.node.decodeImage(image, 3); + const model = await mobilenet.load() + var imgPixel = await tf.browser.fromPixels(canvas) + result = await model.classify(imgPixel) + return result +} + + +module.exports = { + catdetector, + drawBoxes +} diff --git a/helpers/leetspeak.js b/helpers/leetspeak.js new file mode 100644 index 0000000..c54d1f3 --- /dev/null +++ b/helpers/leetspeak.js @@ -0,0 +1,91 @@ +const alphabetBasic = { + 'a': '4', + 'b': '8', + 'e': '3', + 'f': 'f', + 'g': '6', // or 9 + 'i': '1', // or | + 'o': '0', + 's': '5', + 't': '7' // or + +} + +const alphabetAdvanced = { + 'c': '(', // or k or |< or /< + 'd': '<|', + 'h': '|-|', + 'k': '|<', // or /< + 'l': '|', // or 1 + 'm': '|\\/|', + 'n': '|\\|', + 'p': '|2', + 'u': '|_|', + 'v': '/', // or \/ + 'w': '//', // or \/\/ + 'x': '><', + 'y': '\'/' +} + +const alphabetReversed = [ + [/(\|\\\/\|)/g, 'm'], + [/(\|\\\|)/g, 'n'], + [/(\()/g, 'c'], + [/(<\|)/g, 'd'], + [/\|-\|/g, 'h'], + [/(\|<)/g, 'k'], + [/(\|2)/g, 'p'], + [/(\|_\|)/g, 'u'], + [/(\/\/)/g, 'w'], + [/(><)/g, 'x'], + [/(\|)/g, 'l'], + [/(\'\/)/g, 'y'], + [/(\/)/g, 'v'], + [/(1)/g, 'i'], + [/(0)/g, 'o'], + [/(3)/g, 'e'], + [/(4)/g, 'a'], + [/(5)/g, 's'], + [/(6)/g, 'g'], + [/(7)/g, 't'], + [/(8)/g, 'b'], + [/(ph)/g, 'f'], +] + +// Convert input into l33t +const convertInput = (text, useAdvanced = 'n') => { + for (let i = 0; i < text.length; i++) { + let alphabet + let letter = text[i].toLowerCase() + + if (useAdvanced.toLowerCase() === 'y') { + // Use advanced l33t speak alphabet + alphabet = alphabetBasic[letter] ? alphabetBasic[letter] : alphabetAdvanced[letter] + } else { + // Use basic l33t speak alphabet + alphabet = alphabetBasic[letter] + } + + if (alphabet) { + text = text.replace(text[i], alphabet) + } + } + + // Show the result in console + console.log(text) + + return text +} + +const convertInputReverse = (text) => { + text = text.toLowerCase() + + alphabetReversed.map((x) => { + text = text.replace(x[0], x[1]) + }) + + console.log(text) + + return text +} + +module.exports = { convertInput, convertInputReverse } diff --git a/helpers/makecard.js b/helpers/makecard.js new file mode 100644 index 0000000..73edc2a --- /dev/null +++ b/helpers/makecard.js @@ -0,0 +1,65 @@ +const canvasAPP = require('canvas'); + +const applyText = (canvas, text) => { + const ctx = canvas.getContext('2d'); + + // Declare a base size of the font + let fontSize = 70; + + do { + // Assign the font to the context and decrement it so it can be measured again + ctx.font = `${fontSize -= 10}px sans-serif`; + // Compare pixel width of the text to the canvas minus the approximate avatar size + } while (ctx.measureText(text).width > canvas.width - 300); + + // Return the result to use in the actual canvas + return ctx.font; +}; + +async function makeCard(type, img, texttop, textbottom){ + var background = await canvasAPP.loadImage('./action.png') + if(type == "s" || type == "S"){ + background = await canvasAPP.loadImage('./status.png') + } + if(textbottom[0]==' '){ + textbottom = textbottom.slice(1, textbottom.length) + } + const canvas = await canvasAPP.createCanvas(background.width, background.height) + const ctx = await canvas.getContext('2d') + await ctx.drawImage(background, 0, 0) + const font1 = "40px sans-serif"; + const font2 = "8px sans-serif"; + const pic = await canvasAPP.loadImage(img) + ctx.drawImage(pic,200,220,360,360) + ctx.font = applyText(canvas, texttop); + ctx.textBaseline = "top"; + ctx.fillStyle = '#ffffff'; + ctx.fillText(texttop, canvas.width/3.25, 60) + ctx.font = '16pt sans-serif' + let x = canvas.width/4; + let maxWidth = 400; + let y = 620 + let line = ''; + let lineHeight = 25; + for(var n = 0; n < textbottom.length; n++) { + var testLine = line + textbottom[n] + ' '; + var metrics = ctx.measureText(testLine); + var testWidth = metrics.width; + if (testWidth > maxWidth && n > 0) { + ctx.fillText(line, x, y); + line = textbottom[n] + ' '; + y += lineHeight; + } + else { + line = testLine; + } + ctx.fillText(line, x, y); + } + const buffer = canvas.toBuffer('image/png') + return buffer +}; + + +module.exports = { + makeCard +} diff --git a/helpers/steamer.js b/helpers/steamer.js new file mode 100644 index 0000000..1232be7 --- /dev/null +++ b/helpers/steamer.js @@ -0,0 +1,168 @@ +const baseURL = "https://api.steampowered.com/" +const token = '6CF857296B7A47108E148C40164822B2' +var http = require("http"); +const superagent = require("superagent") + + + +async function createRequest(interfaceName, method, version) { + let url = `${baseURL}/${interfaceName}/${method}/v${version}/?key=${token}&format=json`; + return url; +} + +async function ownedGames(steamID) { + return new Promise((resolve, reject) => { + let req = http.get(`http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=${token}&steamid=${steamID}&format=json`, function(res){ + var body = "" + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + let json + try{ + json = JSON.parse(body) + } catch(error){ + console.log(error) + } + resolve(json); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} +async function getSteamID(vanityUrl) { + return new Promise((resolve, reject) => { + let req = http.get(`http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=${token}&vanityurl=${vanityUrl}&format=json`, function(res){ + var body = "" + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + let json + try{ + json = JSON.parse(body) + } catch(error){ + console.log(error) + } + resolve(json); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} + +async function recentGames(steamID) { + return new Promise((resolve, reject) => { + let req = http.get(`http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?key=${token}&steamid=${steamID}&format=json`, function(res){ + var body = "" + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + let json + try{ + json = JSON.parse(body) + } catch(error){ + console.log(error) + } + resolve(json); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} + +async function user(steamID) { + return new Promise((resolve, reject) => { + let req = http.get(`http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${token}&steamids=${steamID}`, function(res){ + var body = "" + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + let json + try{ + json = JSON.parse(body) + } catch(error){ + console.log(error) + } + resolve(json); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} + +async function gameNews(appID) { + return new Promise((resolve, reject) => { + let req = http.get(`http://api.steampowered.com/ISteamNews/GetNewsForApp/v0002/?appid=${appID}&count=1&maxlength=300&format=json`, function(res){ + var body = "" + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + let json + try{ + json = JSON.parse(body) + } catch(error){ + console.log(error) + } + resolve(json); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} + +async function game(appID) { + return new Promise((resolve, reject) => { + let req = http.request(`https://store.steampowered.com/api/appdetails?appids=${appID}`, function(res){ + var body = []; + res.on('data', function(chunk) { + body.push(chunk); + }); + res.on('end', function() { + try { + body = JSON.parse(Buffer.concat(body).toString()); + } catch(e) { + reject(e); + } + resolve(body); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); + }) +} +module.exports = { + getSteamID, + game, + gameNews, + user, + createRequest, + ownedGames, + recentGames, +} diff --git a/helpers/urbaner.js b/helpers/urbaner.js new file mode 100644 index 0000000..1e1c490 --- /dev/null +++ b/helpers/urbaner.js @@ -0,0 +1,47 @@ + var http = require("https"); + + + +async function define(term) { + return new Promise((resolve, reject) => { + const path = '/define?term='+term; + const options = { + "method": "GET", + "hostname": "mashape-community-urban-dictionary.p.rapidapi.com", + "port": null, + "path": path, + "headers": { + "x-rapidapi-key": "1276b32e63msh739dcbdeaf39a12p175d69jsn31c93e5fcdbc", + "x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com", + "useQueryString": true + } + }; + + const req = http.request(options, (res) => { + if (res.statusCode < 200 || res.statusCode >= 300) { + return reject(new Error('statusCode=' + res.statusCode)); + } + var body = []; + res.on('data', function(chunk) { + body.push(chunk); + }); + res.on('end', function() { + try { + body = JSON.parse(Buffer.concat(body).toString()); + } catch(e) { + reject(e); + } + resolve(body); + }); + }); + req.on('error', (e) => { + reject(e.message); + }); + // send the request + req.end(); +}); +} + +module.exports = { + define, +}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..45f2a84 --- /dev/null +++ b/index.js @@ -0,0 +1,106 @@ +const fs = require('fs'); +const fetch = require('node-fetch') +const { Client, MessageAttachment, Collection } = require('discord.js'); +const { prefix, token } = require('./config.json'); +const db = require('quick.db'); + +const client = new Client(); +client.commands = new Collection(); +client.cooldowns = new Collection(); + +const commandFolders = fs.readdirSync('./commands'); + +for (const folder of commandFolders) { + const commandFiles = fs.readdirSync(`./commands/${folder}`).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + const command = require(`./commands/${folder}/${file}`); + client.commands.set(command.name, command); + } +} + +client.once('ready', () => { + console.log('Ready!'); +}); + + +function getCoefficient(level) { + let arg = (0.000412081 * Math.pow(level, 2)) + return arg +} + + +client.on('message', async message => { + if(message.author.id != 819816527175614465){ + db.add(`messages_${message.guild.id}_${message.author.id}`, 1) + let messageFetch = db.fetch(`messages_${message.guild.id}_${message.author.id}`) + + let messages = messageFetch; + let previous = Math.floor(getCoefficient(messages-1)) + let level = Math.floor(getCoefficient(messages)) + if(level > previous){ + message.reply(`Congrats you just leveled up to level ${level}`) + } + } + + if (!message.content.startsWith(prefix) || message.author.bot) return; + + const args = message.content.slice(prefix.length).trim().split(/ +/); + const commandName = args.shift().toLowerCase(); + + const command = client.commands.get(commandName) + || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + if (!command) return; + + if (command.guildOnly && message.channel.type === 'dm') { + return message.reply('I can\'t execute that command inside DMs!'); + } + + if (command.permissions) { + const authorPerms = message.channel.permissionsFor(message.author); + if (!authorPerms || !authorPerms.has(command.permissions)) { + return message.reply('You can not do this!'); + } + } + + if (command.args && !args.length) { + let reply = `You didn't provide any arguments, ${message.author}!`; + + if (command.usage) { + reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``; + } + + return message.channel.send(reply); + } + +const { cooldowns } = client; + + if (!cooldowns.has(command.name)) { + cooldowns.set(command.name, new Collection()); + } + + const now = Date.now(); + const timestamps = cooldowns.get(command.name); + const cooldownAmount = (command.cooldown || 3) * 1000; + + if (timestamps.has(message.author.id)) { + const expirationTime = timestamps.get(message.author.id) + cooldownAmount; + + if (now < expirationTime) { + const timeLeft = (expirationTime - now) / 1000; + return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`); + } + } + + timestamps.set(message.author.id, now); + setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); + + try { + command.execute(message, args, client); + } catch (error) { + console.error(error); + message.reply('there was an error trying to execute that command!'); + } +}); + +client.login(token); diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..fee0cce --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,448 @@ +{ + "name": "PharmaBot", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + }, + "node_modules/@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", + "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==" + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", + "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/prism-media": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", + "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==", + "peerDependencies": { + "@discordjs/opus": "^0.5.0", + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve-alpn": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", + "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==" + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/node_modules/@discordjs/collection/LICENSE b/node_modules/@discordjs/collection/LICENSE new file mode 100644 index 0000000..9997d13 --- /dev/null +++ b/node_modules/@discordjs/collection/LICENSE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 - 2020 Amish Shah + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/@discordjs/collection/README.md b/node_modules/@discordjs/collection/README.md new file mode 100644 index 0000000..0e31ccd --- /dev/null +++ b/node_modules/@discordjs/collection/README.md @@ -0,0 +1,3 @@ +# Collection + +Utility data structure used in Discord.js. diff --git a/node_modules/@discordjs/collection/dist/index.d.ts b/node_modules/@discordjs/collection/dist/index.d.ts new file mode 100644 index 0000000..a332396 --- /dev/null +++ b/node_modules/@discordjs/collection/dist/index.d.ts @@ -0,0 +1,319 @@ +export interface CollectionConstructor { + new (): Collection; + new (entries?: ReadonlyArray | null): Collection; + new (iterable: Iterable): Collection; + readonly prototype: Collection; + readonly [Symbol.species]: CollectionConstructor; +} +/** + * A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has + * an ID, for significantly improved performance and ease-of-use. + * @extends {Map} + * @property {number} size - The amount of elements in this collection. + */ +declare class Collection extends Map { + private _array; + private _keyArray; + static readonly default: typeof Collection; + ['constructor']: typeof Collection; + constructor(entries?: ReadonlyArray | null); + /** + * Identical to [Map.get()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get). + * Gets an element with the specified key, and returns its value, or `undefined` if the element does not exist. + * @param {*} key - The key to get from this collection + * @returns {* | undefined} + */ + get(key: K): V | undefined; + /** + * Identical to [Map.set()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set). + * Sets a new element in the collection with the specified key and value. + * @param {*} key - The key of the element to add + * @param {*} value - The value of the element to add + * @returns {Collection} + */ + set(key: K, value: V): this; + /** + * Identical to [Map.has()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has). + * Checks if an element exists in the collection. + * @param {*} key - The key of the element to check for + * @returns {boolean} `true` if the element exists, `false` if it does not exist. + */ + has(key: K): boolean; + /** + * Identical to [Map.delete()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete). + * Deletes an element from the collection. + * @param {*} key - The key to delete from the collection + * @returns {boolean} `true` if the element was removed, `false` if the element does not exist. + */ + delete(key: K): boolean; + /** + * Identical to [Map.clear()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear). + * Removes all elements from the collection. + * @returns {undefined} + */ + clear(): void; + /** + * Creates an ordered array of the values of this collection, and caches it internally. The array will only be + * reconstructed if an item is added to or removed from the collection, or if you change the length of the array + * itself. If you don't want this caching behavior, use `[...collection.values()]` or + * `Array.from(collection.values())` instead. + * @returns {Array} + */ + array(): V[]; + /** + * Creates an ordered array of the keys of this collection, and caches it internally. The array will only be + * reconstructed if an item is added to or removed from the collection, or if you change the length of the array + * itself. If you don't want this caching behavior, use `[...collection.keys()]` or + * `Array.from(collection.keys())` instead. + * @returns {Array} + */ + keyArray(): K[]; + /** + * Obtains the first value(s) in this collection. + * @param {number} [amount] Amount of values to obtain from the beginning + * @returns {*|Array<*>} A single value if no amount is provided or an array of values, starting from the end if + * amount is negative + */ + first(): V | undefined; + first(amount: number): V[]; + /** + * Obtains the first key(s) in this collection. + * @param {number} [amount] Amount of keys to obtain from the beginning + * @returns {*|Array<*>} A single key if no amount is provided or an array of keys, starting from the end if + * amount is negative + */ + firstKey(): K | undefined; + firstKey(amount: number): K[]; + /** + * Obtains the last value(s) in this collection. This relies on {@link Collection#array}, and thus the caching + * mechanism applies here as well. + * @param {number} [amount] Amount of values to obtain from the end + * @returns {*|Array<*>} A single value if no amount is provided or an array of values, starting from the start if + * amount is negative + */ + last(): V | undefined; + last(amount: number): V[]; + /** + * Obtains the last key(s) in this collection. This relies on {@link Collection#keyArray}, and thus the caching + * mechanism applies here as well. + * @param {number} [amount] Amount of keys to obtain from the end + * @returns {*|Array<*>} A single key if no amount is provided or an array of keys, starting from the start if + * amount is negative + */ + lastKey(): K | undefined; + lastKey(amount: number): K[]; + /** + * Obtains unique random value(s) from this collection. This relies on {@link Collection#array}, and thus the caching + * mechanism applies here as well. + * @param {number} [amount] Amount of values to obtain randomly + * @returns {*|Array<*>} A single value if no amount is provided or an array of values + */ + random(): V; + random(amount: number): V[]; + /** + * Obtains unique random key(s) from this collection. This relies on {@link Collection#keyArray}, and thus the caching + * mechanism applies here as well. + * @param {number} [amount] Amount of keys to obtain randomly + * @returns {*|Array<*>} A single key if no amount is provided or an array + */ + randomKey(): K; + randomKey(amount: number): K[]; + /** + * Searches for a single item where the given function returns a truthy value. This behaves like + * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find). + * All collections used in Discord.js are mapped using their `id` property, and if you want to find by id you + * should use the `get` method. See + * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) for details. + * @param {Function} fn The function to test with (should return boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {*} + * @example collection.find(user => user.username === 'Bob'); + */ + find(fn: (value: V, key: K, collection: this) => boolean): V | undefined; + find(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): V | undefined; + /** + * Searches for the key of a single item where the given function returns a truthy value. This behaves like + * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex), + * but returns the key rather than the positional index. + * @param {Function} fn The function to test with (should return boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {*} + * @example collection.findKey(user => user.username === 'Bob'); + */ + findKey(fn: (value: V, key: K, collection: this) => boolean): K | undefined; + findKey(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): K | undefined; + /** + * Removes items that satisfy the provided filter function. + * @param {Function} fn Function used to test (should return a boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {number} The number of removed entries + */ + sweep(fn: (value: V, key: K, collection: this) => boolean): number; + sweep(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): number; + /** + * Identical to + * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), + * but returns a Collection instead of an Array. + * @param {Function} fn The function to test with (should return boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection} + * @example collection.filter(user => user.username === 'Bob'); + */ + filter(fn: (value: V, key: K, collection: this) => boolean): this; + filter(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): this; + /** + * Partitions the collection into two collections where the first collection + * contains the items that passed and the second contains the items that failed. + * @param {Function} fn Function used to test (should return a boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection[]} + * @example const [big, small] = collection.partition(guild => guild.memberCount > 250); + */ + partition(fn: (value: V, key: K, collection: this) => boolean): [this, this]; + partition(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): [this, this]; + /** + * Maps each item into a Collection, then joins the results into a single Collection. Identical in behavior to + * [Array.flatMap()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap). + * @param {Function} fn Function that produces a new Collection + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection} + * @example collection.flatMap(guild => guild.members.cache); + */ + flatMap(fn: (value: V, key: K, collection: this) => Collection): Collection; + flatMap(fn: (this: This, value: V, key: K, collection: this) => Collection, thisArg: This): Collection; + /** + * Maps each item to another value into an array. Identical in behavior to + * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). + * @param {Function} fn Function that produces an element of the new array, taking three arguments + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Array} + * @example collection.map(user => user.tag); + */ + map(fn: (value: V, key: K, collection: this) => T): T[]; + map(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): T[]; + /** + * Maps each item to another value into a collection. Identical in behavior to + * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). + * @param {Function} fn Function that produces an element of the new collection, taking three arguments + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection} + * @example collection.mapValues(user => user.tag); + */ + mapValues(fn: (value: V, key: K, collection: this) => T): Collection; + mapValues(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): Collection; + /** + * Checks if there exists an item that passes a test. Identical in behavior to + * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some). + * @param {Function} fn Function used to test (should return a boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {boolean} + * @example collection.some(user => user.discriminator === '0000'); + */ + some(fn: (value: V, key: K, collection: this) => boolean): boolean; + some(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): boolean; + /** + * Checks if all items passes a test. Identical in behavior to + * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every). + * @param {Function} fn Function used to test (should return a boolean) + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {boolean} + * @example collection.every(user => !user.bot); + */ + every(fn: (value: V, key: K, collection: this) => boolean): boolean; + every(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): boolean; + /** + * Applies a function to produce a single value. Identical in behavior to + * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce). + * @param {Function} fn Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`, + * and `collection` + * @param {*} [initialValue] Starting value for the accumulator + * @returns {*} + * @example collection.reduce((acc, guild) => acc + guild.memberCount, 0); + */ + reduce(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T; + /** + * Identical to + * [Map.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach), + * but returns the collection instead of undefined. + * @param {Function} fn Function to execute for each element + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection} + * @example + * collection + * .each(user => console.log(user.username)) + * .filter(user => user.bot) + * .each(user => console.log(user.username)); + */ + each(fn: (value: V, key: K, collection: this) => void): this; + each(fn: (this: T, value: V, key: K, collection: this) => void, thisArg: T): this; + /** + * Runs a function on the collection and returns the collection. + * @param {Function} fn Function to execute + * @param {*} [thisArg] Value to use as `this` when executing function + * @returns {Collection} + * @example + * collection + * .tap(coll => console.log(coll.size)) + * .filter(user => user.bot) + * .tap(coll => console.log(coll.size)) + */ + tap(fn: (collection: this) => void): this; + tap(fn: (this: T, collection: this) => void, thisArg: T): this; + /** + * Creates an identical shallow copy of this collection. + * @returns {Collection} + * @example const newColl = someColl.clone(); + */ + clone(): this; + /** + * Combines this collection with others into a new collection. None of the source collections are modified. + * @param {...Collection} collections Collections to merge + * @returns {Collection} + * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); + */ + concat(...collections: Collection[]): this; + /** + * Checks if this collection shares identical items with another. + * This is different to checking for equality using equal-signs, because + * the collections may be different objects, but contain the same data. + * @param {Collection} collection Collection to compare with + * @returns {boolean} Whether the collections have identical contents + */ + equals(collection: Collection): boolean; + /** + * The sort method sorts the items of a collection in place and returns it. + * The sort is not necessarily stable in Node 10 or older. + * The default sort order is according to string Unicode code points. + * @param {Function} [compareFunction] Specifies a function that defines the sort order. + * If omitted, the collection is sorted according to each character's Unicode code point value, + * according to the string conversion of each element. + * @returns {Collection} + * @example collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); + */ + sort(compareFunction?: (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number): this; + /** + * The intersect method returns a new structure containing items where the keys are present in both original structures. + * @param {Collection} other The other Collection to filter against + * @returns {Collection} + */ + intersect(other: Collection): Collection; + /** + * The difference method returns a new structure containing items where the key is present in one of the original structures but not the other. + * @param {Collection} other The other Collection to filter against + * @returns {Collection} + */ + difference(other: Collection): Collection; + /** + * The sorted method sorts the items of a collection and returns it. + * The sort is not necessarily stable in Node 10 or older. + * The default sort order is according to string Unicode code points. + * @param {Function} [compareFunction] Specifies a function that defines the sort order. + * If omitted, the collection is sorted according to each character's Unicode code point value, + * according to the string conversion of each element. + * @returns {Collection} + * @example collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); + */ + sorted(compareFunction?: (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number): this; +} +export { Collection }; +export default Collection; diff --git a/node_modules/@discordjs/collection/dist/index.js b/node_modules/@discordjs/collection/dist/index.js new file mode 100644 index 0000000..8c47cfd --- /dev/null +++ b/node_modules/@discordjs/collection/dist/index.js @@ -0,0 +1,392 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Collection = void 0; +/** + * A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has + * an ID, for significantly improved performance and ease-of-use. + * @extends {Map} + * @property {number} size - The amount of elements in this collection. + */ +class Collection extends Map { + constructor(entries) { + super(entries); + /** + * Cached array for the `array()` method - will be reset to `null` whenever `set()` or `delete()` are called + * @name Collection#_array + * @type {?Array} + * @private + */ + Object.defineProperty(this, '_array', { value: null, writable: true, configurable: true }); + /** + * Cached array for the `keyArray()` method - will be reset to `null` whenever `set()` or `delete()` are called + * @name Collection#_keyArray + * @type {?Array} + * @private + */ + Object.defineProperty(this, '_keyArray', { value: null, writable: true, configurable: true }); + } + /** + * Identical to [Map.get()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get). + * Gets an element with the specified key, and returns its value, or `undefined` if the element does not exist. + * @param {*} key - The key to get from this collection + * @returns {* | undefined} + */ + get(key) { + return super.get(key); + } + /** + * Identical to [Map.set()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set). + * Sets a new element in the collection with the specified key and value. + * @param {*} key - The key of the element to add + * @param {*} value - The value of the element to add + * @returns {Collection} + */ + set(key, value) { + this._array = null; + this._keyArray = null; + return super.set(key, value); + } + /** + * Identical to [Map.has()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has). + * Checks if an element exists in the collection. + * @param {*} key - The key of the element to check for + * @returns {boolean} `true` if the element exists, `false` if it does not exist. + */ + has(key) { + return super.has(key); + } + /** + * Identical to [Map.delete()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete). + * Deletes an element from the collection. + * @param {*} key - The key to delete from the collection + * @returns {boolean} `true` if the element was removed, `false` if the element does not exist. + */ + delete(key) { + this._array = null; + this._keyArray = null; + return super.delete(key); + } + /** + * Identical to [Map.clear()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear). + * Removes all elements from the collection. + * @returns {undefined} + */ + clear() { + return super.clear(); + } + /** + * Creates an ordered array of the values of this collection, and caches it internally. The array will only be + * reconstructed if an item is added to or removed from the collection, or if you change the length of the array + * itself. If you don't want this caching behavior, use `[...collection.values()]` or + * `Array.from(collection.values())` instead. + * @returns {Array} + */ + array() { + if (!this._array || this._array.length !== this.size) + this._array = [...this.values()]; + return this._array; + } + /** + * Creates an ordered array of the keys of this collection, and caches it internally. The array will only be + * reconstructed if an item is added to or removed from the collection, or if you change the length of the array + * itself. If you don't want this caching behavior, use `[...collection.keys()]` or + * `Array.from(collection.keys())` instead. + * @returns {Array} + */ + keyArray() { + if (!this._keyArray || this._keyArray.length !== this.size) + this._keyArray = [...this.keys()]; + return this._keyArray; + } + first(amount) { + if (typeof amount === 'undefined') + return this.values().next().value; + if (amount < 0) + return this.last(amount * -1); + amount = Math.min(this.size, amount); + const iter = this.values(); + return Array.from({ length: amount }, () => iter.next().value); + } + firstKey(amount) { + if (typeof amount === 'undefined') + return this.keys().next().value; + if (amount < 0) + return this.lastKey(amount * -1); + amount = Math.min(this.size, amount); + const iter = this.keys(); + return Array.from({ length: amount }, () => iter.next().value); + } + last(amount) { + const arr = this.array(); + if (typeof amount === 'undefined') + return arr[arr.length - 1]; + if (amount < 0) + return this.first(amount * -1); + if (!amount) + return []; + return arr.slice(-amount); + } + lastKey(amount) { + const arr = this.keyArray(); + if (typeof amount === 'undefined') + return arr[arr.length - 1]; + if (amount < 0) + return this.firstKey(amount * -1); + if (!amount) + return []; + return arr.slice(-amount); + } + random(amount) { + let arr = this.array(); + if (typeof amount === 'undefined') + return arr[Math.floor(Math.random() * arr.length)]; + if (arr.length === 0 || !amount) + return []; + arr = arr.slice(); + return Array.from({ length: amount }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + } + randomKey(amount) { + let arr = this.keyArray(); + if (typeof amount === 'undefined') + return arr[Math.floor(Math.random() * arr.length)]; + if (arr.length === 0 || !amount) + return []; + arr = arr.slice(); + return Array.from({ length: amount }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + } + find(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + for (const [key, val] of this) { + if (fn(val, key, this)) + return val; + } + return undefined; + } + findKey(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + for (const [key, val] of this) { + if (fn(val, key, this)) + return key; + } + return undefined; + } + sweep(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + const previousSize = this.size; + for (const [key, val] of this) { + if (fn(val, key, this)) + this.delete(key); + } + return previousSize - this.size; + } + filter(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + const results = new this.constructor[Symbol.species](); + for (const [key, val] of this) { + if (fn(val, key, this)) + results.set(key, val); + } + return results; + } + partition(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + // TODO: consider removing the from the constructors after TS 3.7.0 is released, as it infers it + const results = [new this.constructor[Symbol.species](), new this.constructor[Symbol.species]()]; + for (const [key, val] of this) { + if (fn(val, key, this)) { + results[0].set(key, val); + } + else { + results[1].set(key, val); + } + } + return results; + } + flatMap(fn, thisArg) { + const collections = this.map(fn, thisArg); + return new this.constructor[Symbol.species]().concat(...collections); + } + map(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + const iter = this.entries(); + return Array.from({ length: this.size }, () => { + const [key, value] = iter.next().value; + return fn(value, key, this); + }); + } + mapValues(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + const coll = new this.constructor[Symbol.species](); + for (const [key, val] of this) + coll.set(key, fn(val, key, this)); + return coll; + } + some(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + for (const [key, val] of this) { + if (fn(val, key, this)) + return true; + } + return false; + } + every(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + for (const [key, val] of this) { + if (!fn(val, key, this)) + return false; + } + return true; + } + /** + * Applies a function to produce a single value. Identical in behavior to + * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce). + * @param {Function} fn Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`, + * and `collection` + * @param {*} [initialValue] Starting value for the accumulator + * @returns {*} + * @example collection.reduce((acc, guild) => acc + guild.memberCount, 0); + */ + reduce(fn, initialValue) { + let accumulator; + if (typeof initialValue !== 'undefined') { + accumulator = initialValue; + for (const [key, val] of this) + accumulator = fn(accumulator, val, key, this); + return accumulator; + } + let first = true; + for (const [key, val] of this) { + if (first) { + accumulator = val; + first = false; + continue; + } + accumulator = fn(accumulator, val, key, this); + } + // No items iterated. + if (first) { + throw new TypeError('Reduce of empty collection with no initial value'); + } + return accumulator; + } + each(fn, thisArg) { + this.forEach(fn, thisArg); + return this; + } + tap(fn, thisArg) { + if (typeof thisArg !== 'undefined') + fn = fn.bind(thisArg); + fn(this); + return this; + } + /** + * Creates an identical shallow copy of this collection. + * @returns {Collection} + * @example const newColl = someColl.clone(); + */ + clone() { + return new this.constructor[Symbol.species](this); + } + /** + * Combines this collection with others into a new collection. None of the source collections are modified. + * @param {...Collection} collections Collections to merge + * @returns {Collection} + * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); + */ + concat(...collections) { + const newColl = this.clone(); + for (const coll of collections) { + for (const [key, val] of coll) + newColl.set(key, val); + } + return newColl; + } + /** + * Checks if this collection shares identical items with another. + * This is different to checking for equality using equal-signs, because + * the collections may be different objects, but contain the same data. + * @param {Collection} collection Collection to compare with + * @returns {boolean} Whether the collections have identical contents + */ + equals(collection) { + if (!collection) + return false; + if (this === collection) + return true; + if (this.size !== collection.size) + return false; + for (const [key, value] of this) { + if (!collection.has(key) || value !== collection.get(key)) { + return false; + } + } + return true; + } + /** + * The sort method sorts the items of a collection in place and returns it. + * The sort is not necessarily stable in Node 10 or older. + * The default sort order is according to string Unicode code points. + * @param {Function} [compareFunction] Specifies a function that defines the sort order. + * If omitted, the collection is sorted according to each character's Unicode code point value, + * according to the string conversion of each element. + * @returns {Collection} + * @example collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); + */ + sort(compareFunction = (x, y) => Number(x > y) || Number(x === y) - 1) { + const entries = [...this.entries()]; + entries.sort((a, b) => compareFunction(a[1], b[1], a[0], b[0])); + // Perform clean-up + super.clear(); + this._array = null; + this._keyArray = null; + // Set the new entries + for (const [k, v] of entries) { + super.set(k, v); + } + return this; + } + /** + * The intersect method returns a new structure containing items where the keys are present in both original structures. + * @param {Collection} other The other Collection to filter against + * @returns {Collection} + */ + intersect(other) { + return other.filter((_, k) => this.has(k)); + } + /** + * The difference method returns a new structure containing items where the key is present in one of the original structures but not the other. + * @param {Collection} other The other Collection to filter against + * @returns {Collection} + */ + difference(other) { + return other.filter((_, k) => !this.has(k)).concat(this.filter((_, k) => !other.has(k))); + } + /** + * The sorted method sorts the items of a collection and returns it. + * The sort is not necessarily stable in Node 10 or older. + * The default sort order is according to string Unicode code points. + * @param {Function} [compareFunction] Specifies a function that defines the sort order. + * If omitted, the collection is sorted according to each character's Unicode code point value, + * according to the string conversion of each element. + * @returns {Collection} + * @example collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); + */ + sorted(compareFunction = (x, y) => Number(x > y) || Number(x === y) - 1) { + return new this.constructor[Symbol.species]([...this.entries()]) + .sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk)); + } +} +exports.Collection = Collection; +Collection.default = Collection; +module.exports = Collection; +exports.default = Collection; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLyIsInNvdXJjZXMiOlsiaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBUUE7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQWlCLFNBQVEsR0FBUztJQU12QyxZQUFtQixPQUErQztRQUNqRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFZjs7Ozs7V0FLRztRQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUUzRjs7Ozs7V0FLRztRQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMvRixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxHQUFHLENBQUMsR0FBTTtRQUNoQixPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEdBQUcsQ0FBQyxHQUFNLEVBQUUsS0FBUTtRQUMxQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLEdBQUcsQ0FBQyxHQUFNO1FBQ2hCLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsR0FBTTtRQUNuQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLO1FBQ1gsT0FBTyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEtBQUs7UUFDWCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsSUFBSTtZQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZGLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksUUFBUTtRQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxJQUFJO1lBQUUsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUYsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3ZCLENBQUM7SUFVTSxLQUFLLENBQUMsTUFBZTtRQUMzQixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDckUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMzQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFVTSxRQUFRLENBQUMsTUFBZTtRQUM5QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDbkUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFXTSxJQUFJLENBQUMsTUFBZTtRQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXO1lBQUUsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLE1BQU0sR0FBRyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDdkIsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQVdNLE9BQU8sQ0FBQyxNQUFlO1FBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM1QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlELElBQUksTUFBTSxHQUFHLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBVU0sTUFBTSxDQUFDLE1BQWU7UUFDNUIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVztZQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRyxDQUFDO0lBVU0sU0FBUyxDQUFDLE1BQWU7UUFDL0IsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzFCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVztZQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRyxDQUFDO0lBZU0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEdBQUcsQ0FBQztTQUNuQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFhTSxPQUFPLENBQUMsRUFBbUQsRUFBRSxPQUFpQjtRQUNwRixJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDO2dCQUFFLE9BQU8sR0FBRyxDQUFDO1NBQ25DO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbEIsQ0FBQztJQVVNLEtBQUssQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ2xGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDL0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3pDO1FBQ0QsT0FBTyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBYU0sTUFBTSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDbkYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBZ0IsQ0FBQztRQUNyRSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDO2dCQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQzlDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDaEIsQ0FBQztJQVlNLFNBQVMsQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ3RGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELHVHQUF1RztRQUN2RyxNQUFNLE9BQU8sR0FBaUIsQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFnQixFQUFFLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQWdCLENBQUMsQ0FBQztRQUMzSSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUU7Z0JBQ3ZCLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2FBQ3pCO2lCQUFNO2dCQUNOLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2FBQ3pCO1NBQ0Q7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNoQixDQUFDO0lBWU0sT0FBTyxDQUFJLEVBQTRELEVBQUUsT0FBaUI7UUFDaEcsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUMsT0FBUSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUE2QixDQUFDLE1BQU0sQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFZTSxHQUFHLENBQUksRUFBNkMsRUFBRSxPQUFpQjtRQUM3RSxJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDNUIsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFNLEVBQUU7WUFDaEQsTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDO1lBQ3ZDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBWU0sU0FBUyxDQUFJLEVBQTZDLEVBQUUsT0FBaUI7UUFDbkYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBNEIsQ0FBQztRQUM5RSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtZQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDakUsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBWU0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLElBQUksQ0FBQztTQUNwQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2QsQ0FBQztJQVlNLEtBQUssQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ2xGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEtBQUssQ0FBQztTQUN0QztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksTUFBTSxDQUFJLEVBQTZELEVBQUUsWUFBZ0I7UUFDL0YsSUFBSSxXQUFlLENBQUM7UUFFcEIsSUFBSSxPQUFPLFlBQVksS0FBSyxXQUFXLEVBQUU7WUFDeEMsV0FBVyxHQUFHLFlBQVksQ0FBQztZQUMzQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtnQkFBRSxXQUFXLEdBQUcsRUFBRSxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdFLE9BQU8sV0FBVyxDQUFDO1NBQ25CO1FBQ0QsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1YsV0FBVyxHQUFHLEdBQW1CLENBQUM7Z0JBQ2xDLEtBQUssR0FBRyxLQUFLLENBQUM7Z0JBQ2QsU0FBUzthQUNUO1lBQ0QsV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUM5QztRQUVELHFCQUFxQjtRQUNyQixJQUFJLEtBQUssRUFBRTtZQUNWLE1BQU0sSUFBSSxTQUFTLENBQUMsa0RBQWtELENBQUMsQ0FBQztTQUN4RTtRQUVELE9BQU8sV0FBVyxDQUFDO0lBQ3BCLENBQUM7SUFpQk0sSUFBSSxDQUFDLEVBQWdELEVBQUUsT0FBaUI7UUFDOUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFnRCxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQWVNLEdBQUcsQ0FBQyxFQUE4QixFQUFFLE9BQWlCO1FBQzNELElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNULE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLO1FBQ1gsT0FBTyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBUyxDQUFDO0lBQzNELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxHQUFHLFdBQStCO1FBQy9DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixLQUFLLE1BQU0sSUFBSSxJQUFJLFdBQVcsRUFBRTtZQUMvQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztTQUNyRDtRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsVUFBNEI7UUFDekMsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUM5QixJQUFJLElBQUksS0FBSyxVQUFVO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxJQUFJO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDaEQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRTtZQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLEtBQUssVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDMUQsT0FBTyxLQUFLLENBQUM7YUFDYjtTQUNEO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksSUFBSSxDQUFDLGtCQUF3RixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ3pKLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNwQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEUsbUJBQW1CO1FBQ25CLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNkLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ25CLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBRXRCLHNCQUFzQjtRQUN0QixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksT0FBTyxFQUFFO1lBQzdCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2hCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFNBQVMsQ0FBQyxLQUF1QjtRQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxVQUFVLENBQUMsS0FBdUI7UUFDeEMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsa0JBQXdGLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBVSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDM0osT0FBUSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBVTthQUN4RSxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7O0FBSU8sZ0NBQVU7QUFwakJLLGtCQUFPLEdBQXNCLFVBQVUsQ0FBQztBQW1qQmhFLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO0FBRTVCLGtCQUFlLFVBQVUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgQ29sbGVjdGlvbkNvbnN0cnVjdG9yIHtcblx0bmV3KCk6IENvbGxlY3Rpb248dW5rbm93biwgdW5rbm93bj47XG5cdG5ldzxLLCBWPihlbnRyaWVzPzogUmVhZG9ubHlBcnJheTxyZWFkb25seSBbSywgVl0+IHwgbnVsbCk6IENvbGxlY3Rpb248SywgVj47XG5cdG5ldzxLLCBWPihpdGVyYWJsZTogSXRlcmFibGU8cmVhZG9ubHkgW0ssIFZdPik6IENvbGxlY3Rpb248SywgVj47XG5cdHJlYWRvbmx5IHByb3RvdHlwZTogQ29sbGVjdGlvbjx1bmtub3duLCB1bmtub3duPjtcblx0cmVhZG9ubHkgW1N5bWJvbC5zcGVjaWVzXTogQ29sbGVjdGlvbkNvbnN0cnVjdG9yO1xufVxuXG4vKipcbiAqIEEgTWFwIHdpdGggYWRkaXRpb25hbCB1dGlsaXR5IG1ldGhvZHMuIFRoaXMgaXMgdXNlZCB0aHJvdWdob3V0IGRpc2NvcmQuanMgcmF0aGVyIHRoYW4gQXJyYXlzIGZvciBhbnl0aGluZyB0aGF0IGhhc1xuICogYW4gSUQsIGZvciBzaWduaWZpY2FudGx5IGltcHJvdmVkIHBlcmZvcm1hbmNlIGFuZCBlYXNlLW9mLXVzZS5cbiAqIEBleHRlbmRzIHtNYXB9XG4gKiBAcHJvcGVydHkge251bWJlcn0gc2l6ZSAtIFRoZSBhbW91bnQgb2YgZWxlbWVudHMgaW4gdGhpcyBjb2xsZWN0aW9uLlxuICovXG5jbGFzcyBDb2xsZWN0aW9uPEssIFY+IGV4dGVuZHMgTWFwPEssIFY+IHtcblx0cHJpdmF0ZSBfYXJyYXkhOiBWW10gfCBudWxsO1xuXHRwcml2YXRlIF9rZXlBcnJheSE6IEtbXSB8IG51bGw7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZGVmYXVsdDogdHlwZW9mIENvbGxlY3Rpb24gPSBDb2xsZWN0aW9uO1xuXHRwdWJsaWMgWydjb25zdHJ1Y3RvciddOiB0eXBlb2YgQ29sbGVjdGlvbjtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoZW50cmllcz86IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW0ssIFZdPiB8IG51bGwpIHtcblx0XHRzdXBlcihlbnRyaWVzKTtcblxuXHRcdC8qKlxuXHRcdCAqIENhY2hlZCBhcnJheSBmb3IgdGhlIGBhcnJheSgpYCBtZXRob2QgLSB3aWxsIGJlIHJlc2V0IHRvIGBudWxsYCB3aGVuZXZlciBgc2V0KClgIG9yIGBkZWxldGUoKWAgYXJlIGNhbGxlZFxuXHRcdCAqIEBuYW1lIENvbGxlY3Rpb24jX2FycmF5XG5cdFx0ICogQHR5cGUgez9BcnJheX1cblx0XHQgKiBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnX2FycmF5JywgeyB2YWx1ZTogbnVsbCwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9KTtcblxuXHRcdC8qKlxuXHRcdCAqIENhY2hlZCBhcnJheSBmb3IgdGhlIGBrZXlBcnJheSgpYCBtZXRob2QgLSB3aWxsIGJlIHJlc2V0IHRvIGBudWxsYCB3aGVuZXZlciBgc2V0KClgIG9yIGBkZWxldGUoKWAgYXJlIGNhbGxlZFxuXHRcdCAqIEBuYW1lIENvbGxlY3Rpb24jX2tleUFycmF5XG5cdFx0ICogQHR5cGUgez9BcnJheX1cblx0XHQgKiBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnX2tleUFycmF5JywgeyB2YWx1ZTogbnVsbCwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG8gW01hcC5nZXQoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2dldCkuXG5cdCAqIEdldHMgYW4gZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5LCBhbmQgcmV0dXJucyBpdHMgdmFsdWUsIG9yIGB1bmRlZmluZWRgIGlmIHRoZSBlbGVtZW50IGRvZXMgbm90IGV4aXN0LlxuXHQgKiBAcGFyYW0geyp9IGtleSAtIFRoZSBrZXkgdG8gZ2V0IGZyb20gdGhpcyBjb2xsZWN0aW9uXG5cdCAqIEByZXR1cm5zIHsqIHwgdW5kZWZpbmVkfVxuXHQgKi9cblx0cHVibGljIGdldChrZXk6IEspOiBWIHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gc3VwZXIuZ2V0KGtleSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuc2V0KCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9zZXQpLlxuXHQgKiBTZXRzIGEgbmV3IGVsZW1lbnQgaW4gdGhlIGNvbGxlY3Rpb24gd2l0aCB0aGUgc3BlY2lmaWVkIGtleSBhbmQgdmFsdWUuXG5cdCAqIEBwYXJhbSB7Kn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgZWxlbWVudCB0byBhZGRcblx0ICogQHBhcmFtIHsqfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgZWxlbWVudCB0byBhZGRcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqL1xuXHRwdWJsaWMgc2V0KGtleTogSywgdmFsdWU6IFYpOiB0aGlzIHtcblx0XHR0aGlzLl9hcnJheSA9IG51bGw7XG5cdFx0dGhpcy5fa2V5QXJyYXkgPSBudWxsO1xuXHRcdHJldHVybiBzdXBlci5zZXQoa2V5LCB2YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuaGFzKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9oYXMpLlxuXHQgKiBDaGVja3MgaWYgYW4gZWxlbWVudCBleGlzdHMgaW4gdGhlIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7Kn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgZWxlbWVudCB0byBjaGVjayBmb3Jcblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZWxlbWVudCBleGlzdHMsIGBmYWxzZWAgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cdCAqL1xuXHRwdWJsaWMgaGFzKGtleTogSyk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBzdXBlci5oYXMoa2V5KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG8gW01hcC5kZWxldGUoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2RlbGV0ZSkuXG5cdCAqIERlbGV0ZXMgYW4gZWxlbWVudCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0geyp9IGtleSAtIFRoZSBrZXkgdG8gZGVsZXRlIGZyb20gdGhlIGNvbGxlY3Rpb25cblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZWxlbWVudCB3YXMgcmVtb3ZlZCwgYGZhbHNlYCBpZiB0aGUgZWxlbWVudCBkb2VzIG5vdCBleGlzdC5cblx0ICovXG5cdHB1YmxpYyBkZWxldGUoa2V5OiBLKTogYm9vbGVhbiB7XG5cdFx0dGhpcy5fYXJyYXkgPSBudWxsO1xuXHRcdHRoaXMuX2tleUFycmF5ID0gbnVsbDtcblx0XHRyZXR1cm4gc3VwZXIuZGVsZXRlKGtleSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuY2xlYXIoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2NsZWFyKS5cblx0ICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSB0aGUgY29sbGVjdGlvbi5cblx0ICogQHJldHVybnMge3VuZGVmaW5lZH1cblx0ICovXG5cdHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcblx0XHRyZXR1cm4gc3VwZXIuY2xlYXIoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIG9yZGVyZWQgYXJyYXkgb2YgdGhlIHZhbHVlcyBvZiB0aGlzIGNvbGxlY3Rpb24sIGFuZCBjYWNoZXMgaXQgaW50ZXJuYWxseS4gVGhlIGFycmF5IHdpbGwgb25seSBiZVxuXHQgKiByZWNvbnN0cnVjdGVkIGlmIGFuIGl0ZW0gaXMgYWRkZWQgdG8gb3IgcmVtb3ZlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLCBvciBpZiB5b3UgY2hhbmdlIHRoZSBsZW5ndGggb2YgdGhlIGFycmF5XG5cdCAqIGl0c2VsZi4gSWYgeW91IGRvbid0IHdhbnQgdGhpcyBjYWNoaW5nIGJlaGF2aW9yLCB1c2UgYFsuLi5jb2xsZWN0aW9uLnZhbHVlcygpXWAgb3Jcblx0ICogYEFycmF5LmZyb20oY29sbGVjdGlvbi52YWx1ZXMoKSlgIGluc3RlYWQuXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICovXG5cdHB1YmxpYyBhcnJheSgpOiBWW10ge1xuXHRcdGlmICghdGhpcy5fYXJyYXkgfHwgdGhpcy5fYXJyYXkubGVuZ3RoICE9PSB0aGlzLnNpemUpIHRoaXMuX2FycmF5ID0gWy4uLnRoaXMudmFsdWVzKCldO1xuXHRcdHJldHVybiB0aGlzLl9hcnJheTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIG9yZGVyZWQgYXJyYXkgb2YgdGhlIGtleXMgb2YgdGhpcyBjb2xsZWN0aW9uLCBhbmQgY2FjaGVzIGl0IGludGVybmFsbHkuIFRoZSBhcnJheSB3aWxsIG9ubHkgYmVcblx0ICogcmVjb25zdHJ1Y3RlZCBpZiBhbiBpdGVtIGlzIGFkZGVkIHRvIG9yIHJlbW92ZWQgZnJvbSB0aGUgY29sbGVjdGlvbiwgb3IgaWYgeW91IGNoYW5nZSB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheVxuXHQgKiBpdHNlbGYuIElmIHlvdSBkb24ndCB3YW50IHRoaXMgY2FjaGluZyBiZWhhdmlvciwgdXNlIGBbLi4uY29sbGVjdGlvbi5rZXlzKCldYCBvclxuXHQgKiBgQXJyYXkuZnJvbShjb2xsZWN0aW9uLmtleXMoKSlgIGluc3RlYWQuXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICovXG5cdHB1YmxpYyBrZXlBcnJheSgpOiBLW10ge1xuXHRcdGlmICghdGhpcy5fa2V5QXJyYXkgfHwgdGhpcy5fa2V5QXJyYXkubGVuZ3RoICE9PSB0aGlzLnNpemUpIHRoaXMuX2tleUFycmF5ID0gWy4uLnRoaXMua2V5cygpXTtcblx0XHRyZXR1cm4gdGhpcy5fa2V5QXJyYXk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB0aGUgZmlyc3QgdmFsdWUocykgaW4gdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF0gQW1vdW50IG9mIHZhbHVlcyB0byBvYnRhaW4gZnJvbSB0aGUgYmVnaW5uaW5nXG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSB2YWx1ZSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2YgdmFsdWVzLCBzdGFydGluZyBmcm9tIHRoZSBlbmQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgZmlyc3QoKTogViB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpcnN0KGFtb3VudDogbnVtYmVyKTogVltdO1xuXHRwdWJsaWMgZmlyc3QoYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gdGhpcy52YWx1ZXMoKS5uZXh0KCkudmFsdWU7XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmxhc3QoYW1vdW50ICogLTEpO1xuXHRcdGFtb3VudCA9IE1hdGgubWluKHRoaXMuc2l6ZSwgYW1vdW50KTtcblx0XHRjb25zdCBpdGVyID0gdGhpcy52YWx1ZXMoKTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogYW1vdW50IH0sICgpOiBWID0+IGl0ZXIubmV4dCgpLnZhbHVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBPYnRhaW5zIHRoZSBmaXJzdCBrZXkocykgaW4gdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF0gQW1vdW50IG9mIGtleXMgdG8gb2J0YWluIGZyb20gdGhlIGJlZ2lubmluZ1xuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUga2V5IGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheSBvZiBrZXlzLCBzdGFydGluZyBmcm9tIHRoZSBlbmQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgZmlyc3RLZXkoKTogSyB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpcnN0S2V5KGFtb3VudDogbnVtYmVyKTogS1tdO1xuXHRwdWJsaWMgZmlyc3RLZXkoYW1vdW50PzogbnVtYmVyKTogSyB8IEtbXSB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gdGhpcy5rZXlzKCkubmV4dCgpLnZhbHVlO1xuXHRcdGlmIChhbW91bnQgPCAwKSByZXR1cm4gdGhpcy5sYXN0S2V5KGFtb3VudCAqIC0xKTtcblx0XHRhbW91bnQgPSBNYXRoLm1pbih0aGlzLnNpemUsIGFtb3VudCk7XG5cdFx0Y29uc3QgaXRlciA9IHRoaXMua2V5cygpO1xuXHRcdHJldHVybiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBhbW91bnQgfSwgKCk6IEsgPT4gaXRlci5uZXh0KCkudmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdGhlIGxhc3QgdmFsdWUocykgaW4gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNhcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiB2YWx1ZXMgdG8gb2J0YWluIGZyb20gdGhlIGVuZFxuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUgdmFsdWUgaWYgbm8gYW1vdW50IGlzIHByb3ZpZGVkIG9yIGFuIGFycmF5IG9mIHZhbHVlcywgc3RhcnRpbmcgZnJvbSB0aGUgc3RhcnQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgbGFzdCgpOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgbGFzdChhbW91bnQ6IG51bWJlcik6IFZbXTtcblx0cHVibGljIGxhc3QoYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgYXJyID0gdGhpcy5hcnJheSgpO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmZpcnN0KGFtb3VudCAqIC0xKTtcblx0XHRpZiAoIWFtb3VudCkgcmV0dXJuIFtdO1xuXHRcdHJldHVybiBhcnIuc2xpY2UoLWFtb3VudCk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB0aGUgbGFzdCBrZXkocykgaW4gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNrZXlBcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiBrZXlzIHRvIG9idGFpbiBmcm9tIHRoZSBlbmRcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIGtleSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2Yga2V5cywgc3RhcnRpbmcgZnJvbSB0aGUgc3RhcnQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgbGFzdEtleSgpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgbGFzdEtleShhbW91bnQ6IG51bWJlcik6IEtbXTtcblx0cHVibGljIGxhc3RLZXkoYW1vdW50PzogbnVtYmVyKTogSyB8IEtbXSB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgYXJyID0gdGhpcy5rZXlBcnJheSgpO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmZpcnN0S2V5KGFtb3VudCAqIC0xKTtcblx0XHRpZiAoIWFtb3VudCkgcmV0dXJuIFtdO1xuXHRcdHJldHVybiBhcnIuc2xpY2UoLWFtb3VudCk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB1bmlxdWUgcmFuZG9tIHZhbHVlKHMpIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNhcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiB2YWx1ZXMgdG8gb2J0YWluIHJhbmRvbWx5XG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSB2YWx1ZSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2YgdmFsdWVzXG5cdCAqL1xuXHRwdWJsaWMgcmFuZG9tKCk6IFY7XG5cdHB1YmxpYyByYW5kb20oYW1vdW50OiBudW1iZXIpOiBWW107XG5cdHB1YmxpYyByYW5kb20oYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB7XG5cdFx0bGV0IGFyciA9IHRoaXMuYXJyYXkoKTtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBhcnJbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyLmxlbmd0aCldO1xuXHRcdGlmIChhcnIubGVuZ3RoID09PSAwIHx8ICFhbW91bnQpIHJldHVybiBbXTtcblx0XHRhcnIgPSBhcnIuc2xpY2UoKTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogYW1vdW50IH0sICgpOiBWID0+IGFyci5zcGxpY2UoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyLmxlbmd0aCksIDEpWzBdKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBPYnRhaW5zIHVuaXF1ZSByYW5kb20ga2V5KHMpIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNrZXlBcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiBrZXlzIHRvIG9idGFpbiByYW5kb21seVxuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUga2V5IGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheVxuXHQgKi9cblx0cHVibGljIHJhbmRvbUtleSgpOiBLO1xuXHRwdWJsaWMgcmFuZG9tS2V5KGFtb3VudDogbnVtYmVyKTogS1tdO1xuXHRwdWJsaWMgcmFuZG9tS2V5KGFtb3VudD86IG51bWJlcik6IEsgfCBLW10ge1xuXHRcdGxldCBhcnIgPSB0aGlzLmtleUFycmF5KCk7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gYXJyW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpXTtcblx0XHRpZiAoYXJyLmxlbmd0aCA9PT0gMCB8fCAhYW1vdW50KSByZXR1cm4gW107XG5cdFx0YXJyID0gYXJyLnNsaWNlKCk7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IGFtb3VudCB9LCAoKTogSyA9PiBhcnIuc3BsaWNlKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpLCAxKVswXSk7XG5cdH1cblxuXHQvKipcblx0ICogU2VhcmNoZXMgZm9yIGEgc2luZ2xlIGl0ZW0gd2hlcmUgdGhlIGdpdmVuIGZ1bmN0aW9uIHJldHVybnMgYSB0cnV0aHkgdmFsdWUuIFRoaXMgYmVoYXZlcyBsaWtlXG5cdCAqIFtBcnJheS5maW5kKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbmQpLlxuXHQgKiA8d2Fybj5BbGwgY29sbGVjdGlvbnMgdXNlZCBpbiBEaXNjb3JkLmpzIGFyZSBtYXBwZWQgdXNpbmcgdGhlaXIgYGlkYCBwcm9wZXJ0eSwgYW5kIGlmIHlvdSB3YW50IHRvIGZpbmQgYnkgaWQgeW91XG5cdCAqIHNob3VsZCB1c2UgdGhlIGBnZXRgIG1ldGhvZC4gU2VlXG5cdCAqIFtNRE5dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9nZXQpIGZvciBkZXRhaWxzLjwvd2Fybj5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIHRlc3Qgd2l0aCAoc2hvdWxkIHJldHVybiBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZpbmQodXNlciA9PiB1c2VyLnVzZXJuYW1lID09PSAnQm9iJyk7XG5cdCAqL1xuXHRwdWJsaWMgZmluZChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogViB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4gdmFsO1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNlYXJjaGVzIGZvciB0aGUga2V5IG9mIGEgc2luZ2xlIGl0ZW0gd2hlcmUgdGhlIGdpdmVuIGZ1bmN0aW9uIHJldHVybnMgYSB0cnV0aHkgdmFsdWUuIFRoaXMgYmVoYXZlcyBsaWtlXG5cdCAqIFtBcnJheS5maW5kSW5kZXgoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZmluZEluZGV4KSxcblx0ICogYnV0IHJldHVybnMgdGhlIGtleSByYXRoZXIgdGhhbiB0aGUgcG9zaXRpb25hbCBpbmRleC5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIHRlc3Qgd2l0aCAoc2hvdWxkIHJldHVybiBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZpbmRLZXkodXNlciA9PiB1c2VyLnVzZXJuYW1lID09PSAnQm9iJyk7XG5cdCAqL1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleTxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogSyB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4ga2V5O1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgaXRlbXMgdGhhdCBzYXRpc2Z5IHRoZSBwcm92aWRlZCBmaWx0ZXIgZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gdGVzdCAoc2hvdWxkIHJldHVybiBhIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge251bWJlcn0gVGhlIG51bWJlciBvZiByZW1vdmVkIGVudHJpZXNcblx0ICovXG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogbnVtYmVyIHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Y29uc3QgcHJldmlvdXNTaXplID0gdGhpcy5zaXplO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSB0aGlzLmRlbGV0ZShrZXkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcHJldmlvdXNTaXplIC0gdGhpcy5zaXplO1xuXHR9XG5cblx0LyoqXG5cdCAqIElkZW50aWNhbCB0b1xuXHQgKiBbQXJyYXkuZmlsdGVyKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbHRlciksXG5cdCAqIGJ1dCByZXR1cm5zIGEgQ29sbGVjdGlvbiBpbnN0ZWFkIG9mIGFuIEFycmF5LlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gdGVzdCB3aXRoIChzaG91bGQgcmV0dXJuIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24uZmlsdGVyKHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gJ0JvYicpO1xuXHQgKi9cblx0cHVibGljIGZpbHRlcihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiB0aGlzO1xuXHRwdWJsaWMgZmlsdGVyPFQ+KGZuOiAodGhpczogVCwgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZzogVCk6IHRoaXM7XG5cdHB1YmxpYyBmaWx0ZXIoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCByZXN1bHRzID0gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdPEssIFY+KCkgYXMgdGhpcztcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmVzdWx0cy5zZXQoa2V5LCB2YWwpO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0cztcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJ0aXRpb25zIHRoZSBjb2xsZWN0aW9uIGludG8gdHdvIGNvbGxlY3Rpb25zIHdoZXJlIHRoZSBmaXJzdCBjb2xsZWN0aW9uXG5cdCAqIGNvbnRhaW5zIHRoZSBpdGVtcyB0aGF0IHBhc3NlZCBhbmQgdGhlIHNlY29uZCBjb250YWlucyB0aGUgaXRlbXMgdGhhdCBmYWlsZWQuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gdGVzdCAoc2hvdWxkIHJldHVybiBhIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb25bXX1cblx0ICogQGV4YW1wbGUgY29uc3QgW2JpZywgc21hbGxdID0gY29sbGVjdGlvbi5wYXJ0aXRpb24oZ3VpbGQgPT4gZ3VpbGQubWVtYmVyQ291bnQgPiAyNTApO1xuXHQgKi9cblx0cHVibGljIHBhcnRpdGlvbihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBbdGhpcywgdGhpc107XG5cdHB1YmxpYyBwYXJ0aXRpb248VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogW3RoaXMsIHRoaXNdO1xuXHRwdWJsaWMgcGFydGl0aW9uKGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZz86IHVua25vd24pOiBbdGhpcywgdGhpc10ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHQvLyBUT0RPOiBjb25zaWRlciByZW1vdmluZyB0aGUgPEssIFY+IGZyb20gdGhlIGNvbnN0cnVjdG9ycyBhZnRlciBUUyAzLjcuMCBpcyByZWxlYXNlZCwgYXMgaXQgaW5mZXJzIGl0XG5cdFx0Y29uc3QgcmVzdWx0czogW3RoaXMsIHRoaXNdID0gW25ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpIGFzIHRoaXMsIG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpIGFzIHRoaXNdO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSB7XG5cdFx0XHRcdHJlc3VsdHNbMF0uc2V0KGtleSwgdmFsKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlc3VsdHNbMV0uc2V0KGtleSwgdmFsKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvKipcblx0ICogTWFwcyBlYWNoIGl0ZW0gaW50byBhIENvbGxlY3Rpb24sIHRoZW4gam9pbnMgdGhlIHJlc3VsdHMgaW50byBhIHNpbmdsZSBDb2xsZWN0aW9uLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5LmZsYXRNYXAoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZmxhdE1hcCkuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYSBuZXcgQ29sbGVjdGlvblxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZsYXRNYXAoZ3VpbGQgPT4gZ3VpbGQubWVtYmVycy5jYWNoZSk7XG5cdCAqL1xuXHRwdWJsaWMgZmxhdE1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4pOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgZmxhdE1hcDxULCBUaGlzPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4sIHRoaXNBcmc6IFRoaXMpOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgZmxhdE1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4sIHRoaXNBcmc/OiB1bmtub3duKTogQ29sbGVjdGlvbjxLLCBUPiB7XG5cdFx0Y29uc3QgY29sbGVjdGlvbnMgPSB0aGlzLm1hcChmbiwgdGhpc0FyZyk7XG5cdFx0cmV0dXJuIChuZXcgdGhpcy5jb25zdHJ1Y3RvcltTeW1ib2wuc3BlY2llc108SywgVD4oKSBhcyBDb2xsZWN0aW9uPEssIFQ+KS5jb25jYXQoLi4uY29sbGVjdGlvbnMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1hcHMgZWFjaCBpdGVtIHRvIGFub3RoZXIgdmFsdWUgaW50byBhbiBhcnJheS4gSWRlbnRpY2FsIGluIGJlaGF2aW9yIHRvXG5cdCAqIFtBcnJheS5tYXAoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvbWFwKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhbiBlbGVtZW50IG9mIHRoZSBuZXcgYXJyYXksIHRha2luZyB0aHJlZSBhcmd1bWVudHNcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7QXJyYXl9XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24ubWFwKHVzZXIgPT4gdXNlci50YWcpO1xuXHQgKi9cblx0cHVibGljIG1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQpOiBUW107XG5cdHB1YmxpYyBtYXA8VGhpcywgVD4oZm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnOiBUaGlzKTogVFtdO1xuXHRwdWJsaWMgbWFwPFQ+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgdGhpc0FyZz86IHVua25vd24pOiBUW10ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCBpdGVyID0gdGhpcy5lbnRyaWVzKCk7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMuc2l6ZSB9LCAoKTogVCA9PiB7XG5cdFx0XHRjb25zdCBba2V5LCB2YWx1ZV0gPSBpdGVyLm5leHQoKS52YWx1ZTtcblx0XHRcdHJldHVybiBmbih2YWx1ZSwga2V5LCB0aGlzKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXBzIGVhY2ggaXRlbSB0byBhbm90aGVyIHZhbHVlIGludG8gYSBjb2xsZWN0aW9uLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5Lm1hcCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9tYXApLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGVsZW1lbnQgb2YgdGhlIG5ldyBjb2xsZWN0aW9uLCB0YWtpbmcgdGhyZWUgYXJndW1lbnRzXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24ubWFwVmFsdWVzKHVzZXIgPT4gdXNlci50YWcpO1xuXHQgKi9cblx0cHVibGljIG1hcFZhbHVlczxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQpOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgbWFwVmFsdWVzPFRoaXMsIFQ+KGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgdGhpc0FyZzogVGhpcyk6IENvbGxlY3Rpb248SywgVD47XG5cdHB1YmxpYyBtYXBWYWx1ZXM8VD4oZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnPzogdW5rbm93bik6IENvbGxlY3Rpb248SywgVD4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCBjb2xsID0gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdPEssIFQ+KCkgYXMgQ29sbGVjdGlvbjxLLCBUPjtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykgY29sbC5zZXQoa2V5LCBmbih2YWwsIGtleSwgdGhpcykpO1xuXHRcdHJldHVybiBjb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGVyZSBleGlzdHMgYW4gaXRlbSB0aGF0IHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuc29tZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9zb21lKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdXNlZCB0byB0ZXN0IChzaG91bGQgcmV0dXJuIGEgYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5zb21lKHVzZXIgPT4gdXNlci5kaXNjcmltaW5hdG9yID09PSAnMDAwMCcpO1xuXHQgKi9cblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWU8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IGJvb2xlYW4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgYWxsIGl0ZW1zIHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuZXZlcnkoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZXZlcnkpLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB1c2VkIHRvIHRlc3QgKHNob3VsZCByZXR1cm4gYSBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmV2ZXJ5KHVzZXIgPT4gIXVzZXIuYm90KTtcblx0ICovXG5cdHB1YmxpYyBldmVyeShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBib29sZWFuO1xuXHRwdWJsaWMgZXZlcnk8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogYm9vbGVhbjtcblx0cHVibGljIGV2ZXJ5KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZz86IHVua25vd24pOiBib29sZWFuIHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWxdIG9mIHRoaXMpIHtcblx0XHRcdGlmICghZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFwcGxpZXMgYSBmdW5jdGlvbiB0byBwcm9kdWNlIGEgc2luZ2xlIHZhbHVlLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5LnJlZHVjZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9yZWR1Y2UpLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB1c2VkIHRvIHJlZHVjZSwgdGFraW5nIGZvdXIgYXJndW1lbnRzOyBgYWNjdW11bGF0b3JgLCBgY3VycmVudFZhbHVlYCwgYGN1cnJlbnRLZXlgLFxuXHQgKiBhbmQgYGNvbGxlY3Rpb25gXG5cdCAqIEBwYXJhbSB7Kn0gW2luaXRpYWxWYWx1ZV0gU3RhcnRpbmcgdmFsdWUgZm9yIHRoZSBhY2N1bXVsYXRvclxuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5yZWR1Y2UoKGFjYywgZ3VpbGQpID0+IGFjYyArIGd1aWxkLm1lbWJlckNvdW50LCAwKTtcblx0ICovXG5cdHB1YmxpYyByZWR1Y2U8VD4oZm46IChhY2N1bXVsYXRvcjogVCwgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgaW5pdGlhbFZhbHVlPzogVCk6IFQge1xuXHRcdGxldCBhY2N1bXVsYXRvciE6IFQ7XG5cblx0XHRpZiAodHlwZW9mIGluaXRpYWxWYWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdGFjY3VtdWxhdG9yID0gaW5pdGlhbFZhbHVlO1xuXHRcdFx0Zm9yIChjb25zdCBba2V5LCB2YWxdIG9mIHRoaXMpIGFjY3VtdWxhdG9yID0gZm4oYWNjdW11bGF0b3IsIHZhbCwga2V5LCB0aGlzKTtcblx0XHRcdHJldHVybiBhY2N1bXVsYXRvcjtcblx0XHR9XG5cdFx0bGV0IGZpcnN0ID0gdHJ1ZTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZpcnN0KSB7XG5cdFx0XHRcdGFjY3VtdWxhdG9yID0gdmFsIGFzIHVua25vd24gYXMgVDtcblx0XHRcdFx0Zmlyc3QgPSBmYWxzZTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRhY2N1bXVsYXRvciA9IGZuKGFjY3VtdWxhdG9yLCB2YWwsIGtleSwgdGhpcyk7XG5cdFx0fVxuXG5cdFx0Ly8gTm8gaXRlbXMgaXRlcmF0ZWQuXG5cdFx0aWYgKGZpcnN0KSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdSZWR1Y2Ugb2YgZW1wdHkgY29sbGVjdGlvbiB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gYWNjdW11bGF0b3I7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvXG5cdCAqIFtNYXAuZm9yRWFjaCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvZm9yRWFjaCksXG5cdCAqIGJ1dCByZXR1cm5zIHRoZSBjb2xsZWN0aW9uIGluc3RlYWQgb2YgdW5kZWZpbmVkLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBleGVjdXRlIGZvciBlYWNoIGVsZW1lbnRcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGVcblx0ICogY29sbGVjdGlvblxuXHQgKiAgLmVhY2godXNlciA9PiBjb25zb2xlLmxvZyh1c2VyLnVzZXJuYW1lKSlcblx0ICogIC5maWx0ZXIodXNlciA9PiB1c2VyLmJvdClcblx0ICogIC5lYWNoKHVzZXIgPT4gY29uc29sZS5sb2codXNlci51c2VybmFtZSkpO1xuXHQgKi9cblx0cHVibGljIGVhY2goZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkKTogdGhpcztcblx0cHVibGljIGVhY2g8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnOiBUKTogdGhpcztcblx0cHVibGljIGVhY2goZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdHRoaXMuZm9yRWFjaChmbiBhcyAodmFsdWU6IFYsIGtleTogSywgbWFwOiBNYXA8SywgVj4pID0+IHZvaWQsIHRoaXNBcmcpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgYSBmdW5jdGlvbiBvbiB0aGUgY29sbGVjdGlvbiBhbmQgcmV0dXJucyB0aGUgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gZXhlY3V0ZVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBjb2xsZWN0aW9uXG5cdCAqICAudGFwKGNvbGwgPT4gY29uc29sZS5sb2coY29sbC5zaXplKSlcblx0ICogIC5maWx0ZXIodXNlciA9PiB1c2VyLmJvdClcblx0ICogIC50YXAoY29sbCA9PiBjb25zb2xlLmxvZyhjb2xsLnNpemUpKVxuXHQgKi9cblx0cHVibGljIHRhcChmbjogKGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQpOiB0aGlzO1xuXHRwdWJsaWMgdGFwPFQ+KGZuOiAodGhpczogVCwgY29sbGVjdGlvbjogdGhpcykgPT4gdm9pZCwgdGhpc0FyZzogVCk6IHRoaXM7XG5cdHB1YmxpYyB0YXAoZm46IChjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmbih0aGlzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGlkZW50aWNhbCBzaGFsbG93IGNvcHkgb2YgdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGUgY29uc3QgbmV3Q29sbCA9IHNvbWVDb2xsLmNsb25lKCk7XG5cdCAqL1xuXHRwdWJsaWMgY2xvbmUoKTogdGhpcyB7XG5cdFx0cmV0dXJuIG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXSh0aGlzKSBhcyB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbWJpbmVzIHRoaXMgY29sbGVjdGlvbiB3aXRoIG90aGVycyBpbnRvIGEgbmV3IGNvbGxlY3Rpb24uIE5vbmUgb2YgdGhlIHNvdXJjZSBjb2xsZWN0aW9ucyBhcmUgbW9kaWZpZWQuXG5cdCAqIEBwYXJhbSB7Li4uQ29sbGVjdGlvbn0gY29sbGVjdGlvbnMgQ29sbGVjdGlvbnMgdG8gbWVyZ2Vcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbnN0IG5ld0NvbGwgPSBzb21lQ29sbC5jb25jYXQoc29tZU90aGVyQ29sbCwgYW5vdGhlckNvbGwsIG9oQm95QUNvbGwpO1xuXHQgKi9cblx0cHVibGljIGNvbmNhdCguLi5jb2xsZWN0aW9uczogQ29sbGVjdGlvbjxLLCBWPltdKTogdGhpcyB7XG5cdFx0Y29uc3QgbmV3Q29sbCA9IHRoaXMuY2xvbmUoKTtcblx0XHRmb3IgKGNvbnN0IGNvbGwgb2YgY29sbGVjdGlvbnMpIHtcblx0XHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBjb2xsKSBuZXdDb2xsLnNldChrZXksIHZhbCk7XG5cdFx0fVxuXHRcdHJldHVybiBuZXdDb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGNvbGxlY3Rpb24gc2hhcmVzIGlkZW50aWNhbCBpdGVtcyB3aXRoIGFub3RoZXIuXG5cdCAqIFRoaXMgaXMgZGlmZmVyZW50IHRvIGNoZWNraW5nIGZvciBlcXVhbGl0eSB1c2luZyBlcXVhbC1zaWducywgYmVjYXVzZVxuXHQgKiB0aGUgY29sbGVjdGlvbnMgbWF5IGJlIGRpZmZlcmVudCBvYmplY3RzLCBidXQgY29udGFpbiB0aGUgc2FtZSBkYXRhLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IGNvbGxlY3Rpb24gQ29sbGVjdGlvbiB0byBjb21wYXJlIHdpdGhcblx0ICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGNvbGxlY3Rpb25zIGhhdmUgaWRlbnRpY2FsIGNvbnRlbnRzXG5cdCAqL1xuXHRwdWJsaWMgZXF1YWxzKGNvbGxlY3Rpb246IENvbGxlY3Rpb248SywgVj4pOiBib29sZWFuIHtcblx0XHRpZiAoIWNvbGxlY3Rpb24pIHJldHVybiBmYWxzZTtcblx0XHRpZiAodGhpcyA9PT0gY29sbGVjdGlvbikgcmV0dXJuIHRydWU7XG5cdFx0aWYgKHRoaXMuc2l6ZSAhPT0gY29sbGVjdGlvbi5zaXplKSByZXR1cm4gZmFsc2U7XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcykge1xuXHRcdFx0aWYgKCFjb2xsZWN0aW9uLmhhcyhrZXkpIHx8IHZhbHVlICE9PSBjb2xsZWN0aW9uLmdldChrZXkpKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHNvcnQgbWV0aG9kIHNvcnRzIHRoZSBpdGVtcyBvZiBhIGNvbGxlY3Rpb24gaW4gcGxhY2UgYW5kIHJldHVybnMgaXQuXG5cdCAqIFRoZSBzb3J0IGlzIG5vdCBuZWNlc3NhcmlseSBzdGFibGUgaW4gTm9kZSAxMCBvciBvbGRlci5cblx0ICogVGhlIGRlZmF1bHQgc29ydCBvcmRlciBpcyBhY2NvcmRpbmcgdG8gc3RyaW5nIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJlRnVuY3Rpb25dIFNwZWNpZmllcyBhIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgc29ydCBvcmRlci5cblx0ICogSWYgb21pdHRlZCwgdGhlIGNvbGxlY3Rpb24gaXMgc29ydGVkIGFjY29yZGluZyB0byBlYWNoIGNoYXJhY3RlcidzIFVuaWNvZGUgY29kZSBwb2ludCB2YWx1ZSxcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBzdHJpbmcgY29udmVyc2lvbiBvZiBlYWNoIGVsZW1lbnQuXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnNvcnQoKHVzZXJBLCB1c2VyQikgPT4gdXNlckEuY3JlYXRlZFRpbWVzdGFtcCAtIHVzZXJCLmNyZWF0ZWRUaW1lc3RhbXApO1xuXHQgKi9cblx0cHVibGljIHNvcnQoY29tcGFyZUZ1bmN0aW9uOiAoZmlyc3RWYWx1ZTogViwgc2Vjb25kVmFsdWU6IFYsIGZpcnN0S2V5OiBLLCBzZWNvbmRLZXk6IEspID0+IG51bWJlciA9ICh4LCB5KTogbnVtYmVyID0+IE51bWJlcih4ID4geSkgfHwgTnVtYmVyKHggPT09IHkpIC0gMSk6IHRoaXMge1xuXHRcdGNvbnN0IGVudHJpZXMgPSBbLi4udGhpcy5lbnRyaWVzKCldO1xuXHRcdGVudHJpZXMuc29ydCgoYSwgYik6IG51bWJlciA9PiBjb21wYXJlRnVuY3Rpb24oYVsxXSwgYlsxXSwgYVswXSwgYlswXSkpO1xuXG5cdFx0Ly8gUGVyZm9ybSBjbGVhbi11cFxuXHRcdHN1cGVyLmNsZWFyKCk7XG5cdFx0dGhpcy5fYXJyYXkgPSBudWxsO1xuXHRcdHRoaXMuX2tleUFycmF5ID0gbnVsbDtcblxuXHRcdC8vIFNldCB0aGUgbmV3IGVudHJpZXNcblx0XHRmb3IgKGNvbnN0IFtrLCB2XSBvZiBlbnRyaWVzKSB7XG5cdFx0XHRzdXBlci5zZXQoaywgdik7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBpbnRlcnNlY3QgbWV0aG9kIHJldHVybnMgYSBuZXcgc3RydWN0dXJlIGNvbnRhaW5pbmcgaXRlbXMgd2hlcmUgdGhlIGtleXMgYXJlIHByZXNlbnQgaW4gYm90aCBvcmlnaW5hbCBzdHJ1Y3R1cmVzLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IG90aGVyIFRoZSBvdGhlciBDb2xsZWN0aW9uIHRvIGZpbHRlciBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIGludGVyc2VjdChvdGhlcjogQ29sbGVjdGlvbjxLLCBWPik6IENvbGxlY3Rpb248SywgVj4ge1xuXHRcdHJldHVybiBvdGhlci5maWx0ZXIoKF8sIGspID0+IHRoaXMuaGFzKGspKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgZGlmZmVyZW5jZSBtZXRob2QgcmV0dXJucyBhIG5ldyBzdHJ1Y3R1cmUgY29udGFpbmluZyBpdGVtcyB3aGVyZSB0aGUga2V5IGlzIHByZXNlbnQgaW4gb25lIG9mIHRoZSBvcmlnaW5hbCBzdHJ1Y3R1cmVzIGJ1dCBub3QgdGhlIG90aGVyLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IG90aGVyIFRoZSBvdGhlciBDb2xsZWN0aW9uIHRvIGZpbHRlciBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIGRpZmZlcmVuY2Uob3RoZXI6IENvbGxlY3Rpb248SywgVj4pOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRyZXR1cm4gb3RoZXIuZmlsdGVyKChfLCBrKSA9PiAhdGhpcy5oYXMoaykpLmNvbmNhdCh0aGlzLmZpbHRlcigoXywgaykgPT4gIW90aGVyLmhhcyhrKSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzb3J0ZWQgbWV0aG9kIHNvcnRzIHRoZSBpdGVtcyBvZiBhIGNvbGxlY3Rpb24gYW5kIHJldHVybnMgaXQuXG5cdCAqIFRoZSBzb3J0IGlzIG5vdCBuZWNlc3NhcmlseSBzdGFibGUgaW4gTm9kZSAxMCBvciBvbGRlci5cblx0ICogVGhlIGRlZmF1bHQgc29ydCBvcmRlciBpcyBhY2NvcmRpbmcgdG8gc3RyaW5nIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJlRnVuY3Rpb25dIFNwZWNpZmllcyBhIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgc29ydCBvcmRlci5cblx0ICogSWYgb21pdHRlZCwgdGhlIGNvbGxlY3Rpb24gaXMgc29ydGVkIGFjY29yZGluZyB0byBlYWNoIGNoYXJhY3RlcidzIFVuaWNvZGUgY29kZSBwb2ludCB2YWx1ZSxcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBzdHJpbmcgY29udmVyc2lvbiBvZiBlYWNoIGVsZW1lbnQuXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnNvcnRlZCgodXNlckEsIHVzZXJCKSA9PiB1c2VyQS5jcmVhdGVkVGltZXN0YW1wIC0gdXNlckIuY3JlYXRlZFRpbWVzdGFtcCk7XG5cdCAqL1xuXHRwdWJsaWMgc29ydGVkKGNvbXBhcmVGdW5jdGlvbjogKGZpcnN0VmFsdWU6IFYsIHNlY29uZFZhbHVlOiBWLCBmaXJzdEtleTogSywgc2Vjb25kS2V5OiBLKSA9PiBudW1iZXIgPSAoeCwgeSk6IG51bWJlciA9PiBOdW1iZXIoeCA+IHkpIHx8IE51bWJlcih4ID09PSB5KSAtIDEpOiB0aGlzIHtcblx0XHRyZXR1cm4gKG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXShbLi4udGhpcy5lbnRyaWVzKCldKSBhcyB0aGlzKVxuXHRcdFx0LnNvcnQoKGF2LCBidiwgYWssIGJrKSA9PiBjb21wYXJlRnVuY3Rpb24oYXYsIGJ2LCBhaywgYmspKTtcblx0fVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxlY3Rpb247XG5leHBvcnQgeyBDb2xsZWN0aW9uIH07XG5leHBvcnQgZGVmYXVsdCBDb2xsZWN0aW9uO1xuIl19 \ No newline at end of file diff --git a/node_modules/@discordjs/collection/package.json b/node_modules/@discordjs/collection/package.json new file mode 100644 index 0000000..ebb4898 --- /dev/null +++ b/node_modules/@discordjs/collection/package.json @@ -0,0 +1,49 @@ +{ + "name": "@discordjs/collection", + "version": "0.1.6", + "description": "Utility data structure used in Discord.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "lint": "eslint src --ext .ts", + "prebuild": "npm run lint", + "build": "rimraf dist/ && tsc", + "pretest": "npm run build", + "test": "node test/index.js", + "docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json", + "docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/discordjs/collection.git" + }, + "keywords": [ + "map", + "collection", + "utility" + ], + "author": "Amish Shah ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/discordjs/collection/issues" + }, + "homepage": "https://github.com/discordjs/collection#readme", + "devDependencies": { + "@babel/cli": "^7.8.4", + "@babel/core": "^7.8.4", + "@babel/preset-env": "^7.8.4", + "@babel/preset-typescript": "^7.8.3", + "@types/node": "^13.7.4", + "@typescript-eslint/eslint-plugin": "^2.21.0", + "@typescript-eslint/parser": "^2.21.0", + "discord.js-docgen": "discordjs/docgen#ts-patch", + "eslint": "^6.8.0", + "eslint-config-marine": "^6.0.0", + "jsdoc-babel": "^0.5.0", + "rimraf": "^3.0.2", + "typescript": "^3.8.2" + }, + "eslintConfig": { + "extends": "marine/node" + } +} diff --git a/node_modules/@discordjs/form-data/License b/node_modules/@discordjs/form-data/License new file mode 100644 index 0000000..c7ff12a --- /dev/null +++ b/node_modules/@discordjs/form-data/License @@ -0,0 +1,19 @@ +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/node_modules/@discordjs/form-data/Readme.md b/node_modules/@discordjs/form-data/Readme.md new file mode 100644 index 0000000..3d8c93a --- /dev/null +++ b/node_modules/@discordjs/form-data/Readme.md @@ -0,0 +1,353 @@ +# Form-Data [![NPM Module](https://img.shields.io/npm/v/form-data.svg)](https://www.npmjs.com/package/form-data) [![Join the chat at https://gitter.im/form-data/form-data](http://form-data.github.io/images/gitterbadge.svg)](https://gitter.im/form-data/form-data) + +A library to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications. + +The API of this library is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd]. + +[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface + +[![Linux Build](https://img.shields.io/travis/form-data/form-data/master.svg?label=linux:6.x-12.x)](https://travis-ci.org/form-data/form-data) +[![MacOS Build](https://img.shields.io/travis/form-data/form-data/master.svg?label=macos:6.x-12.x)](https://travis-ci.org/form-data/form-data) +[![Windows Build](https://img.shields.io/travis/form-data/form-data/master.svg?label=windows:6.x-12.x)](https://travis-ci.org/form-data/form-data) + +[![Coverage Status](https://img.shields.io/coveralls/form-data/form-data/master.svg?label=code+coverage)](https://coveralls.io/github/form-data/form-data?branch=master) +[![Dependency Status](https://img.shields.io/david/form-data/form-data.svg)](https://david-dm.org/form-data/form-data) + +## Install + +``` +npm install --save form-data +``` + +## Usage + +In this example we are constructing a form with 3 fields that contain a string, +a buffer and a file stream. + +``` javascript +var FormData = require('form-data'); +var fs = require('fs'); + +var form = new FormData(); +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_file', fs.createReadStream('/foo/bar.jpg')); +``` + +Also you can use http-response stream: + +``` javascript +var FormData = require('form-data'); +var http = require('http'); + +var form = new FormData(); + +http.request('http://nodejs.org/images/logo.png', function(response) { + form.append('my_field', 'my value'); + form.append('my_buffer', new Buffer(10)); + form.append('my_logo', response); +}); +``` + +Or @mikeal's [request](https://github.com/request/request) stream: + +``` javascript +var FormData = require('form-data'); +var request = require('request'); + +var form = new FormData(); + +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_logo', request('http://nodejs.org/images/logo.png')); +``` + +In order to submit this form to a web application, call ```submit(url, [callback])``` method: + +``` javascript +form.submit('http://example.org/', function(err, res) { + // res – response object (http.IncomingMessage) // + res.resume(); +}); + +``` + +For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods. + +### Custom options + +You can provide custom options, such as `maxDataSize`: + +``` javascript +var FormData = require('form-data'); + +var form = new FormData({ maxDataSize: 20971520 }); +form.append('my_field', 'my value'); +form.append('my_buffer', /* something big */); +``` + +List of available options could be found in [combined-stream](https://github.com/felixge/node-combined-stream/blob/master/lib/combined_stream.js#L7-L15) + +### Alternative submission methods + +You can use node's http client interface: + +``` javascript +var http = require('http'); + +var request = http.request({ + method: 'post', + host: 'example.org', + path: '/upload', + headers: form.getHeaders() +}); + +form.pipe(request); + +request.on('response', function(res) { + console.log(res.statusCode); +}); +``` + +Or if you would prefer the `'Content-Length'` header to be set for you: + +``` javascript +form.submit('example.org/upload', function(err, res) { + console.log(res.statusCode); +}); +``` + +To use custom headers and pre-known length in parts: + +``` javascript +var CRLF = '\r\n'; +var form = new FormData(); + +var options = { + header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF, + knownLength: 1 +}; + +form.append('my_buffer', buffer, options); + +form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); +}); +``` + +Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually: + +``` javascript +someModule.stream(function(err, stdout, stderr) { + if (err) throw err; + + var form = new FormData(); + + form.append('file', stdout, { + filename: 'unicycle.jpg', // ... or: + filepath: 'photos/toys/unicycle.jpg', + contentType: 'image/jpeg', + knownLength: 19806 + }); + + form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); + }); +}); +``` + +The `filepath` property overrides `filename` and may contain a relative path. This is typically used when uploading [multiple files from a directory](https://wicg.github.io/entries-api/#dom-htmlinputelement-webkitdirectory). + +For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter: + +``` javascript +form.submit({ + host: 'example.com', + path: '/probably.php?extra=params', + auth: 'username:password' +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +In case you need to also send custom HTTP headers with the POST request, you can use the `headers` key in first parameter of `form.submit()`: + +``` javascript +form.submit({ + host: 'example.com', + path: '/surelynot.php', + headers: {'x-test-header': 'test-header-value'} +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +### Methods + +- [_Void_ append( **String** _field_, **Mixed** _value_ [, **Mixed** _options_] )](https://github.com/form-data/form-data#void-append-string-field-mixed-value--mixed-options-). +- [_Headers_ getHeaders( [**Headers** _userHeaders_] )](https://github.com/form-data/form-data#array-getheaders-array-userheaders-) +- [_String_ getBoundary()](https://github.com/form-data/form-data#string-getboundary) +- [_Buffer_ getBuffer()](https://github.com/form-data/form-data#buffer-getbuffer) +- [_Integer_ getLengthSync()](https://github.com/form-data/form-data#integer-getlengthsync) +- [_Integer_ getLength( **function** _callback_ )](https://github.com/form-data/form-data#integer-getlength-function-callback-) +- [_Boolean_ hasKnownLength()](https://github.com/form-data/form-data#boolean-hasknownlength) +- [_Request_ submit( _params_, **function** _callback_ )](https://github.com/form-data/form-data#request-submit-params-function-callback-) +- [_String_ toString()](https://github.com/form-data/form-data#string-tostring) + +#### _Void_ append( **String** _field_, **Mixed** _value_ [, **Mixed** _options_] ) +Append data to the form. You can submit about any format (string, integer, boolean, buffer, etc.). However, Arrays are not supported and need to be turned into strings by the user. +```javascript +var form = new FormData(); +form.append( 'my_string', 'my value' ); +form.append( 'my_integer', 1 ); +form.append( 'my_boolean', true ); +form.append( 'my_buffer', new Buffer(10) ); +form.append( 'my_array_as_json', JSON.stringify( ['bird','cute'] ) ) +``` + +You may provide a string for options, or an object. +```javascript +// Set filename by providing a string for options +form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), 'bar.jpg' ); + +// provide an object. +form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), {filename: 'bar.jpg', contentType: 'image/jpeg', knownLength: 19806} ); +``` + +#### _Headers_ getHeaders( [**Headers** _userHeaders_] ) +This method adds the correct `content-type` header to the provided array of `userHeaders`. + +#### _String_ getBoundary() +Return the boundary of the formData. A boundary consists of 26 `-` followed by 24 numbers +for example: +```javascript +--------------------------515890814546601021194782 +``` +_Note: The boundary must be unique and may not appear in the data._ + +#### _Buffer_ getBuffer() +Return the full formdata request package, as a Buffer. You can insert this Buffer in e.g. Axios to send multipart data. +```javascript +var form = new FormData(); +form.append( 'my_buffer', Buffer.from([0x4a,0x42,0x20,0x52,0x6f,0x63,0x6b,0x73]) ); +form.append( 'my_file', fs.readFileSync('/foo/bar.jpg') ); + +axios.post( 'https://example.com/path/to/api', + form.getBuffer(), + form.getHeaders() + ) +``` +**Note:** Because the output is of type Buffer, you can only append types that are accepted by Buffer: *string, Buffer, ArrayBuffer, Array, or Array-like Object*. A ReadStream for example will result in an error. + +#### _Integer_ getLengthSync() +Same as `getLength` but synchronous. + +_Note: getLengthSync __doesn't__ calculate streams length._ + +#### _Integer_ getLength( **function** _callback_ ) +Returns the `Content-Length` async. The callback is used to handle errors and continue once the length has been calculated +```javascript +this.getLength(function(err, length) { + if (err) { + this._error(err); + return; + } + + // add content length + request.setHeader('Content-Length', length); + + ... +}.bind(this)); +``` + +#### _Boolean_ hasKnownLength() +Checks if the length of added values is known. + +#### _Request_ submit( _params_, **function** _callback_ ) +Submit the form to a web application. +```javascript +var form = new FormData(); +form.append( 'my_string', 'Hello World' ); + +form.submit( 'http://example.com/', function(err, res) { + // res – response object (http.IncomingMessage) // + res.resume(); +} ); +``` + +#### _String_ toString() +Returns the form data as a string. Don't use this if you are sending files or buffers, use `getBuffer()` instead. + +### Integration with other libraries + +#### Request + +Form submission using [request](https://github.com/request/request): + +```javascript +var formData = { + my_field: 'my_value', + my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), +}; + +request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) { + if (err) { + return console.error('upload failed:', err); + } + console.log('Upload successful! Server responded with:', body); +}); +``` + +For more details see [request readme](https://github.com/request/request#multipartform-data-multipart-form-uploads). + +#### node-fetch + +You can also submit a form using [node-fetch](https://github.com/bitinn/node-fetch): + +```javascript +var form = new FormData(); + +form.append('a', 1); + +fetch('http://example.com', { method: 'POST', body: form }) + .then(function(res) { + return res.json(); + }).then(function(json) { + console.log(json); + }); +``` + +#### axios + +In Node.js you can post a file using [axios](https://github.com/axios/axios): +```javascript +const form = new FormData(); +const stream = fs.createReadStream(PATH_TO_FILE); + +form.append('image', stream); + +// In Node.js environment you need to set boundary in the header field 'Content-Type' by calling method `getHeaders` +const formHeaders = form.getHeaders(); + +axios.post('http://example.com', form, { + headers: { + ...formHeaders, + }, +}) +.then(response => response) +.catch(error => error) +``` + +## Notes + +- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround. +- ```getLength(cb)``` will send an error as first parameter of callback if stream length cannot be calculated (e.g. send in custom streams w/o using ```knownLength```). +- ```sbumit``` will not add `content-length` if form length is unknown or not calculable. +- Starting version `2.x` FormData has dropped support for `node@0.10.x`. +- Starting version `3.x` FormData has dropped support for `node@4.x`. + +## License + +Form-Data is released under the [MIT](License) license. diff --git a/node_modules/@discordjs/form-data/index.d.ts b/node_modules/@discordjs/form-data/index.d.ts new file mode 100644 index 0000000..6e52045 --- /dev/null +++ b/node_modules/@discordjs/form-data/index.d.ts @@ -0,0 +1,61 @@ +// Definitions by: Carlos Ballesteros Velasco +// Leon Yu +// BendingBender +// Maple Miao + +/// +import * as stream from 'stream'; +import * as http from 'http'; + +export = FormData; + +// Extracted because @types/node doesn't export interfaces. +interface ReadableOptions { + highWaterMark?: number; + encoding?: string; + objectMode?: boolean; + read?(this: stream.Readable, size: number): void; + destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void; + autoDestroy?: boolean; +} + +interface Options extends ReadableOptions { + writable?: boolean; + readable?: boolean; + dataSize?: number; + maxDataSize?: number; + pauseStreams?: boolean; +} + +declare class FormData extends stream.Readable { + constructor(options?: Options); + append(key: string, value: any, options?: FormData.AppendOptions | string): void; + getHeaders(userHeaders?: FormData.Headers): FormData.Headers; + submit( + params: string | FormData.SubmitOptions, + callback?: (error: Error | null, response: http.IncomingMessage) => void + ): http.ClientRequest; + getBuffer(): Buffer; + getBoundary(): string; + getLength(callback: (err: Error | null, length: number) => void): void; + getLengthSync(): number; + hasKnownLength(): boolean; +} + +declare namespace FormData { + interface Headers { + [key: string]: any; + } + + interface AppendOptions { + header?: string | Headers; + knownLength?: number; + filename?: string; + filepath?: string; + contentType?: string; + } + + interface SubmitOptions extends http.RequestOptions { + protocol?: 'https:' | 'http:'; + } +} diff --git a/node_modules/@discordjs/form-data/lib/browser.js b/node_modules/@discordjs/form-data/lib/browser.js new file mode 100644 index 0000000..09e7c70 --- /dev/null +++ b/node_modules/@discordjs/form-data/lib/browser.js @@ -0,0 +1,2 @@ +/* eslint-env browser */ +module.exports = typeof self == 'object' ? self.FormData : window.FormData; diff --git a/node_modules/@discordjs/form-data/lib/form_data.js b/node_modules/@discordjs/form-data/lib/form_data.js new file mode 100644 index 0000000..0b9d8c8 --- /dev/null +++ b/node_modules/@discordjs/form-data/lib/form_data.js @@ -0,0 +1,497 @@ +var CombinedStream = require('combined-stream'); +var util = require('util'); +var path = require('path'); +var http = require('http'); +var https = require('https'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var Stream = require('stream').Stream; +var mime = require('mime-types'); +var asynckit = require('asynckit'); +var populate = require('./populate.js'); + +// Public API +module.exports = FormData; + +// make it a Stream +util.inherits(FormData, CombinedStream); + +/** + * Create readable "multipart/form-data" streams. + * Can be used to submit forms + * and file uploads to other web applications. + * + * @constructor + * @param {Object} options - Properties to be added/overriden for FormData and CombinedStream + */ +function FormData(options) { + if (!(this instanceof FormData)) { + return new FormData(options); + } + + this._overheadLength = 0; + this._valueLength = 0; + this._valuesToMeasure = []; + + CombinedStream.call(this); + + options = options || {}; + for (var option in options) { + this[option] = options[option]; + } +} + +FormData.LINE_BREAK = '\r\n'; +FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; + +FormData.prototype.append = function(field, value, options) { + + options = options || {}; + + // allow filename as single option + if (typeof options == 'string') { + options = {filename: options}; + } + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') { + value = '' + value; + } + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response or not a stream + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) && !(value instanceof Stream))) { + return; + } + + // no need to bother with the length + if (!options.knownLength) { + this._valuesToMeasure.push(value); + } +}; + +FormData.prototype._lengthRetriever = function(value, callback) { + + if (value.hasOwnProperty('fd')) { + + // take read range into a account + // `end` = Infinity –> read file till the end + // + // TODO: Looks like there is bug in Node fs.createReadStream + // it doesn't respect `end` options without `start` options + // Fix it when node fixes it. + // https://github.com/joyent/node/issues/7819 + if (value.end != undefined && value.end != Infinity && value.start != undefined) { + + // when end specified + // no need to calculate range + // inclusive, starts with 0 + callback(null, value.end + 1 - (value.start ? value.start : 0)); + + // not that fast snoopy + } else { + // still need to fetch file size from fs + fs.stat(value.path, function(err, stat) { + + var fileSize; + + if (err) { + callback(err); + return; + } + + // update final size based on the range options + fileSize = stat.size - (value.start ? value.start : 0); + callback(null, fileSize); + }); + } + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + callback(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + callback(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + callback('Unknown stream'); + } +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (typeof options.header == 'string') { + return options.header; + } + + var contentDisposition = this._getContentDisposition(value, options); + var contentType = this._getContentType(value, options); + + var contents = ''; + var headers = { + // add custom disposition as third element or keep it two elements if not + 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []), + // if no content type. allow it to be empty array + 'Content-Type': [].concat(contentType || []) + }; + + // allow custom headers. + if (typeof options.header == 'object') { + populate(headers, options.header); + } + + var header; + for (var prop in headers) { + if (!headers.hasOwnProperty(prop)) continue; + header = headers[prop]; + + // skip nullish headers. + if (header == null) { + continue; + } + + // convert all headers to arrays. + if (!Array.isArray(header)) { + header = [header]; + } + + // add non-empty headers. + if (header.length) { + contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + } + } + + return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; +}; + +FormData.prototype._getContentDisposition = function(value, options) { + + var filename + , contentDisposition + ; + + if (typeof options.filepath === 'string') { + // custom filepath for relative paths + filename = path.normalize(options.filepath).replace(/\\/g, '/'); + } else if (options.filename || value.name || value.path) { + // custom filename take precedence + // formidable and the browser add a name property + // fs- and request- streams have path property + filename = path.basename(options.filename || value.name || value.path); + } else if (value.readable && value.hasOwnProperty('httpVersion')) { + // or try http response + filename = path.basename(value.client._httpMessage.path || ''); + } + + if (filename) { + contentDisposition = 'filename="' + filename + '"'; + } + + return contentDisposition; +}; + +FormData.prototype._getContentType = function(value, options) { + + // use custom content-type above all + var contentType = options.contentType; + + // or try `name` from formidable, browser + if (!contentType && value.name) { + contentType = mime.lookup(value.name); + } + + // or try `path` from fs-, request- streams + if (!contentType && value.path) { + contentType = mime.lookup(value.path); + } + + // or if it's http-reponse + if (!contentType && value.readable && value.hasOwnProperty('httpVersion')) { + contentType = value.headers['content-type']; + } + + // or guess it from the filepath or filename + if (!contentType && (options.filepath || options.filename)) { + contentType = mime.lookup(options.filepath || options.filename); + } + + // fallback to the default content type if `value` is not simple value + if (!contentType && typeof value == 'object') { + contentType = FormData.DEFAULT_CONTENT_TYPE; + } + + return contentType; +}; + +FormData.prototype._multiPartFooter = function() { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var header; + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (header in userHeaders) { + if (userHeaders.hasOwnProperty(header)) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + } + + return formHeaders; +}; + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype.getBuffer = function() { + var dataBuffer = new Buffer.alloc( 0 ); + var boundary = this.getBoundary(); + + // Create the form content. Add Line breaks to the end of data. + for (var i = 0, len = this._streams.length; i < len; i++) { + if (typeof this._streams[i] !== 'function') { + + // Add content to the buffer. + if(Buffer.isBuffer(this._streams[i])) { + dataBuffer = Buffer.concat( [dataBuffer, this._streams[i]]); + }else { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(this._streams[i])]); + } + + // Add break after content. + if (typeof this._streams[i] !== 'string' || this._streams[i].substring( 2, boundary.length + 2 ) !== boundary) { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(FormData.LINE_BREAK)] ); + } + } + } + + // Add the footer and return the Buffer object. + return Buffer.concat( [dataBuffer, Buffer.from(this._lastBoundary())] ); +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function() { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/form-data/form-data/issues/40 + if (!this.hasKnownLength()) { + // Some async length retrievers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +// Public API to check if length of added values is known +// https://github.com/form-data/form-data/issues/196 +// https://github.com/form-data/form-data/issues/262 +FormData.prototype.hasKnownLength = function() { + var hasKnownLength = true; + + if (this._valuesToMeasure.length) { + hasKnownLength = false; + } + + return hasKnownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._valuesToMeasure.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) { + if (err) { + cb(err); + return; + } + + values.forEach(function(length) { + knownLength += length; + }); + + cb(null, knownLength); + }); +}; + +FormData.prototype.submit = function(params, cb) { + var request + , options + , defaults = {method: 'post'} + ; + + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { + + params = parseUrl(params); + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname, + protocol: params.protocol + }, defaults); + + // use custom params + } else { + + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; + } + } + + // put that good code in getHeaders to some use + options.headers = this.getHeaders(params.headers); + + // https if specified, fallback to http in any other case + if (options.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + if (err && err !== 'Unknown stream') { + this._error(err); + return; + } + + // add content length + if (length) { + request.setHeader('Content-Length', length); + } + + this.pipe(request); + if (cb) { + var onResponse; + + var callback = function (error, responce) { + request.removeListener('error', callback); + request.removeListener('response', onResponse); + + return cb.call(this, error, responce); + }; + + onResponse = callback.bind(this, null); + + request.on('error', callback); + request.on('response', onResponse); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (!this.error) { + this.error = err; + this.pause(); + this.emit('error', err); + } +}; + +FormData.prototype.toString = function () { + return '[object FormData]'; +}; diff --git a/node_modules/@discordjs/form-data/lib/populate.js b/node_modules/@discordjs/form-data/lib/populate.js new file mode 100644 index 0000000..4d35738 --- /dev/null +++ b/node_modules/@discordjs/form-data/lib/populate.js @@ -0,0 +1,10 @@ +// populates missing values +module.exports = function(dst, src) { + + Object.keys(src).forEach(function(prop) + { + dst[prop] = dst[prop] || src[prop]; + }); + + return dst; +}; diff --git a/node_modules/@discordjs/form-data/package.json b/node_modules/@discordjs/form-data/package.json new file mode 100644 index 0000000..854446f --- /dev/null +++ b/node_modules/@discordjs/form-data/package.json @@ -0,0 +1,64 @@ +{ + "author": "Felix Geisendörfer (http://debuggable.com/)", + "name": "@discordjs/form-data", + "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", + "version": "3.0.1", + "repository": { + "type": "git", + "url": "git://github.com/form-data/form-data.git" + }, + "main": "./lib/form_data", + "browser": "./lib/browser", + "typings": "./index.d.ts", + "scripts": { + "pretest": "rimraf coverage test/tmp", + "test": "istanbul cover test/run.js", + "posttest": "istanbul report lcov text", + "lint": "eslint lib/*.js test/*.js test/integration/*.js", + "report": "istanbul report lcov text", + "ci-lint": "is-node-modern 8 && npm run lint || is-node-not-modern 8", + "ci-test": "npm run test && npm run browser && npm run report", + "predebug": "rimraf coverage test/tmp", + "debug": "verbose=1 ./test/run.js", + "browser": "browserify -t browserify-istanbul test/run-browser.js | obake --coverage", + "check": "istanbul check-coverage coverage/coverage*.json", + "files": "pkgfiles --sort=name", + "get-version": "node -e \"console.log(require('./package.json').version)\"" + }, + "pre-commit": [ + "lint", + "ci-test", + "check" + ], + "engines": { + "node": ">= 6" + }, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "devDependencies": { + "@types/node": "^12.0.10", + "browserify": "^13.1.1", + "browserify-istanbul": "^2.0.0", + "coveralls": "^3.0.4", + "cross-spawn": "^6.0.5", + "eslint": "^6.0.1", + "fake": "^0.2.2", + "far": "^0.0.7", + "formidable": "^1.0.17", + "in-publish": "^2.0.0", + "is-node-modern": "^1.0.0", + "istanbul": "^0.4.5", + "obake": "^0.1.2", + "puppeteer": "^1.19.0", + "pkgfiles": "^2.3.0", + "pre-commit": "^1.1.3", + "request": "^2.88.0", + "rimraf": "^2.7.1", + "tape": "^4.6.2", + "typescript": "^3.5.2" + }, + "license": "MIT" +} diff --git a/node_modules/@sindresorhus/is/dist/index.d.ts b/node_modules/@sindresorhus/is/dist/index.d.ts new file mode 100644 index 0000000..3687767 --- /dev/null +++ b/node_modules/@sindresorhus/is/dist/index.d.ts @@ -0,0 +1,220 @@ +/// +/// +/// +import { Class, TypedArray, ObservableLike, Primitive } from './types'; +export { Class, TypedArray, ObservableLike, Primitive }; +declare const objectTypeNames: readonly ["Function", "Generator", "AsyncGenerator", "GeneratorFunction", "AsyncGeneratorFunction", "AsyncFunction", "Observable", "Array", "Buffer", "Object", "RegExp", "Date", "Error", "Map", "Set", "WeakMap", "WeakSet", "ArrayBuffer", "SharedArrayBuffer", "DataView", "Promise", "URL", "HTMLElement", ...("Int8Array" | "Uint8Array" | "Uint8ClampedArray" | "Int16Array" | "Uint16Array" | "Int32Array" | "Uint32Array" | "Float32Array" | "Float64Array" | "BigInt64Array" | "BigUint64Array")[]]; +declare type ObjectTypeName = typeof objectTypeNames[number]; +declare const primitiveTypeNames: readonly ["null", "undefined", "string", "number", "bigint", "boolean", "symbol"]; +declare type PrimitiveTypeName = typeof primitiveTypeNames[number]; +export declare type TypeName = ObjectTypeName | PrimitiveTypeName; +declare function is(value: unknown): TypeName; +declare namespace is { + var undefined: (value: unknown) => value is undefined; + var string: (value: unknown) => value is string; + var number: (value: unknown) => value is number; + var bigint: (value: unknown) => value is bigint; + var function_: (value: unknown) => value is Function; + var null_: (value: unknown) => value is null; + var class_: (value: unknown) => value is Class; + var boolean: (value: unknown) => value is boolean; + var symbol: (value: unknown) => value is symbol; + var numericString: (value: unknown) => value is string; + var array: (value: unknown, assertion?: ((value: T) => value is T) | undefined) => value is T[]; + var buffer: (value: unknown) => value is Buffer; + var nullOrUndefined: (value: unknown) => value is null | undefined; + var object: (value: unknown) => value is object; + var iterable: (value: unknown) => value is IterableIterator; + var asyncIterable: (value: unknown) => value is AsyncIterableIterator; + var generator: (value: unknown) => value is Generator; + var asyncGenerator: (value: unknown) => value is AsyncGenerator; + var nativePromise: (value: unknown) => value is Promise; + var promise: (value: unknown) => value is Promise; + var generatorFunction: (value: unknown) => value is GeneratorFunction; + var asyncGeneratorFunction: (value: unknown) => value is (...args: any[]) => Promise; + var asyncFunction: (value: unknown) => value is (...args: any[]) => Promise; + var boundFunction: (value: unknown) => value is Function; + var regExp: (value: unknown) => value is RegExp; + var date: (value: unknown) => value is Date; + var error: (value: unknown) => value is Error; + var map: (value: unknown) => value is Map; + var set: (value: unknown) => value is Set; + var weakMap: (value: unknown) => value is WeakMap; + var weakSet: (value: unknown) => value is WeakSet; + var int8Array: (value: unknown) => value is Int8Array; + var uint8Array: (value: unknown) => value is Uint8Array; + var uint8ClampedArray: (value: unknown) => value is Uint8ClampedArray; + var int16Array: (value: unknown) => value is Int16Array; + var uint16Array: (value: unknown) => value is Uint16Array; + var int32Array: (value: unknown) => value is Int32Array; + var uint32Array: (value: unknown) => value is Uint32Array; + var float32Array: (value: unknown) => value is Float32Array; + var float64Array: (value: unknown) => value is Float64Array; + var bigInt64Array: (value: unknown) => value is BigInt64Array; + var bigUint64Array: (value: unknown) => value is BigUint64Array; + var arrayBuffer: (value: unknown) => value is ArrayBuffer; + var sharedArrayBuffer: (value: unknown) => value is SharedArrayBuffer; + var dataView: (value: unknown) => value is DataView; + var directInstanceOf: (instance: unknown, class_: Class) => instance is T; + var urlInstance: (value: unknown) => value is URL; + var urlString: (value: unknown) => value is string; + var truthy: (value: unknown) => boolean; + var falsy: (value: unknown) => boolean; + var nan: (value: unknown) => boolean; + var primitive: (value: unknown) => value is Primitive; + var integer: (value: unknown) => value is number; + var safeInteger: (value: unknown) => value is number; + var plainObject: (value: unknown) => value is Record; + var typedArray: (value: unknown) => value is TypedArray; + var arrayLike: (value: unknown) => value is ArrayLike; + var inRange: (value: number, range: number | number[]) => value is number; + var domElement: (value: unknown) => value is HTMLElement; + var observable: (value: unknown) => value is ObservableLike; + var nodeStream: (value: unknown) => value is NodeStream; + var infinite: (value: unknown) => value is number; + var evenInteger: (value: number) => value is number; + var oddInteger: (value: number) => value is number; + var emptyArray: (value: unknown) => value is never[]; + var nonEmptyArray: (value: unknown) => value is unknown[]; + var emptyString: (value: unknown) => value is ""; + var nonEmptyString: (value: unknown) => value is string; + var emptyStringOrWhitespace: (value: unknown) => value is string; + var emptyObject: (value: unknown) => value is Record; + var nonEmptyObject: (value: unknown) => value is Record; + var emptySet: (value: unknown) => value is Set; + var nonEmptySet: (value: unknown) => value is Set; + var emptyMap: (value: unknown) => value is Map; + var nonEmptyMap: (value: unknown) => value is Map; + var any: (predicate: Predicate | Predicate[], ...values: unknown[]) => boolean; + var all: (predicate: Predicate, ...values: unknown[]) => boolean; +} +declare type ObjectKey = string | number | symbol; +export interface ArrayLike { + readonly [index: number]: T; + readonly length: number; +} +export interface NodeStream extends NodeJS.EventEmitter { + pipe(destination: T, options?: { + end?: boolean; + }): T; +} +export declare type Predicate = (value: unknown) => boolean; +export declare const enum AssertionTypeDescription { + class_ = "Class", + numericString = "string with a number", + nullOrUndefined = "null or undefined", + iterable = "Iterable", + asyncIterable = "AsyncIterable", + nativePromise = "native Promise", + urlString = "string with a URL", + truthy = "truthy", + falsy = "falsy", + nan = "NaN", + primitive = "primitive", + integer = "integer", + safeInteger = "integer", + plainObject = "plain object", + arrayLike = "array-like", + typedArray = "TypedArray", + domElement = "HTMLElement", + nodeStream = "Node.js Stream", + infinite = "infinite number", + emptyArray = "empty array", + nonEmptyArray = "non-empty array", + emptyString = "empty string", + nonEmptyString = "non-empty string", + emptyStringOrWhitespace = "empty string or whitespace", + emptyObject = "empty object", + nonEmptyObject = "non-empty object", + emptySet = "empty set", + nonEmptySet = "non-empty set", + emptyMap = "empty map", + nonEmptyMap = "non-empty map", + evenInteger = "even integer", + oddInteger = "odd integer", + directInstanceOf = "T", + inRange = "in range", + any = "predicate returns truthy for any value", + all = "predicate returns truthy for all values" +} +interface Assert { + undefined: (value: unknown) => asserts value is undefined; + string: (value: unknown) => asserts value is string; + number: (value: unknown) => asserts value is number; + bigint: (value: unknown) => asserts value is bigint; + function_: (value: unknown) => asserts value is Function; + null_: (value: unknown) => asserts value is null; + class_: (value: unknown) => asserts value is Class; + boolean: (value: unknown) => asserts value is boolean; + symbol: (value: unknown) => asserts value is symbol; + numericString: (value: unknown) => asserts value is string; + array: (value: unknown, assertion?: (element: unknown) => asserts element is T) => asserts value is T[]; + buffer: (value: unknown) => asserts value is Buffer; + nullOrUndefined: (value: unknown) => asserts value is null | undefined; + object: (value: unknown) => asserts value is Record; + iterable: (value: unknown) => asserts value is Iterable; + asyncIterable: (value: unknown) => asserts value is AsyncIterable; + generator: (value: unknown) => asserts value is Generator; + asyncGenerator: (value: unknown) => asserts value is AsyncGenerator; + nativePromise: (value: unknown) => asserts value is Promise; + promise: (value: unknown) => asserts value is Promise; + generatorFunction: (value: unknown) => asserts value is GeneratorFunction; + asyncGeneratorFunction: (value: unknown) => asserts value is AsyncGeneratorFunction; + asyncFunction: (value: unknown) => asserts value is Function; + boundFunction: (value: unknown) => asserts value is Function; + regExp: (value: unknown) => asserts value is RegExp; + date: (value: unknown) => asserts value is Date; + error: (value: unknown) => asserts value is Error; + map: (value: unknown) => asserts value is Map; + set: (value: unknown) => asserts value is Set; + weakMap: (value: unknown) => asserts value is WeakMap; + weakSet: (value: unknown) => asserts value is WeakSet; + int8Array: (value: unknown) => asserts value is Int8Array; + uint8Array: (value: unknown) => asserts value is Uint8Array; + uint8ClampedArray: (value: unknown) => asserts value is Uint8ClampedArray; + int16Array: (value: unknown) => asserts value is Int16Array; + uint16Array: (value: unknown) => asserts value is Uint16Array; + int32Array: (value: unknown) => asserts value is Int32Array; + uint32Array: (value: unknown) => asserts value is Uint32Array; + float32Array: (value: unknown) => asserts value is Float32Array; + float64Array: (value: unknown) => asserts value is Float64Array; + bigInt64Array: (value: unknown) => asserts value is BigInt64Array; + bigUint64Array: (value: unknown) => asserts value is BigUint64Array; + arrayBuffer: (value: unknown) => asserts value is ArrayBuffer; + sharedArrayBuffer: (value: unknown) => asserts value is SharedArrayBuffer; + dataView: (value: unknown) => asserts value is DataView; + urlInstance: (value: unknown) => asserts value is URL; + urlString: (value: unknown) => asserts value is string; + truthy: (value: unknown) => asserts value is unknown; + falsy: (value: unknown) => asserts value is unknown; + nan: (value: unknown) => asserts value is unknown; + primitive: (value: unknown) => asserts value is Primitive; + integer: (value: unknown) => asserts value is number; + safeInteger: (value: unknown) => asserts value is number; + plainObject: (value: unknown) => asserts value is Record; + typedArray: (value: unknown) => asserts value is TypedArray; + arrayLike: (value: unknown) => asserts value is ArrayLike; + domElement: (value: unknown) => asserts value is HTMLElement; + observable: (value: unknown) => asserts value is ObservableLike; + nodeStream: (value: unknown) => asserts value is NodeStream; + infinite: (value: unknown) => asserts value is number; + emptyArray: (value: unknown) => asserts value is never[]; + nonEmptyArray: (value: unknown) => asserts value is unknown[]; + emptyString: (value: unknown) => asserts value is ''; + nonEmptyString: (value: unknown) => asserts value is string; + emptyStringOrWhitespace: (value: unknown) => asserts value is string; + emptyObject: (value: unknown) => asserts value is Record; + nonEmptyObject: (value: unknown) => asserts value is Record; + emptySet: (value: unknown) => asserts value is Set; + nonEmptySet: (value: unknown) => asserts value is Set; + emptyMap: (value: unknown) => asserts value is Map; + nonEmptyMap: (value: unknown) => asserts value is Map; + evenInteger: (value: number) => asserts value is number; + oddInteger: (value: number) => asserts value is number; + directInstanceOf: (instance: unknown, class_: Class) => asserts instance is T; + inRange: (value: number, range: number | number[]) => asserts value is number; + any: (predicate: Predicate | Predicate[], ...values: unknown[]) => void | never; + all: (predicate: Predicate, ...values: unknown[]) => void | never; +} +export declare const assert: Assert; +export default is; diff --git a/node_modules/@sindresorhus/is/dist/index.js b/node_modules/@sindresorhus/is/dist/index.js new file mode 100644 index 0000000..f86cf5c --- /dev/null +++ b/node_modules/@sindresorhus/is/dist/index.js @@ -0,0 +1,418 @@ +"use strict"; +/// +/// +/// +Object.defineProperty(exports, "__esModule", { value: true }); +const typedArrayTypeNames = [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array', + 'BigInt64Array', + 'BigUint64Array' +]; +function isTypedArrayName(name) { + return typedArrayTypeNames.includes(name); +} +const objectTypeNames = [ + 'Function', + 'Generator', + 'AsyncGenerator', + 'GeneratorFunction', + 'AsyncGeneratorFunction', + 'AsyncFunction', + 'Observable', + 'Array', + 'Buffer', + 'Object', + 'RegExp', + 'Date', + 'Error', + 'Map', + 'Set', + 'WeakMap', + 'WeakSet', + 'ArrayBuffer', + 'SharedArrayBuffer', + 'DataView', + 'Promise', + 'URL', + 'HTMLElement', + ...typedArrayTypeNames +]; +function isObjectTypeName(name) { + return objectTypeNames.includes(name); +} +const primitiveTypeNames = [ + 'null', + 'undefined', + 'string', + 'number', + 'bigint', + 'boolean', + 'symbol' +]; +function isPrimitiveTypeName(name) { + return primitiveTypeNames.includes(name); +} +// eslint-disable-next-line @typescript-eslint/ban-types +function isOfType(type) { + return (value) => typeof value === type; +} +const { toString } = Object.prototype; +const getObjectType = (value) => { + const objectTypeName = toString.call(value).slice(8, -1); + if (/HTML\w+Element/.test(objectTypeName) && is.domElement(value)) { + return 'HTMLElement'; + } + if (isObjectTypeName(objectTypeName)) { + return objectTypeName; + } + return undefined; +}; +const isObjectOfType = (type) => (value) => getObjectType(value) === type; +function is(value) { + if (value === null) { + return 'null'; + } + switch (typeof value) { + case 'undefined': + return 'undefined'; + case 'string': + return 'string'; + case 'number': + return 'number'; + case 'boolean': + return 'boolean'; + case 'function': + return 'Function'; + case 'bigint': + return 'bigint'; + case 'symbol': + return 'symbol'; + default: + } + if (is.observable(value)) { + return 'Observable'; + } + if (is.array(value)) { + return 'Array'; + } + if (is.buffer(value)) { + return 'Buffer'; + } + const tagType = getObjectType(value); + if (tagType) { + return tagType; + } + if (value instanceof String || value instanceof Boolean || value instanceof Number) { + throw new TypeError('Please don\'t use object wrappers for primitive types'); + } + return 'Object'; +} +is.undefined = isOfType('undefined'); +is.string = isOfType('string'); +const isNumberType = isOfType('number'); +is.number = (value) => isNumberType(value) && !is.nan(value); +is.bigint = isOfType('bigint'); +// eslint-disable-next-line @typescript-eslint/ban-types +is.function_ = isOfType('function'); +is.null_ = (value) => value === null; +is.class_ = (value) => is.function_(value) && value.toString().startsWith('class '); +is.boolean = (value) => value === true || value === false; +is.symbol = isOfType('symbol'); +is.numericString = (value) => is.string(value) && !is.emptyStringOrWhitespace(value) && !Number.isNaN(Number(value)); +is.array = (value, assertion) => { + if (!Array.isArray(value)) { + return false; + } + if (!is.function_(assertion)) { + return true; + } + return value.every(assertion); +}; +is.buffer = (value) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = value) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.isBuffer) === null || _c === void 0 ? void 0 : _c.call(_b, value)) !== null && _d !== void 0 ? _d : false; }; +is.nullOrUndefined = (value) => is.null_(value) || is.undefined(value); +is.object = (value) => !is.null_(value) && (typeof value === 'object' || is.function_(value)); +is.iterable = (value) => { var _a; return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a[Symbol.iterator]); }; +is.asyncIterable = (value) => { var _a; return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a[Symbol.asyncIterator]); }; +is.generator = (value) => is.iterable(value) && is.function_(value.next) && is.function_(value.throw); +is.asyncGenerator = (value) => is.asyncIterable(value) && is.function_(value.next) && is.function_(value.throw); +is.nativePromise = (value) => isObjectOfType('Promise')(value); +const hasPromiseAPI = (value) => { + var _a, _b; + return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a.then) && + is.function_((_b = value) === null || _b === void 0 ? void 0 : _b.catch); +}; +is.promise = (value) => is.nativePromise(value) || hasPromiseAPI(value); +is.generatorFunction = isObjectOfType('GeneratorFunction'); +is.asyncGeneratorFunction = (value) => getObjectType(value) === 'AsyncGeneratorFunction'; +is.asyncFunction = (value) => getObjectType(value) === 'AsyncFunction'; +// eslint-disable-next-line no-prototype-builtins, @typescript-eslint/ban-types +is.boundFunction = (value) => is.function_(value) && !value.hasOwnProperty('prototype'); +is.regExp = isObjectOfType('RegExp'); +is.date = isObjectOfType('Date'); +is.error = isObjectOfType('Error'); +is.map = (value) => isObjectOfType('Map')(value); +is.set = (value) => isObjectOfType('Set')(value); +is.weakMap = (value) => isObjectOfType('WeakMap')(value); +is.weakSet = (value) => isObjectOfType('WeakSet')(value); +is.int8Array = isObjectOfType('Int8Array'); +is.uint8Array = isObjectOfType('Uint8Array'); +is.uint8ClampedArray = isObjectOfType('Uint8ClampedArray'); +is.int16Array = isObjectOfType('Int16Array'); +is.uint16Array = isObjectOfType('Uint16Array'); +is.int32Array = isObjectOfType('Int32Array'); +is.uint32Array = isObjectOfType('Uint32Array'); +is.float32Array = isObjectOfType('Float32Array'); +is.float64Array = isObjectOfType('Float64Array'); +is.bigInt64Array = isObjectOfType('BigInt64Array'); +is.bigUint64Array = isObjectOfType('BigUint64Array'); +is.arrayBuffer = isObjectOfType('ArrayBuffer'); +is.sharedArrayBuffer = isObjectOfType('SharedArrayBuffer'); +is.dataView = isObjectOfType('DataView'); +is.directInstanceOf = (instance, class_) => Object.getPrototypeOf(instance) === class_.prototype; +is.urlInstance = (value) => isObjectOfType('URL')(value); +is.urlString = (value) => { + if (!is.string(value)) { + return false; + } + try { + new URL(value); // eslint-disable-line no-new + return true; + } + catch (_a) { + return false; + } +}; +// TODO: Use the `not` operator with a type guard here when it's available. +// Example: `is.truthy = (value: unknown): value is (not false | not 0 | not '' | not undefined | not null) => Boolean(value);` +is.truthy = (value) => Boolean(value); +// Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);` +is.falsy = (value) => !value; +is.nan = (value) => Number.isNaN(value); +is.primitive = (value) => is.null_(value) || isPrimitiveTypeName(typeof value); +is.integer = (value) => Number.isInteger(value); +is.safeInteger = (value) => Number.isSafeInteger(value); +is.plainObject = (value) => { + // From: https://github.com/sindresorhus/is-plain-obj/blob/main/index.js + if (toString.call(value) !== '[object Object]') { + return false; + } + const prototype = Object.getPrototypeOf(value); + return prototype === null || prototype === Object.getPrototypeOf({}); +}; +is.typedArray = (value) => isTypedArrayName(getObjectType(value)); +const isValidLength = (value) => is.safeInteger(value) && value >= 0; +is.arrayLike = (value) => !is.nullOrUndefined(value) && !is.function_(value) && isValidLength(value.length); +is.inRange = (value, range) => { + if (is.number(range)) { + return value >= Math.min(0, range) && value <= Math.max(range, 0); + } + if (is.array(range) && range.length === 2) { + return value >= Math.min(...range) && value <= Math.max(...range); + } + throw new TypeError(`Invalid range: ${JSON.stringify(range)}`); +}; +const NODE_TYPE_ELEMENT = 1; +const DOM_PROPERTIES_TO_CHECK = [ + 'innerHTML', + 'ownerDocument', + 'style', + 'attributes', + 'nodeValue' +]; +is.domElement = (value) => { + return is.object(value) && + value.nodeType === NODE_TYPE_ELEMENT && + is.string(value.nodeName) && + !is.plainObject(value) && + DOM_PROPERTIES_TO_CHECK.every(property => property in value); +}; +is.observable = (value) => { + var _a, _b, _c, _d; + if (!value) { + return false; + } + // eslint-disable-next-line no-use-extend-native/no-use-extend-native + if (value === ((_b = (_a = value)[Symbol.observable]) === null || _b === void 0 ? void 0 : _b.call(_a))) { + return true; + } + if (value === ((_d = (_c = value)['@@observable']) === null || _d === void 0 ? void 0 : _d.call(_c))) { + return true; + } + return false; +}; +is.nodeStream = (value) => is.object(value) && is.function_(value.pipe) && !is.observable(value); +is.infinite = (value) => value === Infinity || value === -Infinity; +const isAbsoluteMod2 = (remainder) => (value) => is.integer(value) && Math.abs(value % 2) === remainder; +is.evenInteger = isAbsoluteMod2(0); +is.oddInteger = isAbsoluteMod2(1); +is.emptyArray = (value) => is.array(value) && value.length === 0; +is.nonEmptyArray = (value) => is.array(value) && value.length > 0; +is.emptyString = (value) => is.string(value) && value.length === 0; +// TODO: Use `not ''` when the `not` operator is available. +is.nonEmptyString = (value) => is.string(value) && value.length > 0; +const isWhiteSpaceString = (value) => is.string(value) && !/\S/.test(value); +is.emptyStringOrWhitespace = (value) => is.emptyString(value) || isWhiteSpaceString(value); +is.emptyObject = (value) => is.object(value) && !is.map(value) && !is.set(value) && Object.keys(value).length === 0; +// TODO: Use `not` operator here to remove `Map` and `Set` from type guard: +// - https://github.com/Microsoft/TypeScript/pull/29317 +is.nonEmptyObject = (value) => is.object(value) && !is.map(value) && !is.set(value) && Object.keys(value).length > 0; +is.emptySet = (value) => is.set(value) && value.size === 0; +is.nonEmptySet = (value) => is.set(value) && value.size > 0; +is.emptyMap = (value) => is.map(value) && value.size === 0; +is.nonEmptyMap = (value) => is.map(value) && value.size > 0; +const predicateOnArray = (method, predicate, values) => { + if (!is.function_(predicate)) { + throw new TypeError(`Invalid predicate: ${JSON.stringify(predicate)}`); + } + if (values.length === 0) { + throw new TypeError('Invalid number of values'); + } + return method.call(values, predicate); +}; +is.any = (predicate, ...values) => { + const predicates = is.array(predicate) ? predicate : [predicate]; + return predicates.some(singlePredicate => predicateOnArray(Array.prototype.some, singlePredicate, values)); +}; +is.all = (predicate, ...values) => predicateOnArray(Array.prototype.every, predicate, values); +const assertType = (condition, description, value, options = {}) => { + if (!condition) { + const { multipleValues } = options; + const valuesMessage = multipleValues ? + `received values of types ${[ + ...new Set(value.map(singleValue => `\`${is(singleValue)}\``)) + ].join(', ')}` : + `received value of type \`${is(value)}\``; + throw new TypeError(`Expected value which is \`${description}\`, ${valuesMessage}.`); + } +}; +exports.assert = { + // Unknowns. + undefined: (value) => assertType(is.undefined(value), 'undefined', value), + string: (value) => assertType(is.string(value), 'string', value), + number: (value) => assertType(is.number(value), 'number', value), + bigint: (value) => assertType(is.bigint(value), 'bigint', value), + // eslint-disable-next-line @typescript-eslint/ban-types + function_: (value) => assertType(is.function_(value), 'Function', value), + null_: (value) => assertType(is.null_(value), 'null', value), + class_: (value) => assertType(is.class_(value), "Class" /* class_ */, value), + boolean: (value) => assertType(is.boolean(value), 'boolean', value), + symbol: (value) => assertType(is.symbol(value), 'symbol', value), + numericString: (value) => assertType(is.numericString(value), "string with a number" /* numericString */, value), + array: (value, assertion) => { + const assert = assertType; + assert(is.array(value), 'Array', value); + if (assertion) { + value.forEach(assertion); + } + }, + buffer: (value) => assertType(is.buffer(value), 'Buffer', value), + nullOrUndefined: (value) => assertType(is.nullOrUndefined(value), "null or undefined" /* nullOrUndefined */, value), + object: (value) => assertType(is.object(value), 'Object', value), + iterable: (value) => assertType(is.iterable(value), "Iterable" /* iterable */, value), + asyncIterable: (value) => assertType(is.asyncIterable(value), "AsyncIterable" /* asyncIterable */, value), + generator: (value) => assertType(is.generator(value), 'Generator', value), + asyncGenerator: (value) => assertType(is.asyncGenerator(value), 'AsyncGenerator', value), + nativePromise: (value) => assertType(is.nativePromise(value), "native Promise" /* nativePromise */, value), + promise: (value) => assertType(is.promise(value), 'Promise', value), + generatorFunction: (value) => assertType(is.generatorFunction(value), 'GeneratorFunction', value), + asyncGeneratorFunction: (value) => assertType(is.asyncGeneratorFunction(value), 'AsyncGeneratorFunction', value), + // eslint-disable-next-line @typescript-eslint/ban-types + asyncFunction: (value) => assertType(is.asyncFunction(value), 'AsyncFunction', value), + // eslint-disable-next-line @typescript-eslint/ban-types + boundFunction: (value) => assertType(is.boundFunction(value), 'Function', value), + regExp: (value) => assertType(is.regExp(value), 'RegExp', value), + date: (value) => assertType(is.date(value), 'Date', value), + error: (value) => assertType(is.error(value), 'Error', value), + map: (value) => assertType(is.map(value), 'Map', value), + set: (value) => assertType(is.set(value), 'Set', value), + weakMap: (value) => assertType(is.weakMap(value), 'WeakMap', value), + weakSet: (value) => assertType(is.weakSet(value), 'WeakSet', value), + int8Array: (value) => assertType(is.int8Array(value), 'Int8Array', value), + uint8Array: (value) => assertType(is.uint8Array(value), 'Uint8Array', value), + uint8ClampedArray: (value) => assertType(is.uint8ClampedArray(value), 'Uint8ClampedArray', value), + int16Array: (value) => assertType(is.int16Array(value), 'Int16Array', value), + uint16Array: (value) => assertType(is.uint16Array(value), 'Uint16Array', value), + int32Array: (value) => assertType(is.int32Array(value), 'Int32Array', value), + uint32Array: (value) => assertType(is.uint32Array(value), 'Uint32Array', value), + float32Array: (value) => assertType(is.float32Array(value), 'Float32Array', value), + float64Array: (value) => assertType(is.float64Array(value), 'Float64Array', value), + bigInt64Array: (value) => assertType(is.bigInt64Array(value), 'BigInt64Array', value), + bigUint64Array: (value) => assertType(is.bigUint64Array(value), 'BigUint64Array', value), + arrayBuffer: (value) => assertType(is.arrayBuffer(value), 'ArrayBuffer', value), + sharedArrayBuffer: (value) => assertType(is.sharedArrayBuffer(value), 'SharedArrayBuffer', value), + dataView: (value) => assertType(is.dataView(value), 'DataView', value), + urlInstance: (value) => assertType(is.urlInstance(value), 'URL', value), + urlString: (value) => assertType(is.urlString(value), "string with a URL" /* urlString */, value), + truthy: (value) => assertType(is.truthy(value), "truthy" /* truthy */, value), + falsy: (value) => assertType(is.falsy(value), "falsy" /* falsy */, value), + nan: (value) => assertType(is.nan(value), "NaN" /* nan */, value), + primitive: (value) => assertType(is.primitive(value), "primitive" /* primitive */, value), + integer: (value) => assertType(is.integer(value), "integer" /* integer */, value), + safeInteger: (value) => assertType(is.safeInteger(value), "integer" /* safeInteger */, value), + plainObject: (value) => assertType(is.plainObject(value), "plain object" /* plainObject */, value), + typedArray: (value) => assertType(is.typedArray(value), "TypedArray" /* typedArray */, value), + arrayLike: (value) => assertType(is.arrayLike(value), "array-like" /* arrayLike */, value), + domElement: (value) => assertType(is.domElement(value), "HTMLElement" /* domElement */, value), + observable: (value) => assertType(is.observable(value), 'Observable', value), + nodeStream: (value) => assertType(is.nodeStream(value), "Node.js Stream" /* nodeStream */, value), + infinite: (value) => assertType(is.infinite(value), "infinite number" /* infinite */, value), + emptyArray: (value) => assertType(is.emptyArray(value), "empty array" /* emptyArray */, value), + nonEmptyArray: (value) => assertType(is.nonEmptyArray(value), "non-empty array" /* nonEmptyArray */, value), + emptyString: (value) => assertType(is.emptyString(value), "empty string" /* emptyString */, value), + nonEmptyString: (value) => assertType(is.nonEmptyString(value), "non-empty string" /* nonEmptyString */, value), + emptyStringOrWhitespace: (value) => assertType(is.emptyStringOrWhitespace(value), "empty string or whitespace" /* emptyStringOrWhitespace */, value), + emptyObject: (value) => assertType(is.emptyObject(value), "empty object" /* emptyObject */, value), + nonEmptyObject: (value) => assertType(is.nonEmptyObject(value), "non-empty object" /* nonEmptyObject */, value), + emptySet: (value) => assertType(is.emptySet(value), "empty set" /* emptySet */, value), + nonEmptySet: (value) => assertType(is.nonEmptySet(value), "non-empty set" /* nonEmptySet */, value), + emptyMap: (value) => assertType(is.emptyMap(value), "empty map" /* emptyMap */, value), + nonEmptyMap: (value) => assertType(is.nonEmptyMap(value), "non-empty map" /* nonEmptyMap */, value), + // Numbers. + evenInteger: (value) => assertType(is.evenInteger(value), "even integer" /* evenInteger */, value), + oddInteger: (value) => assertType(is.oddInteger(value), "odd integer" /* oddInteger */, value), + // Two arguments. + directInstanceOf: (instance, class_) => assertType(is.directInstanceOf(instance, class_), "T" /* directInstanceOf */, instance), + inRange: (value, range) => assertType(is.inRange(value, range), "in range" /* inRange */, value), + // Variadic functions. + any: (predicate, ...values) => { + return assertType(is.any(predicate, ...values), "predicate returns truthy for any value" /* any */, values, { multipleValues: true }); + }, + all: (predicate, ...values) => assertType(is.all(predicate, ...values), "predicate returns truthy for all values" /* all */, values, { multipleValues: true }) +}; +// Some few keywords are reserved, but we'll populate them for Node.js users +// See https://github.com/Microsoft/TypeScript/issues/2536 +Object.defineProperties(is, { + class: { + value: is.class_ + }, + function: { + value: is.function_ + }, + null: { + value: is.null_ + } +}); +Object.defineProperties(exports.assert, { + class: { + value: exports.assert.class_ + }, + function: { + value: exports.assert.function_ + }, + null: { + value: exports.assert.null_ + } +}); +exports.default = is; +// For CommonJS default export support +module.exports = is; +module.exports.default = is; +module.exports.assert = exports.assert; diff --git a/node_modules/@sindresorhus/is/dist/types.d.ts b/node_modules/@sindresorhus/is/dist/types.d.ts new file mode 100644 index 0000000..a63acda --- /dev/null +++ b/node_modules/@sindresorhus/is/dist/types.d.ts @@ -0,0 +1,24 @@ +/** +Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive). +*/ +export declare type Primitive = null | undefined | string | number | boolean | symbol | bigint; +/** +Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). +*/ +export declare type Class = new (...arguments_: Arguments) => T; +/** +Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`. +*/ +export declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; +declare global { + interface SymbolConstructor { + readonly observable: symbol; + } +} +/** +Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable). +*/ +export interface ObservableLike { + subscribe(observer: (value: unknown) => void): void; + [Symbol.observable](): ObservableLike; +} diff --git a/node_modules/@sindresorhus/is/dist/types.js b/node_modules/@sindresorhus/is/dist/types.js new file mode 100644 index 0000000..0930323 --- /dev/null +++ b/node_modules/@sindresorhus/is/dist/types.js @@ -0,0 +1,3 @@ +"use strict"; +// Extracted from https://github.com/sindresorhus/type-fest/blob/78019f42ea888b0cdceb41a4a78163868de57555/index.d.ts +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@sindresorhus/is/license b/node_modules/@sindresorhus/is/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/@sindresorhus/is/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@sindresorhus/is/package.json b/node_modules/@sindresorhus/is/package.json new file mode 100644 index 0000000..16ef3a4 --- /dev/null +++ b/node_modules/@sindresorhus/is/package.json @@ -0,0 +1,96 @@ +{ + "name": "@sindresorhus/is", + "version": "4.0.1", + "description": "Type check values", + "license": "MIT", + "repository": "sindresorhus/is", + "funding": "https://github.com/sindresorhus/is?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "main": "dist/index.js", + "engines": { + "node": ">=10" + }, + "scripts": { + "build": "del dist && tsc", + "test": "xo && ava", + "prepare": "npm run build" + }, + "files": [ + "dist" + ], + "keywords": [ + "type", + "types", + "is", + "check", + "checking", + "validate", + "validation", + "utility", + "util", + "typeof", + "instanceof", + "object", + "assert", + "assertion", + "test", + "kind", + "primitive", + "verify", + "compare", + "typescript", + "typeguards", + "types" + ], + "devDependencies": { + "@sindresorhus/tsconfig": "^0.7.0", + "@types/jsdom": "^16.1.0", + "@types/node": "^14.0.13", + "@types/zen-observable": "^0.8.0", + "@typescript-eslint/eslint-plugin": "^2.20.0", + "@typescript-eslint/parser": "^2.20.0", + "ava": "^3.3.0", + "del-cli": "^2.0.0", + "eslint-config-xo-typescript": "^0.26.0", + "jsdom": "^16.0.1", + "rxjs": "^6.4.0", + "tempy": "^0.4.0", + "ts-node": "^8.3.0", + "typescript": "~3.8.2", + "xo": "^0.26.1", + "zen-observable": "^0.8.8" + }, + "types": "dist/index.d.ts", + "sideEffects": false, + "ava": { + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register" + ] + }, + "xo": { + "extends": "xo-typescript", + "extensions": [ + "ts" + ], + "parserOptions": { + "project": "./tsconfig.xo.json" + }, + "globals": [ + "BigInt", + "BigInt64Array", + "BigUint64Array" + ], + "rules": { + "@typescript-eslint/promise-function-async": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/explicit-function-return-type": "off" + } + } +} diff --git a/node_modules/@sindresorhus/is/readme.md b/node_modules/@sindresorhus/is/readme.md new file mode 100644 index 0000000..adb9910 --- /dev/null +++ b/node_modules/@sindresorhus/is/readme.md @@ -0,0 +1,602 @@ +# is + +> Type check values + +For example, `is.string('🦄') //=> true` + + + +## Highlights + +- Written in TypeScript +- [Extensive use of type guards](#type-guards) +- [Supports type assertions](#type-assertions) +- [Aware of generic type parameters](#generic-type-parameters) (use with caution) +- Actively maintained +- ![Millions of downloads per week](https://img.shields.io/npm/dw/@sindresorhus/is) + +## Install + +``` +$ npm install @sindresorhus/is +``` + +## Usage + +```js +const is = require('@sindresorhus/is'); + +is('🦄'); +//=> 'string' + +is(new Map()); +//=> 'Map' + +is.number(6); +//=> true +``` + +[Assertions](#type-assertions) perform the same type checks, but throw an error if the type does not match. + +```js +const {assert} = require('@sindresorhus/is'); + +assert.string(2); +//=> Error: Expected value which is `string`, received value of type `number`. +``` + +And with TypeScript: + +```ts +import {assert} from '@sindresorhus/is'; + +assert.string(foo); +// `foo` is now typed as a `string`. +``` + +## API + +### is(value) + +Returns the type of `value`. + +Primitives are lowercase and object types are camelcase. + +Example: + +- `'undefined'` +- `'null'` +- `'string'` +- `'symbol'` +- `'Array'` +- `'Function'` +- `'Object'` + +Note: It will throw an error if you try to feed it object-wrapped primitives, as that's a bad practice. For example `new String('foo')`. + +### is.{method} + +All the below methods accept a value and returns a boolean for whether the value is of the desired type. + +#### Primitives + +##### .undefined(value) +##### .null(value) +##### .string(value) +##### .number(value) + +Note: `is.number(NaN)` returns `false`. This intentionally deviates from `typeof` behavior to increase user-friendliness of `is` type checks. + +##### .boolean(value) +##### .symbol(value) +##### .bigint(value) + +#### Built-in types + +##### .array(value, assertion?) + +Returns true if `value` is an array and all of its items match the assertion (if provided). + +```js +is.array(value); // Validate `value` is an array. +is.array(value, is.number); // Validate `value` is an array and all of its items are numbers. +``` + +##### .function(value) +##### .buffer(value) +##### .object(value) + +Keep in mind that [functions are objects too](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions). + +##### .numericString(value) + +Returns `true` for a string that represents a number satisfying `is.number`, for example, `'42'` and `'-8.3'`. + +Note: `'NaN'` returns `false`, but `'Infinity'` and `'-Infinity'` return `true`. + +##### .regExp(value) +##### .date(value) +##### .error(value) +##### .nativePromise(value) +##### .promise(value) + +Returns `true` for any object with a `.then()` and `.catch()` method. Prefer this one over `.nativePromise()` as you usually want to allow userland promise implementations too. + +##### .generator(value) + +Returns `true` for any object that implements its own `.next()` and `.throw()` methods and has a function definition for `Symbol.iterator`. + +##### .generatorFunction(value) + +##### .asyncFunction(value) + +Returns `true` for any `async` function that can be called with the `await` operator. + +```js +is.asyncFunction(async () => {}); +//=> true + +is.asyncFunction(() => {}); +//=> false +``` + +##### .asyncGenerator(value) + +```js +is.asyncGenerator( + (async function * () { + yield 4; + })() +); +//=> true + +is.asyncGenerator( + (function * () { + yield 4; + })() +); +//=> false +``` + +##### .asyncGeneratorFunction(value) + +```js +is.asyncGeneratorFunction(async function * () { + yield 4; +}); +//=> true + +is.asyncGeneratorFunction(function * () { + yield 4; +}); +//=> false +``` + +##### .boundFunction(value) + +Returns `true` for any `bound` function. + +```js +is.boundFunction(() => {}); +//=> true + +is.boundFunction(function () {}.bind(null)); +//=> true + +is.boundFunction(function () {}); +//=> false +``` + +##### .map(value) +##### .set(value) +##### .weakMap(value) +##### .weakSet(value) + +#### Typed arrays + +##### .int8Array(value) +##### .uint8Array(value) +##### .uint8ClampedArray(value) +##### .int16Array(value) +##### .uint16Array(value) +##### .int32Array(value) +##### .uint32Array(value) +##### .float32Array(value) +##### .float64Array(value) +##### .bigInt64Array(value) +##### .bigUint64Array(value) + +#### Structured data + +##### .arrayBuffer(value) +##### .sharedArrayBuffer(value) +##### .dataView(value) + +#### Emptiness + +##### .emptyString(value) + +Returns `true` if the value is a `string` and the `.length` is 0. + +##### .nonEmptyString(value) + +Returns `true` if the value is a `string` and the `.length` is more than 0. + +##### .emptyStringOrWhitespace(value) + +Returns `true` if `is.emptyString(value)` or if it's a `string` that is all whitespace. + +##### .emptyArray(value) + +Returns `true` if the value is an `Array` and the `.length` is 0. + +##### .nonEmptyArray(value) + +Returns `true` if the value is an `Array` and the `.length` is more than 0. + +##### .emptyObject(value) + +Returns `true` if the value is an `Object` and `Object.keys(value).length` is 0. + +Please note that `Object.keys` returns only own enumerable properties. Hence something like this can happen: + +```js +const object1 = {}; + +Object.defineProperty(object1, 'property1', { + value: 42, + writable: true, + enumerable: false, + configurable: true +}); + +is.emptyObject(object1); +//=> true +``` + +##### .nonEmptyObject(value) + +Returns `true` if the value is an `Object` and `Object.keys(value).length` is more than 0. + +##### .emptySet(value) + +Returns `true` if the value is a `Set` and the `.size` is 0. + +##### .nonEmptySet(Value) + +Returns `true` if the value is a `Set` and the `.size` is more than 0. + +##### .emptyMap(value) + +Returns `true` if the value is a `Map` and the `.size` is 0. + +##### .nonEmptyMap(value) + +Returns `true` if the value is a `Map` and the `.size` is more than 0. + +#### Miscellaneous + +##### .directInstanceOf(value, class) + +Returns `true` if `value` is a direct instance of `class`. + +```js +is.directInstanceOf(new Error(), Error); +//=> true + +class UnicornError extends Error {} + +is.directInstanceOf(new UnicornError(), Error); +//=> false +``` + +##### .urlInstance(value) + +Returns `true` if `value` is an instance of the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL). + +```js +const url = new URL('https://example.com'); + +is.urlInstance(url); +//=> true +``` + +##### .urlString(value) + +Returns `true` if `value` is a URL string. + +Note: this only does basic checking using the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL) constructor. + +```js +const url = 'https://example.com'; + +is.urlString(url); +//=> true + +is.urlString(new URL(url)); +//=> false +``` + +##### .truthy(value) + +Returns `true` for all values that evaluate to true in a boolean context: + +```js +is.truthy('🦄'); +//=> true + +is.truthy(undefined); +//=> false +``` + +##### .falsy(value) + +Returns `true` if `value` is one of: `false`, `0`, `''`, `null`, `undefined`, `NaN`. + +##### .nan(value) +##### .nullOrUndefined(value) +##### .primitive(value) + +JavaScript primitives are as follows: `null`, `undefined`, `string`, `number`, `boolean`, `symbol`. + +##### .integer(value) + +##### .safeInteger(value) + +Returns `true` if `value` is a [safe integer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger). + +##### .plainObject(value) + +An object is plain if it's created by either `{}`, `new Object()`, or `Object.create(null)`. + +##### .iterable(value) +##### .asyncIterable(value) +##### .class(value) + +Returns `true` for instances created by a class. + +##### .typedArray(value) + +##### .arrayLike(value) + +A `value` is array-like if it is not a function and has a `value.length` that is a safe integer greater than or equal to 0. + +```js +is.arrayLike(document.forms); +//=> true + +function foo() { + is.arrayLike(arguments); + //=> true +} +foo(); +``` + +##### .inRange(value, range) + +Check if `value` (number) is in the given `range`. The range is an array of two values, lower bound and upper bound, in no specific order. + +```js +is.inRange(3, [0, 5]); +is.inRange(3, [5, 0]); +is.inRange(0, [-2, 2]); +``` + +##### .inRange(value, upperBound) + +Check if `value` (number) is in the range of `0` to `upperBound`. + +```js +is.inRange(3, 10); +``` + +##### .domElement(value) + +Returns `true` if `value` is a DOM Element. + +##### .nodeStream(value) + +Returns `true` if `value` is a Node.js [stream](https://nodejs.org/api/stream.html). + +```js +const fs = require('fs'); + +is.nodeStream(fs.createReadStream('unicorn.png')); +//=> true +``` + +##### .observable(value) + +Returns `true` if `value` is an `Observable`. + +```js +const {Observable} = require('rxjs'); + +is.observable(new Observable()); +//=> true +``` + +##### .infinite(value) + +Check if `value` is `Infinity` or `-Infinity`. + +##### .evenInteger(value) + +Returns `true` if `value` is an even integer. + +##### .oddInteger(value) + +Returns `true` if `value` is an odd integer. + +##### .any(predicate | predicate[], ...values) + +Using a single `predicate` argument, returns `true` if **any** of the input `values` returns true in the `predicate`: + +```js +is.any(is.string, {}, true, '🦄'); +//=> true + +is.any(is.boolean, 'unicorns', [], new Map()); +//=> false +``` + +Using an array of `predicate[]`, returns `true` if **any** of the input `values` returns true for **any** of the `predicates` provided in an array: + +```js +is.any([is.string, is.number], {}, true, '🦄'); +//=> true + +is.any([is.boolean, is.number], 'unicorns', [], new Map()); +//=> false +``` + +##### .all(predicate, ...values) + +Returns `true` if **all** of the input `values` returns true in the `predicate`: + +```js +is.all(is.object, {}, new Map(), new Set()); +//=> true + +is.all(is.string, '🦄', [], 'unicorns'); +//=> false +``` + +## Type guards + +When using `is` together with TypeScript, [type guards](http://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types) are being used extensively to infer the correct type inside if-else statements. + +```ts +import is from '@sindresorhus/is'; + +const padLeft = (value: string, padding: string | number) => { + if (is.number(padding)) { + // `padding` is typed as `number` + return Array(padding + 1).join(' ') + value; + } + + if (is.string(padding)) { + // `padding` is typed as `string` + return padding + value; + } + + throw new TypeError(`Expected 'padding' to be of type 'string' or 'number', got '${is(padding)}'.`); +} + +padLeft('🦄', 3); +//=> ' 🦄' + +padLeft('🦄', '🌈'); +//=> '🌈🦄' +``` + +## Type assertions + +The type guards are also available as [type assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions), which throw an error for unexpected types. It is a convenient one-line version of the often repetitive "if-not-expected-type-throw" pattern. + +```ts +import {assert} from '@sindresorhus/is'; + +const handleMovieRatingApiResponse = (response: unknown) => { + assert.plainObject(response); + // `response` is now typed as a plain `object` with `unknown` properties. + + assert.number(response.rating); + // `response.rating` is now typed as a `number`. + + assert.string(response.title); + // `response.title` is now typed as a `string`. + + return `${response.title} (${response.rating * 10})`; +}; + +handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'}); +//=> 'The Matrix (8.7)' + +// This throws an error. +handleMovieRatingApiResponse({rating: '🦄'}); +``` + +## Generic type parameters + +The type guards and type assertions are aware of [generic type parameters](https://www.typescriptlang.org/docs/handbook/generics.html), such as `Promise` and `Map`. The default is `unknown` for most cases, since `is` cannot check them at runtime. If the generic type is known at compile-time, either implicitly (inferred) or explicitly (provided), `is` propagates the type so it can be used later. + +Use generic type parameters with caution. They are only checked by the TypeScript compiler, and not checked by `is` at runtime. This can lead to unexpected behavior, where the generic type is _assumed_ at compile-time, but actually is something completely different at runtime. It is best to use `unknown` (default) and type-check the value of the generic type parameter at runtime with `is` or `assert`. + +```ts +import {assert} from '@sindresorhus/is'; + +async function badNumberAssumption(input: unknown) { + // Bad assumption about the generic type parameter fools the compile-time type system. + assert.promise(input); + // `input` is a `Promise` but only assumed to be `Promise`. + + const resolved = await input; + // `resolved` is typed as `number` but was not actually checked at runtime. + + // Multiplication will return NaN if the input promise did not actually contain a number. + return 2 * resolved; +} + +async function goodNumberAssertion(input: unknown) { + assert.promise(input); + // `input` is typed as `Promise` + + const resolved = await input; + // `resolved` is typed as `unknown` + + assert.number(resolved); + // `resolved` is typed as `number` + + // Uses runtime checks so only numbers will reach the multiplication. + return 2 * resolved; +} + +badNumberAssumption(Promise.resolve('An unexpected string')); +//=> NaN + +// This correctly throws an error because of the unexpected string value. +goodNumberAssertion(Promise.resolve('An unexpected string')); +``` + +## FAQ + +### Why yet another type checking module? + +There are hundreds of type checking modules on npm, unfortunately, I couldn't find any that fit my needs: + +- Includes both type methods and ability to get the type +- Types of primitives returned as lowercase and object types as camelcase +- Covers all built-ins +- Unsurprising behavior +- Well-maintained +- Comprehensive test suite + +For the ones I found, pick 3 of these. + +The most common mistakes I noticed in these modules was using `instanceof` for type checking, forgetting that functions are objects, and omitting `symbol` as a primitive. + +## For enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of @sindresorhus/is and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-sindresorhus-is?utm_source=npm-sindresorhus-is&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +## Related + +- [ow](https://github.com/sindresorhus/ow) - Function argument validation for humans +- [is-stream](https://github.com/sindresorhus/is-stream) - Check if something is a Node.js stream +- [is-observable](https://github.com/sindresorhus/is-observable) - Check if a value is an Observable +- [file-type](https://github.com/sindresorhus/file-type) - Detect the file type of a Buffer/Uint8Array +- [is-ip](https://github.com/sindresorhus/is-ip) - Check if a string is an IP address +- [is-array-sorted](https://github.com/sindresorhus/is-array-sorted) - Check if an Array is sorted +- [is-error-constructor](https://github.com/sindresorhus/is-error-constructor) - Check if a value is an error constructor +- [is-empty-iterable](https://github.com/sindresorhus/is-empty-iterable) - Check if an Iterable is empty +- [is-blob](https://github.com/sindresorhus/is-blob) - Check if a value is a Blob - File-like object of immutable, raw data +- [has-emoji](https://github.com/sindresorhus/has-emoji) - Check whether a string has any emoji + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Giora Guttsait](https://github.com/gioragutt) +- [Brandon Smith](https://github.com/brandon93s) diff --git a/node_modules/@szmarczak/http-timer/LICENSE b/node_modules/@szmarczak/http-timer/LICENSE new file mode 100644 index 0000000..15ad2e8 --- /dev/null +++ b/node_modules/@szmarczak/http-timer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Szymon Marczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@szmarczak/http-timer/README.md b/node_modules/@szmarczak/http-timer/README.md new file mode 100644 index 0000000..4f6a615 --- /dev/null +++ b/node_modules/@szmarczak/http-timer/README.md @@ -0,0 +1,89 @@ +# http-timer +> Timings for HTTP requests + +[![Build Status](https://travis-ci.org/szmarczak/http-timer.svg?branch=master)](https://travis-ci.org/szmarczak/http-timer) +[![Coverage Status](https://coveralls.io/repos/github/szmarczak/http-timer/badge.svg?branch=master)](https://coveralls.io/github/szmarczak/http-timer?branch=master) +[![install size](https://packagephobia.now.sh/badge?p=@szmarczak/http-timer)](https://packagephobia.now.sh/result?p=@szmarczak/http-timer) + +Inspired by the [`request` package](https://github.com/request/request). + +## Installation + +NPM: + +> `npm install @szmarczak/http-timer` + +Yarn: + +> `yarn add @szmarczak/http-timer` + +## Usage +```js +const https = require('https'); +const timer = require('@szmarczak/http-timer'); + +const request = https.get('https://httpbin.org/anything'); +timer(request); + +request.once('response', response => { + response.resume(); + response.once('end', () => { + console.log(response.timings); // You can use `request.timings` as well + }); +}); + +// { +// start: 1572712180361, +// socket: 1572712180362, +// lookup: 1572712180415, +// connect: 1572712180571, +// upload: 1572712180884, +// response: 1572712181037, +// end: 1572712181039, +// error: undefined, +// abort: undefined, +// phases: { +// wait: 1, +// dns: 53, +// tcp: 156, +// request: 313, +// firstByte: 153, +// download: 2, +// total: 678 +// } +// } +``` + +## API + +### timer(request) + +Returns: `Object` + +**Note**: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + +- `start` - Time when the request started. +- `socket` - Time when a socket was assigned to the request. +- `lookup` - Time when the DNS lookup finished. +- `connect` - Time when the socket successfully connected. +- `secureConnect` - Time when the socket securely connected. +- `upload` - Time when the request finished uploading. +- `response` - Time when the request fired `response` event. +- `end` - Time when the response fired `end` event. +- `error` - Time when the request fired `error` event. +- `abort` - Time when the request fired `abort` event. +- `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + +If something has not been measured yet, it will be `undefined`. + +## License + +MIT diff --git a/node_modules/@szmarczak/http-timer/dist/source/index.d.ts b/node_modules/@szmarczak/http-timer/dist/source/index.d.ts new file mode 100644 index 0000000..2620b4a --- /dev/null +++ b/node_modules/@szmarczak/http-timer/dist/source/index.d.ts @@ -0,0 +1,32 @@ +/// +import { ClientRequest, IncomingMessage } from 'http'; +export interface Timings { + start: number; + socket?: number; + lookup?: number; + connect?: number; + secureConnect?: number; + upload?: number; + response?: number; + end?: number; + error?: number; + abort?: number; + phases: { + wait?: number; + dns?: number; + tcp?: number; + tls?: number; + request?: number; + firstByte?: number; + download?: number; + total?: number; + }; +} +export interface ClientRequestWithTimings extends ClientRequest { + timings?: Timings; +} +export interface IncomingMessageWithTimings extends IncomingMessage { + timings?: Timings; +} +declare const timer: (request: ClientRequestWithTimings) => Timings; +export default timer; diff --git a/node_modules/@szmarczak/http-timer/dist/source/index.js b/node_modules/@szmarczak/http-timer/dist/source/index.js new file mode 100644 index 0000000..c120ace --- /dev/null +++ b/node_modules/@szmarczak/http-timer/dist/source/index.js @@ -0,0 +1,117 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const defer_to_connect_1 = require("defer-to-connect"); +const nodejsMajorVersion = Number(process.versions.node.split('.')[0]); +const timer = (request) => { + const timings = { + start: Date.now(), + socket: undefined, + lookup: undefined, + connect: undefined, + secureConnect: undefined, + upload: undefined, + response: undefined, + end: undefined, + error: undefined, + abort: undefined, + phases: { + wait: undefined, + dns: undefined, + tcp: undefined, + tls: undefined, + request: undefined, + firstByte: undefined, + download: undefined, + total: undefined + } + }; + request.timings = timings; + const handleError = (origin) => { + const emit = origin.emit.bind(origin); + origin.emit = (event, ...args) => { + // Catches the `error` event + if (event === 'error') { + timings.error = Date.now(); + timings.phases.total = timings.error - timings.start; + origin.emit = emit; + } + // Saves the original behavior + return emit(event, ...args); + }; + }; + handleError(request); + request.prependOnceListener('abort', () => { + timings.abort = Date.now(); + // Let the `end` response event be responsible for setting the total phase, + // unless the Node.js major version is >= 13. + if (!timings.response || nodejsMajorVersion >= 13) { + timings.phases.total = Date.now() - timings.start; + } + }); + const onSocket = (socket) => { + timings.socket = Date.now(); + timings.phases.wait = timings.socket - timings.start; + const lookupListener = () => { + timings.lookup = Date.now(); + timings.phases.dns = timings.lookup - timings.socket; + }; + socket.prependOnceListener('lookup', lookupListener); + defer_to_connect_1.default(socket, { + connect: () => { + timings.connect = Date.now(); + if (timings.lookup === undefined) { + socket.removeListener('lookup', lookupListener); + timings.lookup = timings.connect; + timings.phases.dns = timings.lookup - timings.socket; + } + timings.phases.tcp = timings.connect - timings.lookup; + // This callback is called before flushing any data, + // so we don't need to set `timings.phases.request` here. + }, + secureConnect: () => { + timings.secureConnect = Date.now(); + timings.phases.tls = timings.secureConnect - timings.connect; + } + }); + }; + if (request.socket) { + onSocket(request.socket); + } + else { + request.prependOnceListener('socket', onSocket); + } + const onUpload = () => { + var _a; + timings.upload = Date.now(); + timings.phases.request = timings.upload - (_a = timings.secureConnect, (_a !== null && _a !== void 0 ? _a : timings.connect)); + }; + const writableFinished = () => { + if (typeof request.writableFinished === 'boolean') { + return request.writableFinished; + } + // Node.js doesn't have `request.writableFinished` property + return request.finished && request.outputSize === 0 && (!request.socket || request.socket.writableLength === 0); + }; + if (writableFinished()) { + onUpload(); + } + else { + request.prependOnceListener('finish', onUpload); + } + request.prependOnceListener('response', (response) => { + timings.response = Date.now(); + timings.phases.firstByte = timings.response - timings.upload; + response.timings = timings; + handleError(response); + response.prependOnceListener('end', () => { + timings.end = Date.now(); + timings.phases.download = timings.end - timings.response; + timings.phases.total = timings.end - timings.start; + }); + }); + return timings; +}; +exports.default = timer; +// For CommonJS default export support +module.exports = timer; +module.exports.default = timer; diff --git a/node_modules/@szmarczak/http-timer/package.json b/node_modules/@szmarczak/http-timer/package.json new file mode 100644 index 0000000..1b1cfa5 --- /dev/null +++ b/node_modules/@szmarczak/http-timer/package.json @@ -0,0 +1,74 @@ +{ + "name": "@szmarczak/http-timer", + "version": "4.0.5", + "description": "Timings for HTTP requests", + "main": "dist/source", + "engines": { + "node": ">=10" + }, + "scripts": { + "test": "xo && tsc --noEmit && nyc ava", + "build": "del-cli dist && tsc", + "prepare": "npm run build", + "coveralls": "nyc report --reporter=text-lcov | coveralls" + }, + "files": [ + "dist/source" + ], + "keywords": [ + "http", + "https", + "timer", + "timings" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/szmarczak/http-timer.git" + }, + "author": "Szymon Marczak", + "license": "MIT", + "bugs": { + "url": "https://github.com/szmarczak/http-timer/issues" + }, + "homepage": "https://github.com/szmarczak/http-timer#readme", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "devDependencies": { + "@ava/typescript": "^1.1.0", + "@sindresorhus/tsconfig": "^0.7.0", + "@types/node": "^13.5.1", + "@typescript-eslint/eslint-plugin": "^2.18.0", + "@typescript-eslint/parser": "^2.18.0", + "ava": "^3.2.0", + "coveralls": "^3.0.9", + "del-cli": "^3.0.0", + "eslint-config-xo-typescript": "^0.24.1", + "nyc": "^15.0.0", + "p-event": "^4.1.0", + "typescript": "^3.7.5", + "xo": "^0.25.3" + }, + "types": "dist/source", + "xo": { + "extends": "xo-typescript", + "extensions": [ + "ts" + ] + }, + "nyc": { + "extension": [ + ".ts" + ], + "exclude": [ + "**/tests/**" + ] + }, + "ava": { + "typescript": { + "rewritePaths": { + "tests/": "dist/tests/" + } + } + } +} diff --git a/node_modules/@types/cacheable-request/LICENSE b/node_modules/@types/cacheable-request/LICENSE new file mode 100644 index 0000000..4b1ad51 --- /dev/null +++ b/node_modules/@types/cacheable-request/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/cacheable-request/README.md b/node_modules/@types/cacheable-request/README.md new file mode 100644 index 0000000..8a6bd07 --- /dev/null +++ b/node_modules/@types/cacheable-request/README.md @@ -0,0 +1,16 @@ +# Installation +> `npm install --save @types/cacheable-request` + +# Summary +This package contains type definitions for cacheable-request ( https://github.com/lukechilds/cacheable-request#readme ). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cacheable-request + +Additional Details + * Last updated: Mon, 25 Mar 2019 16:32:10 GMT + * Dependencies: @types/keyv, @types/http-cache-semantics, @types/responselike, @types/node + * Global values: none + +# Credits +These definitions were written by BendingBender , Paul Melnikow . diff --git a/node_modules/@types/cacheable-request/index.d.ts b/node_modules/@types/cacheable-request/index.d.ts new file mode 100644 index 0000000..16e7782 --- /dev/null +++ b/node_modules/@types/cacheable-request/index.d.ts @@ -0,0 +1,137 @@ +// Type definitions for cacheable-request 6.0 +// Project: https://github.com/lukechilds/cacheable-request#readme +// Definitions by: BendingBender +// Paul Melnikow +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 + +/// + +import { request, RequestOptions, ClientRequest, ServerResponse } from 'http'; +import { URL } from 'url'; +import { EventEmitter } from 'events'; +import { Store } from 'keyv'; +import { Options as CacheSemanticsOptions } from 'http-cache-semantics'; +import ResponseLike = require('responselike'); + +export = CacheableRequest; + +declare const CacheableRequest: CacheableRequest; + +type RequestFn = typeof request; + +interface CacheableRequest { + new (requestFn: RequestFn, storageAdapter?: string | CacheableRequest.StorageAdapter): ( + opts: string | URL | (RequestOptions & CacheSemanticsOptions), + cb?: (response: ServerResponse | ResponseLike) => void + ) => CacheableRequest.Emitter; + + RequestError: typeof RequestErrorCls; + CacheError: typeof CacheErrorCls; +} + +declare namespace CacheableRequest { + type StorageAdapter = Store; + + interface Options { + /** + * If the cache should be used. Setting this to `false` will completely bypass the cache for the current request. + * @default true + */ + cache?: boolean; + + /** + * If set to `true` once a cached resource has expired it is deleted and will have to be re-requested. + * + * If set to `false`, after a cached resource's TTL expires it is kept in the cache and will be revalidated + * on the next request with `If-None-Match`/`If-Modified-Since` headers. + * @default false + */ + strictTtl?: boolean; + + /** + * Limits TTL. The `number` represents milliseconds. + * @default undefined + */ + maxTtl?: number; + + /** + * When set to `true`, if the DB connection fails we will automatically fallback to a network request. + * DB errors will still be emitted to notify you of the problem even though the request callback may succeed. + * @default false + */ + automaticFailover?: boolean; + + /** + * Forces refreshing the cache. If the response could be retrieved from the cache, it will perform a + * new request and override the cache instead. + * @default false + */ + forceRefresh?: boolean; + } + + interface Emitter extends EventEmitter { + addListener(event: 'request', listener: (request: ClientRequest) => void): this; + addListener( + event: 'response', + listener: (response: ServerResponse | ResponseLike) => void + ): this; + addListener(event: 'error', listener: (error: RequestError | CacheError) => void): this; + on(event: 'request', listener: (request: ClientRequest) => void): this; + on(event: 'response', listener: (response: ServerResponse | ResponseLike) => void): this; + on(event: 'error', listener: (error: RequestError | CacheError) => void): this; + once(event: 'request', listener: (request: ClientRequest) => void): this; + once(event: 'response', listener: (response: ServerResponse | ResponseLike) => void): this; + once(event: 'error', listener: (error: RequestError | CacheError) => void): this; + prependListener(event: 'request', listener: (request: ClientRequest) => void): this; + prependListener( + event: 'response', + listener: (response: ServerResponse | ResponseLike) => void + ): this; + prependListener(event: 'error', listener: (error: RequestError | CacheError) => void): this; + prependOnceListener(event: 'request', listener: (request: ClientRequest) => void): this; + prependOnceListener( + event: 'response', + listener: (response: ServerResponse | ResponseLike) => void + ): this; + prependOnceListener( + event: 'error', + listener: (error: RequestError | CacheError) => void + ): this; + removeListener(event: 'request', listener: (request: ClientRequest) => void): this; + removeListener( + event: 'response', + listener: (response: ServerResponse | ResponseLike) => void + ): this; + removeListener(event: 'error', listener: (error: RequestError | CacheError) => void): this; + off(event: 'request', listener: (request: ClientRequest) => void): this; + off(event: 'response', listener: (response: ServerResponse | ResponseLike) => void): this; + off(event: 'error', listener: (error: RequestError | CacheError) => void): this; + removeAllListeners(event?: 'request' | 'response' | 'error'): this; + listeners(event: 'request'): Array<(request: ClientRequest) => void>; + listeners(event: 'response'): Array<(response: ServerResponse | ResponseLike) => void>; + listeners(event: 'error'): Array<(error: RequestError | CacheError) => void>; + rawListeners(event: 'request'): Array<(request: ClientRequest) => void>; + rawListeners(event: 'response'): Array<(response: ServerResponse | ResponseLike) => void>; + rawListeners(event: 'error'): Array<(error: RequestError | CacheError) => void>; + emit(event: 'request', request: ClientRequest): boolean; + emit(event: 'response', response: ServerResponse | ResponseLike): boolean; + emit(event: 'error', error: RequestError | CacheError): boolean; + eventNames(): Array<'request' | 'response' | 'error'>; + listenerCount(type: 'request' | 'response' | 'error'): number; + } + + type RequestError = RequestErrorCls; + type CacheError = CacheErrorCls; +} + +declare class RequestErrorCls extends Error { + readonly name: 'RequestError'; + + constructor(error: Error); +} +declare class CacheErrorCls extends Error { + readonly name: 'CacheError'; + + constructor(error: Error); +} diff --git a/node_modules/@types/cacheable-request/package.json b/node_modules/@types/cacheable-request/package.json new file mode 100644 index 0000000..de01a1c --- /dev/null +++ b/node_modules/@types/cacheable-request/package.json @@ -0,0 +1,34 @@ +{ + "name": "@types/cacheable-request", + "version": "6.0.1", + "description": "TypeScript definitions for cacheable-request", + "license": "MIT", + "contributors": [ + { + "name": "BendingBender", + "url": "https://github.com/BendingBender", + "githubUsername": "BendingBender" + }, + { + "name": "Paul Melnikow", + "url": "https://github.com/paulmelnikow", + "githubUsername": "paulmelnikow" + } + ], + "main": "", + "types": "index", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/cacheable-request" + }, + "scripts": {}, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + }, + "typesPublisherContentHash": "c6afce5b9ca6ee2952549da29e2d4af2bd367dbf44a175a005063192d46b7814", + "typeScriptVersion": "2.3" +} \ No newline at end of file diff --git a/node_modules/@types/http-cache-semantics/LICENSE b/node_modules/@types/http-cache-semantics/LICENSE new file mode 100644 index 0000000..4b1ad51 --- /dev/null +++ b/node_modules/@types/http-cache-semantics/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/http-cache-semantics/README.md b/node_modules/@types/http-cache-semantics/README.md new file mode 100644 index 0000000..6245fb3 --- /dev/null +++ b/node_modules/@types/http-cache-semantics/README.md @@ -0,0 +1,16 @@ +# Installation +> `npm install --save @types/http-cache-semantics` + +# Summary +This package contains type definitions for http-cache-semantics ( https://github.com/kornelski/http-cache-semantics#readme ). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/http-cache-semantics + +Additional Details + * Last updated: Wed, 30 Jan 2019 18:47:31 GMT + * Dependencies: none + * Global values: none + +# Credits +These definitions were written by BendingBender . diff --git a/node_modules/@types/http-cache-semantics/index.d.ts b/node_modules/@types/http-cache-semantics/index.d.ts new file mode 100644 index 0000000..40545f3 --- /dev/null +++ b/node_modules/@types/http-cache-semantics/index.d.ts @@ -0,0 +1,170 @@ +// Type definitions for http-cache-semantics 4.0 +// Project: https://github.com/kornelski/http-cache-semantics#readme +// Definitions by: BendingBender +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export = CachePolicy; + +declare class CachePolicy { + constructor(req: CachePolicy.Request, res: CachePolicy.Response, options?: CachePolicy.Options); + + /** + * Returns `true` if the response can be stored in a cache. + * If it's `false` then you MUST NOT store either the request or the response. + */ + storable(): boolean; + + /** + * This is the most important method. Use this method to check whether the cached response is still fresh + * in the context of the new request. + * + * If it returns `true`, then the given `request` matches the original response this cache policy has been + * created with, and the response can be reused without contacting the server. Note that the old response + * can't be returned without being updated, see `responseHeaders()`. + * + * If it returns `false`, then the response may not be matching at all (e.g. it's for a different URL or method), + * or may require to be refreshed first (see `revalidationHeaders()`). + */ + satisfiesWithoutRevalidation(newRequest: CachePolicy.Request): boolean; + + /** + * Returns updated, filtered set of response headers to return to clients receiving the cached response. + * This function is necessary, because proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) + * and update response's `Age` to avoid doubling cache time. + * + * @example + * cachedResponse.headers = cachePolicy.responseHeaders(cachedResponse); + */ + responseHeaders(): CachePolicy.Headers; + + /** + * Returns approximate time in milliseconds until the response becomes stale (i.e. not fresh). + * + * After that time (when `timeToLive() <= 0`) the response might not be usable without revalidation. However, + * there are exceptions, e.g. a client can explicitly allow stale responses, so always check with + * `satisfiesWithoutRevalidation()`. + */ + timeToLive(): number; + + /** + * Chances are you'll want to store the `CachePolicy` object along with the cached response. + * `obj = policy.toObject()` gives a plain JSON-serializable object. + */ + toObject(): CachePolicy.CachePolicyObject; + + /** + * `policy = CachePolicy.fromObject(obj)` creates an instance from object created by `toObject()`. + */ + static fromObject(obj: CachePolicy.CachePolicyObject): CachePolicy; + + /** + * Returns updated, filtered set of request headers to send to the origin server to check if the cached + * response can be reused. These headers allow the origin server to return status 304 indicating the + * response is still fresh. All headers unrelated to caching are passed through as-is. + * + * Use this method when updating cache from the origin server. + * + * @example + * updateRequest.headers = cachePolicy.revalidationHeaders(updateRequest); + */ + revalidationHeaders(newRequest: CachePolicy.Request): CachePolicy.Headers; + + /** + * Use this method to update the cache after receiving a new response from the origin server. + */ + revalidatedPolicy( + revalidationRequest: CachePolicy.Request, + revalidationResponse: CachePolicy.Response + ): CachePolicy.RevalidationPolicy; +} + +declare namespace CachePolicy { + interface Request { + url?: string; + method?: string; + headers: Headers; + } + + interface Response { + status?: number; + headers: Headers; + } + + interface Options { + /** + * If `true`, then the response is evaluated from a perspective of a shared cache (i.e. `private` is not + * cacheable and `s-maxage` is respected). If `false`, then the response is evaluated from a perspective + * of a single-user cache (i.e. `private` is cacheable and `s-maxage` is ignored). + * `true` is recommended for HTTP clients. + * @default true + */ + shared?: boolean; + /** + * A fraction of response's age that is used as a fallback cache duration. The default is 0.1 (10%), + * e.g. if a file hasn't been modified for 100 days, it'll be cached for 100*0.1 = 10 days. + * @default 0.1 + */ + cacheHeuristic?: number; + /** + * A number of milliseconds to assume as the default time to cache responses with `Cache-Control: immutable`. + * Note that [per RFC](https://httpwg.org/specs/rfc8246.html#the-immutable-cache-control-extension) + * these can become stale, so `max-age` still overrides the default. + * @default 24*3600*1000 (24h) + */ + immutableMinTimeToLive?: number; + /** + * If `true`, common anti-cache directives will be completely ignored if the non-standard `pre-check` + * and `post-check` directives are present. These two useless directives are most commonly found + * in bad StackOverflow answers and PHP's "session limiter" defaults. + * @default false + */ + ignoreCargoCult?: boolean; + /** + * If `false`, then server's `Date` header won't be used as the base for `max-age`. This is against the RFC, + * but it's useful if you want to cache responses with very short `max-age`, but your local clock + * is not exactly in sync with the server's. + * @default true + */ + trustServerDate?: boolean; + } + + interface CachePolicyObject { + v: number; + t: number; + sh: boolean; + ch: number; + imm: number; + st: number; + resh: Headers; + rescc: { [key: string]: string }; + m: string; + u?: string; + h?: string; + a: boolean; + reqh: Headers | null; + reqcc: { [key: string]: string }; + } + + interface Headers { + [header: string]: string | string[] | undefined; + } + + interface RevalidationPolicy { + /** + * A new `CachePolicy` with HTTP headers updated from `revalidationResponse`. You can always replace + * the old cached `CachePolicy` with the new one. + */ + policy: CachePolicy; + /** + * Boolean indicating whether the response body has changed. + * + * - If `false`, then a valid 304 Not Modified response has been received, and you can reuse the old + * cached response body. + * - If `true`, you should use new response's body (if present), or make another request to the origin + * server without any conditional headers (i.e. don't use `revalidationHeaders()` this time) to get + * the new resource. + */ + modified: boolean; + matches: boolean; + } +} diff --git a/node_modules/@types/http-cache-semantics/package.json b/node_modules/@types/http-cache-semantics/package.json new file mode 100644 index 0000000..3dcde54 --- /dev/null +++ b/node_modules/@types/http-cache-semantics/package.json @@ -0,0 +1,23 @@ +{ + "name": "@types/http-cache-semantics", + "version": "4.0.0", + "description": "TypeScript definitions for http-cache-semantics", + "license": "MIT", + "contributors": [ + { + "name": "BendingBender", + "url": "https://github.com/BendingBender", + "githubUsername": "BendingBender" + } + ], + "main": "", + "types": "index", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git" + }, + "scripts": {}, + "dependencies": {}, + "typesPublisherContentHash": "0f2f0f2e4444736e9747a8b7b3cd04c9064067e0181263cfb85337511ae13a35", + "typeScriptVersion": "2.0" +} \ No newline at end of file diff --git a/node_modules/@types/keyv/LICENSE b/node_modules/@types/keyv/LICENSE new file mode 100644 index 0000000..4b1ad51 --- /dev/null +++ b/node_modules/@types/keyv/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/keyv/README.md b/node_modules/@types/keyv/README.md new file mode 100644 index 0000000..681af21 --- /dev/null +++ b/node_modules/@types/keyv/README.md @@ -0,0 +1,16 @@ +# Installation +> `npm install --save @types/keyv` + +# Summary +This package contains type definitions for keyv (https://github.com/lukechilds/keyv). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/keyv. + +### Additional Details + * Last updated: Mon, 23 Dec 2019 16:40:54 GMT + * Dependencies: [@types/node](https://npmjs.com/package/@types/node) + * Global values: none + +# Credits +These definitions were written by AryloYeung (https://github.com/Arylo), and BendingBender (https://github.com/BendingBender). diff --git a/node_modules/@types/keyv/index.d.ts b/node_modules/@types/keyv/index.d.ts new file mode 100644 index 0000000..d95745b --- /dev/null +++ b/node_modules/@types/keyv/index.d.ts @@ -0,0 +1,70 @@ +// Type definitions for keyv 3.1 +// Project: https://github.com/lukechilds/keyv +// Definitions by: AryloYeung +// BendingBender +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +/// +import { EventEmitter } from 'events'; + +declare class Keyv extends EventEmitter { + /** + * @param opts The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options. + */ + constructor(opts?: Keyv.Options); + /** + * @param uri The connection string URI. + * + * Merged into the options object as options.uri. + * @param opts The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options. + */ + constructor(uri?: string, opts?: Keyv.Options); + + /** Returns the value. */ + get(key: string): Promise; + /** + * Set a value. + * + * By default keys are persistent. You can set an expiry TTL in milliseconds. + */ + set(key: string, value: TValue, ttl?: number): Promise; + /** + * Deletes an entry. + * + * Returns `true` if the key existed, `false` if not. + */ + delete(key: string): Promise; + /** Delete all entries in the current namespace. */ + clear(): Promise; +} + +declare namespace Keyv { + interface Options { + /** Namespace for the current instance. */ + namespace?: string; + /** A custom serialization function. */ + serialize?: (data: TValue) => string; + /** A custom deserialization function. */ + deserialize?: (data: string) => TValue; + /** The connection string URI. */ + uri?: string; + /** The storage adapter instance to be used by Keyv. */ + store?: Store; + /** Default TTL. Can be overridden by specififying a TTL on `.set()`. */ + ttl?: number; + /** Specify an adapter to use. e.g `'redis'` or `'mongodb'`. */ + adapter?: 'redis' | 'mongodb' | 'mongo' | 'sqlite' | 'postgresql' | 'postgres' | 'mysql'; + + [key: string]: any; + } + + interface Store { + get(key: string): TValue | Promise | undefined; + set(key: string, value: TValue, ttl?: number): any; + delete(key: string): boolean | Promise; + clear(): void | Promise; + } +} + +export = Keyv; diff --git a/node_modules/@types/keyv/package.json b/node_modules/@types/keyv/package.json new file mode 100644 index 0000000..2527ee4 --- /dev/null +++ b/node_modules/@types/keyv/package.json @@ -0,0 +1,31 @@ +{ + "name": "@types/keyv", + "version": "3.1.1", + "description": "TypeScript definitions for keyv", + "license": "MIT", + "contributors": [ + { + "name": "AryloYeung", + "url": "https://github.com/Arylo", + "githubUsername": "Arylo" + }, + { + "name": "BendingBender", + "url": "https://github.com/BendingBender", + "githubUsername": "BendingBender" + } + ], + "main": "", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/keyv" + }, + "scripts": {}, + "dependencies": { + "@types/node": "*" + }, + "typesPublisherContentHash": "883f9e92997b7991324e37284aa16e71d6f43731110ec0e7f62ccca68960aec3", + "typeScriptVersion": "2.8" +} \ No newline at end of file diff --git a/node_modules/@types/node/LICENSE b/node_modules/@types/node/LICENSE new file mode 100755 index 0000000..9e841e7 --- /dev/null +++ b/node_modules/@types/node/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/node/README.md b/node_modules/@types/node/README.md new file mode 100755 index 0000000..4c78366 --- /dev/null +++ b/node_modules/@types/node/README.md @@ -0,0 +1,16 @@ +# Installation +> `npm install --save @types/node` + +# Summary +This package contains type definitions for Node.js (http://nodejs.org/). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node. + +### Additional Details + * Last updated: Tue, 27 Apr 2021 14:31:24 GMT + * Dependencies: none + * Global values: `AbortController`, `AbortSignal`, `Buffer`, `__dirname`, `__filename`, `clearImmediate`, `clearInterval`, `clearTimeout`, `console`, `exports`, `global`, `module`, `process`, `queueMicrotask`, `require`, `setImmediate`, `setInterval`, `setTimeout` + +# Credits +These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [DefinitelyTyped](https://github.com/DefinitelyTyped), [Alberto Schiabel](https://github.com/jkomyno), [Alvis HT Tang](https://github.com/alvis), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [Chigozirim C.](https://github.com/smac89), [David Junger](https://github.com/touffy), [Deividas Bakanas](https://github.com/DeividasBakanas), [Eugene Y. Q. Shen](https://github.com/eyqs), [Hannes Magnusson](https://github.com/Hannes-Magnusson-CK), [Hoàng Văn Khải](https://github.com/KSXGitHub), [Huw](https://github.com/hoo29), [Kelvin Jin](https://github.com/kjin), [Klaus Meinhardt](https://github.com/ajafff), [Lishude](https://github.com/islishude), [Mariusz Wiktorczyk](https://github.com/mwiktorczyk), [Mohsen Azimi](https://github.com/mohsen1), [Nicolas Even](https://github.com/n-e), [Nikita Galkin](https://github.com/galkin), [Parambir Singh](https://github.com/parambirs), [Sebastian Silbermann](https://github.com/eps1lon), [Simon Schick](https://github.com/SimonSchick), [Thomas den Hollander](https://github.com/ThomasdenH), [Wilco Bakker](https://github.com/WilcoBakker), [wwwy3y3](https://github.com/wwwy3y3), [Samuel Ainsworth](https://github.com/samuela), [Kyle Uehlein](https://github.com/kuehlein), [Thanik Bhongbhibhat](https://github.com/bhongy), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Minh Son Nguyen](https://github.com/nguymin4), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Surasak Chaisurin](https://github.com/Ryan-Willpower), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Jason Kwok](https://github.com/JasonHK), [Victor Perin](https://github.com/victorperin), and [Yongsheng Zhang](https://github.com/ZYSzys). diff --git a/node_modules/@types/node/assert.d.ts b/node_modules/@types/node/assert.d.ts new file mode 100755 index 0000000..720bbc6 --- /dev/null +++ b/node_modules/@types/node/assert.d.ts @@ -0,0 +1,129 @@ +declare module 'node:assert' { + import assert = require('assert'); + export = assert; +} + +declare module 'assert' { + /** An alias of `assert.ok()`. */ + function assert(value: any, message?: string | Error): asserts value; + namespace assert { + class AssertionError extends Error { + actual: any; + expected: any; + operator: string; + generatedMessage: boolean; + code: 'ERR_ASSERTION'; + + constructor(options?: { + /** If provided, the error message is set to this value. */ + message?: string; + /** The `actual` property on the error instance. */ + actual?: any; + /** The `expected` property on the error instance. */ + expected?: any; + /** The `operator` property on the error instance. */ + operator?: string; + /** If provided, the generated stack trace omits frames before this function. */ + // tslint:disable-next-line:ban-types + stackStartFn?: Function; + }); + } + + class CallTracker { + calls(exact?: number): () => void; + calls any>(fn?: Func, exact?: number): Func; + report(): CallTrackerReportInformation[]; + verify(): void; + } + interface CallTrackerReportInformation { + message: string; + /** The actual number of times the function was called. */ + actual: number; + /** The number of times the function was expected to be called. */ + expected: number; + /** The name of the function that is wrapped. */ + operator: string; + /** A stack trace of the function. */ + stack: object; + } + + type AssertPredicate = RegExp | (new () => object) | ((thrown: any) => boolean) | object | Error; + + function fail(message?: string | Error): never; + /** @deprecated since v10.0.0 - use fail([message]) or other assert functions instead. */ + function fail( + actual: any, + expected: any, + message?: string | Error, + operator?: string, + // tslint:disable-next-line:ban-types + stackStartFn?: Function, + ): never; + function ok(value: any, message?: string | Error): asserts value; + /** @deprecated since v9.9.0 - use strictEqual() instead. */ + function equal(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use notStrictEqual() instead. */ + function notEqual(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use deepStrictEqual() instead. */ + function deepEqual(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use notDeepStrictEqual() instead. */ + function notDeepEqual(actual: any, expected: any, message?: string | Error): void; + function strictEqual(actual: any, expected: T, message?: string | Error): asserts actual is T; + function notStrictEqual(actual: any, expected: any, message?: string | Error): void; + function deepStrictEqual(actual: any, expected: T, message?: string | Error): asserts actual is T; + function notDeepStrictEqual(actual: any, expected: any, message?: string | Error): void; + + function throws(block: () => any, message?: string | Error): void; + function throws(block: () => any, error: AssertPredicate, message?: string | Error): void; + function doesNotThrow(block: () => any, message?: string | Error): void; + function doesNotThrow(block: () => any, error: AssertPredicate, message?: string | Error): void; + + function ifError(value: any): asserts value is null | undefined; + + function rejects(block: (() => Promise) | Promise, message?: string | Error): Promise; + function rejects( + block: (() => Promise) | Promise, + error: AssertPredicate, + message?: string | Error, + ): Promise; + function doesNotReject(block: (() => Promise) | Promise, message?: string | Error): Promise; + function doesNotReject( + block: (() => Promise) | Promise, + error: AssertPredicate, + message?: string | Error, + ): Promise; + + function match(value: string, regExp: RegExp, message?: string | Error): void; + function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void; + + const strict: Omit< + typeof assert, + | 'equal' + | 'notEqual' + | 'deepEqual' + | 'notDeepEqual' + | 'ok' + | 'strictEqual' + | 'deepStrictEqual' + | 'ifError' + | 'strict' + > & { + (value: any, message?: string | Error): asserts value; + equal: typeof strictEqual; + notEqual: typeof notStrictEqual; + deepEqual: typeof deepStrictEqual; + notDeepEqual: typeof notDeepStrictEqual; + + // Mapped types and assertion functions are incompatible? + // TS2775: Assertions require every name in the call target + // to be declared with an explicit type annotation. + ok: typeof ok; + strictEqual: typeof strictEqual; + deepStrictEqual: typeof deepStrictEqual; + ifError: typeof ifError; + strict: typeof strict; + }; + } + + export = assert; +} diff --git a/node_modules/@types/node/assert/strict.d.ts b/node_modules/@types/node/assert/strict.d.ts new file mode 100755 index 0000000..bc3b2a7 --- /dev/null +++ b/node_modules/@types/node/assert/strict.d.ts @@ -0,0 +1,4 @@ +declare module 'assert/strict' { + import { strict } from 'assert'; + export = strict; +} diff --git a/node_modules/@types/node/async_hooks.d.ts b/node_modules/@types/node/async_hooks.d.ts new file mode 100755 index 0000000..153ebde --- /dev/null +++ b/node_modules/@types/node/async_hooks.d.ts @@ -0,0 +1,233 @@ +/** + * Async Hooks module: https://nodejs.org/api/async_hooks.html + */ +declare module 'node:async_hooks' { + export * from 'async_hooks'; +} + +/** + * Async Hooks module: https://nodejs.org/api/async_hooks.html + */ +declare module 'async_hooks' { + /** + * Returns the asyncId of the current execution context. + */ + function executionAsyncId(): number; + + /** + * The resource representing the current execution. + * Useful to store data within the resource. + * + * Resource objects returned by `executionAsyncResource()` are most often internal + * Node.js handle objects with undocumented APIs. Using any functions or properties + * on the object is likely to crash your application and should be avoided. + * + * Using `executionAsyncResource()` in the top-level execution context will + * return an empty object as there is no handle or request object to use, + * but having an object representing the top-level can be helpful. + */ + function executionAsyncResource(): object; + + /** + * Returns the ID of the resource responsible for calling the callback that is currently being executed. + */ + function triggerAsyncId(): number; + + interface HookCallbacks { + /** + * Called when a class is constructed that has the possibility to emit an asynchronous event. + * @param asyncId a unique ID for the async resource + * @param type the type of the async resource + * @param triggerAsyncId the unique ID of the async resource in whose execution context this async resource was created + * @param resource reference to the resource representing the async operation, needs to be released during destroy + */ + init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void; + + /** + * When an asynchronous operation is initiated or completes a callback is called to notify the user. + * The before callback is called just before said callback is executed. + * @param asyncId the unique identifier assigned to the resource about to execute the callback. + */ + before?(asyncId: number): void; + + /** + * Called immediately after the callback specified in before is completed. + * @param asyncId the unique identifier assigned to the resource which has executed the callback. + */ + after?(asyncId: number): void; + + /** + * Called when a promise has resolve() called. This may not be in the same execution id + * as the promise itself. + * @param asyncId the unique id for the promise that was resolve()d. + */ + promiseResolve?(asyncId: number): void; + + /** + * Called after the resource corresponding to asyncId is destroyed + * @param asyncId a unique ID for the async resource + */ + destroy?(asyncId: number): void; + } + + interface AsyncHook { + /** + * Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop. + */ + enable(): this; + + /** + * Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled. + */ + disable(): this; + } + + /** + * Registers functions to be called for different lifetime events of each async operation. + * @param options the callbacks to register + * @return an AsyncHooks instance used for disabling and enabling hooks + */ + function createHook(options: HookCallbacks): AsyncHook; + + interface AsyncResourceOptions { + /** + * The ID of the execution context that created this async event. + * Default: `executionAsyncId()` + */ + triggerAsyncId?: number; + + /** + * Disables automatic `emitDestroy` when the object is garbage collected. + * This usually does not need to be set (even if `emitDestroy` is called + * manually), unless the resource's `asyncId` is retrieved and the + * sensitive API's `emitDestroy` is called with it. + * Default: `false` + */ + requireManualDestroy?: boolean; + } + + /** + * The class AsyncResource was designed to be extended by the embedder's async resources. + * Using this users can easily trigger the lifetime events of their own resources. + */ + class AsyncResource { + /** + * AsyncResource() is meant to be extended. Instantiating a + * new AsyncResource() also triggers init. If triggerAsyncId is omitted then + * async_hook.executionAsyncId() is used. + * @param type The type of async event. + * @param triggerAsyncId The ID of the execution context that created + * this async event (default: `executionAsyncId()`), or an + * AsyncResourceOptions object (since 9.3) + */ + constructor(type: string, triggerAsyncId?: number|AsyncResourceOptions); + + /** + * Binds the given function to the current execution context. + * @param fn The function to bind to the current execution context. + * @param type An optional name to associate with the underlying `AsyncResource`. + */ + static bind any>(fn: Func, type?: string): Func & { asyncResource: AsyncResource }; + + /** + * Binds the given function to execute to this `AsyncResource`'s scope. + * @param fn The function to bind to the current `AsyncResource`. + */ + bind any>(fn: Func): Func & { asyncResource: AsyncResource }; + + /** + * Call the provided function with the provided arguments in the + * execution context of the async resource. This will establish the + * context, trigger the AsyncHooks before callbacks, call the function, + * trigger the AsyncHooks after callbacks, and then restore the original + * execution context. + * @param fn The function to call in the execution context of this + * async resource. + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runInAsyncScope(fn: (this: This, ...args: any[]) => Result, thisArg?: This, ...args: any[]): Result; + + /** + * Call AsyncHooks destroy callbacks. + */ + emitDestroy(): this; + + /** + * @return the unique ID assigned to this AsyncResource instance. + */ + asyncId(): number; + + /** + * @return the trigger ID for this AsyncResource instance. + */ + triggerAsyncId(): number; + } + + /** + * When having multiple instances of `AsyncLocalStorage`, they are independent + * from each other. It is safe to instantiate this class multiple times. + */ + class AsyncLocalStorage { + /** + * This method disables the instance of `AsyncLocalStorage`. All subsequent calls + * to `asyncLocalStorage.getStore()` will return `undefined` until + * `asyncLocalStorage.run()` is called again. + * + * When calling `asyncLocalStorage.disable()`, all current contexts linked to the + * instance will be exited. + * + * Calling `asyncLocalStorage.disable()` is required before the + * `asyncLocalStorage` can be garbage collected. This does not apply to stores + * provided by the `asyncLocalStorage`, as those objects are garbage collected + * along with the corresponding async resources. + * + * This method is to be used when the `asyncLocalStorage` is not in use anymore + * in the current process. + */ + disable(): void; + + /** + * This method returns the current store. If this method is called outside of an + * asynchronous context initialized by calling `asyncLocalStorage.run`, it will + * return `undefined`. + */ + getStore(): T | undefined; + + /** + * This methods runs a function synchronously within a context and return its + * return value. The store is not accessible outside of the callback function or + * the asynchronous operations created within the callback. + * + * Optionally, arguments can be passed to the function. They will be passed to the + * callback function. + * + * I the callback function throws an error, it will be thrown by `run` too. The + * stacktrace will not be impacted by this call and the context will be exited. + */ + // TODO: Apply generic vararg once available + run(store: T, callback: (...args: any[]) => R, ...args: any[]): R; + + /** + * This methods runs a function synchronously outside of a context and return its + * return value. The store is not accessible within the callback function or the + * asynchronous operations created within the callback. + * + * Optionally, arguments can be passed to the function. They will be passed to the + * callback function. + * + * If the callback function throws an error, it will be thrown by `exit` too. The + * stacktrace will not be impacted by this call and the context will be + * re-entered. + */ + // TODO: Apply generic vararg once available + exit(callback: (...args: any[]) => R, ...args: any[]): R; + + /** + * Calling `asyncLocalStorage.enterWith(store)` will transition into the context + * for the remainder of the current synchronous execution and will persist + * through any following asynchronous calls. + */ + enterWith(store: T): void; + } +} diff --git a/node_modules/@types/node/base.d.ts b/node_modules/@types/node/base.d.ts new file mode 100755 index 0000000..fa67179 --- /dev/null +++ b/node_modules/@types/node/base.d.ts @@ -0,0 +1,19 @@ +// NOTE: These definitions support NodeJS and TypeScript 3.7. + +// NOTE: TypeScript version-specific augmentations can be found in the following paths: +// - ~/base.d.ts - Shared definitions common to all TypeScript versions +// - ~/index.d.ts - Definitions specific to TypeScript 2.1 +// - ~/ts3.7/base.d.ts - Definitions specific to TypeScript 3.7 +// - ~/ts3.7/index.d.ts - Definitions specific to TypeScript 3.7 with assert pulled in + +// Reference required types from the default lib: +/// +/// +/// +/// + +// Base definitions for all NodeJS modules that are not specific to any version of TypeScript: +/// + +// TypeScript 3.7-specific augmentations: +/// diff --git a/node_modules/@types/node/buffer.d.ts b/node_modules/@types/node/buffer.d.ts new file mode 100755 index 0000000..da17c75 --- /dev/null +++ b/node_modules/@types/node/buffer.d.ts @@ -0,0 +1,26 @@ +declare module 'node:buffer' { + export * from 'buffer'; +} + +declare module 'buffer' { + export const INSPECT_MAX_BYTES: number; + export const kMaxLength: number; + export const kStringMaxLength: number; + export const constants: { + MAX_LENGTH: number; + MAX_STRING_LENGTH: number; + }; + const BuffType: typeof Buffer; + + export type TranscodeEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "latin1" | "binary"; + + export function transcode(source: Uint8Array, fromEnc: TranscodeEncoding, toEnc: TranscodeEncoding): Buffer; + + export const SlowBuffer: { + /** @deprecated since v6.0.0, use `Buffer.allocUnsafeSlow()` */ + new(size: number): Buffer; + prototype: Buffer; + }; + + export { BuffType as Buffer }; +} diff --git a/node_modules/@types/node/child_process.d.ts b/node_modules/@types/node/child_process.d.ts new file mode 100755 index 0000000..48adc4e --- /dev/null +++ b/node_modules/@types/node/child_process.d.ts @@ -0,0 +1,514 @@ +declare module 'node:child_process' { + export * from 'child_process'; +} + +declare module 'child_process' { + import { BaseEncodingOptions } from 'node:fs'; + import * as events from 'node:events'; + import * as net from 'node:net'; + import { Writable, Readable, Stream, Pipe } from 'node:stream'; + + type Serializable = string | object | number | boolean; + type SendHandle = net.Socket | net.Server; + + interface ChildProcess extends events.EventEmitter { + stdin: Writable | null; + stdout: Readable | null; + stderr: Readable | null; + readonly channel?: Pipe | null; + readonly stdio: [ + Writable | null, // stdin + Readable | null, // stdout + Readable | null, // stderr + Readable | Writable | null | undefined, // extra + Readable | Writable | null | undefined // extra + ]; + readonly killed: boolean; + readonly pid: number; + readonly connected: boolean; + readonly exitCode: number | null; + readonly signalCode: NodeJS.Signals | null; + readonly spawnargs: string[]; + readonly spawnfile: string; + kill(signal?: NodeJS.Signals | number): boolean; + send(message: Serializable, callback?: (error: Error | null) => void): boolean; + send(message: Serializable, sendHandle?: SendHandle, callback?: (error: Error | null) => void): boolean; + send(message: Serializable, sendHandle?: SendHandle, options?: MessageOptions, callback?: (error: Error | null) => void): boolean; + disconnect(): void; + unref(): void; + ref(): void; + + /** + * events.EventEmitter + * 1. close + * 2. disconnect + * 3. error + * 4. exit + * 5. message + */ + + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + addListener(event: "disconnect", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + addListener(event: "message", listener: (message: Serializable, sendHandle: SendHandle) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close", code: number | null, signal: NodeJS.Signals | null): boolean; + emit(event: "disconnect"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "exit", code: number | null, signal: NodeJS.Signals | null): boolean; + emit(event: "message", message: Serializable, sendHandle: SendHandle): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + on(event: "disconnect", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + on(event: "message", listener: (message: Serializable, sendHandle: SendHandle) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + once(event: "disconnect", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + once(event: "message", listener: (message: Serializable, sendHandle: SendHandle) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + prependListener(event: "disconnect", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + prependListener(event: "message", listener: (message: Serializable, sendHandle: SendHandle) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + prependOnceListener(event: "disconnect", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this; + prependOnceListener(event: "message", listener: (message: Serializable, sendHandle: SendHandle) => void): this; + } + + // return this object when stdio option is undefined or not specified + interface ChildProcessWithoutNullStreams extends ChildProcess { + stdin: Writable; + stdout: Readable; + stderr: Readable; + readonly stdio: [ + Writable, // stdin + Readable, // stdout + Readable, // stderr + Readable | Writable | null | undefined, // extra, no modification + Readable | Writable | null | undefined // extra, no modification + ]; + } + + // return this object when stdio option is a tuple of 3 + interface ChildProcessByStdio< + I extends null | Writable, + O extends null | Readable, + E extends null | Readable, + > extends ChildProcess { + stdin: I; + stdout: O; + stderr: E; + readonly stdio: [ + I, + O, + E, + Readable | Writable | null | undefined, // extra, no modification + Readable | Writable | null | undefined // extra, no modification + ]; + } + + interface MessageOptions { + keepOpen?: boolean; + } + + type StdioOptions = "pipe" | "ignore" | "inherit" | Array<("pipe" | "ipc" | "ignore" | "inherit" | Stream | number | null | undefined)>; + + type SerializationType = 'json' | 'advanced'; + + interface MessagingOptions { + /** + * Specify the kind of serialization used for sending messages between processes. + * @default 'json' + */ + serialization?: SerializationType; + } + + interface ProcessEnvOptions { + uid?: number; + gid?: number; + cwd?: string; + env?: NodeJS.ProcessEnv; + } + + interface CommonOptions extends ProcessEnvOptions { + /** + * @default true + */ + windowsHide?: boolean; + /** + * @default 0 + */ + timeout?: number; + } + + interface CommonSpawnOptions extends CommonOptions, MessagingOptions { + argv0?: string; + stdio?: StdioOptions; + shell?: boolean | string; + windowsVerbatimArguments?: boolean; + } + + interface SpawnOptions extends CommonSpawnOptions { + detached?: boolean; + } + + interface SpawnOptionsWithoutStdio extends SpawnOptions { + stdio?: 'pipe' | Array; + } + + type StdioNull = 'inherit' | 'ignore' | Stream; + type StdioPipe = undefined | null | 'pipe'; + + interface SpawnOptionsWithStdioTuple< + Stdin extends StdioNull | StdioPipe, + Stdout extends StdioNull | StdioPipe, + Stderr extends StdioNull | StdioPipe, + > extends SpawnOptions { + stdio: [Stdin, Stdout, Stderr]; + } + + // overloads of spawn without 'args' + function spawn(command: string, options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams; + + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + + function spawn(command: string, options: SpawnOptions): ChildProcess; + + // overloads of spawn with 'args' + function spawn(command: string, args?: ReadonlyArray, options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams; + + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + function spawn( + command: string, + args: ReadonlyArray, + options: SpawnOptionsWithStdioTuple, + ): ChildProcessByStdio; + + function spawn(command: string, args: ReadonlyArray, options: SpawnOptions): ChildProcess; + + interface ExecOptions extends CommonOptions { + shell?: string; + maxBuffer?: number; + killSignal?: NodeJS.Signals | number; + } + + interface ExecOptionsWithStringEncoding extends ExecOptions { + encoding: BufferEncoding; + } + + interface ExecOptionsWithBufferEncoding extends ExecOptions { + encoding: BufferEncoding | null; // specify `null`. + } + + interface ExecException extends Error { + cmd?: string; + killed?: boolean; + code?: number; + signal?: NodeJS.Signals; + } + + // no `options` definitely means stdout/stderr are `string`. + function exec(command: string, callback?: (error: ExecException | null, stdout: string, stderr: string) => void): ChildProcess; + + // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. + function exec(command: string, options: { encoding: "buffer" | null } & ExecOptions, callback?: (error: ExecException | null, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + + // `options` with well known `encoding` means stdout/stderr are definitely `string`. + function exec(command: string, options: { encoding: BufferEncoding } & ExecOptions, callback?: (error: ExecException | null, stdout: string, stderr: string) => void): ChildProcess; + + // `options` with an `encoding` whose type is `string` means stdout/stderr could either be `Buffer` or `string`. + // There is no guarantee the `encoding` is unknown as `string` is a superset of `BufferEncoding`. + function exec( + command: string, + options: { encoding: BufferEncoding } & ExecOptions, + callback?: (error: ExecException | null, stdout: string | Buffer, stderr: string | Buffer) => void, + ): ChildProcess; + + // `options` without an `encoding` means stdout/stderr are definitely `string`. + function exec(command: string, options: ExecOptions, callback?: (error: ExecException | null, stdout: string, stderr: string) => void): ChildProcess; + + // fallback if nothing else matches. Worst case is always `string | Buffer`. + function exec( + command: string, + options: (BaseEncodingOptions & ExecOptions) | undefined | null, + callback?: (error: ExecException | null, stdout: string | Buffer, stderr: string | Buffer) => void, + ): ChildProcess; + + interface PromiseWithChild extends Promise { + child: ChildProcess; + } + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + namespace exec { + function __promisify__(command: string): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(command: string, options: { encoding: "buffer" | null } & ExecOptions): PromiseWithChild<{ stdout: Buffer, stderr: Buffer }>; + function __promisify__(command: string, options: { encoding: BufferEncoding } & ExecOptions): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(command: string, options: ExecOptions): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(command: string, options?: (BaseEncodingOptions & ExecOptions) | null): PromiseWithChild<{ stdout: string | Buffer, stderr: string | Buffer }>; + } + + interface ExecFileOptions extends CommonOptions { + maxBuffer?: number; + killSignal?: NodeJS.Signals | number; + windowsVerbatimArguments?: boolean; + shell?: boolean | string; + } + interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { + encoding: BufferEncoding; + } + interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { + encoding: 'buffer' | null; + } + interface ExecFileOptionsWithOtherEncoding extends ExecFileOptions { + encoding: BufferEncoding; + } + type ExecFileException = ExecException & NodeJS.ErrnoException; + + function execFile(file: string): ChildProcess; + function execFile(file: string, options: (BaseEncodingOptions & ExecFileOptions) | undefined | null): ChildProcess; + function execFile(file: string, args?: ReadonlyArray | null): ChildProcess; + function execFile(file: string, args: ReadonlyArray | undefined | null, options: (BaseEncodingOptions & ExecFileOptions) | undefined | null): ChildProcess; + + // no `options` definitely means stdout/stderr are `string`. + function execFile(file: string, callback: (error: ExecFileException | null, stdout: string, stderr: string) => void): ChildProcess; + function execFile(file: string, args: ReadonlyArray | undefined | null, callback: (error: ExecFileException | null, stdout: string, stderr: string) => void): ChildProcess; + + // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. + function execFile(file: string, options: ExecFileOptionsWithBufferEncoding, callback: (error: ExecFileException | null, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + function execFile( + file: string, + args: ReadonlyArray | undefined | null, + options: ExecFileOptionsWithBufferEncoding, + callback: (error: ExecFileException | null, stdout: Buffer, stderr: Buffer) => void, + ): ChildProcess; + + // `options` with well known `encoding` means stdout/stderr are definitely `string`. + function execFile(file: string, options: ExecFileOptionsWithStringEncoding, callback: (error: ExecFileException | null, stdout: string, stderr: string) => void): ChildProcess; + function execFile( + file: string, + args: ReadonlyArray | undefined | null, + options: ExecFileOptionsWithStringEncoding, + callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + + // `options` with an `encoding` whose type is `string` means stdout/stderr could either be `Buffer` or `string`. + // There is no guarantee the `encoding` is unknown as `string` is a superset of `BufferEncoding`. + function execFile( + file: string, + options: ExecFileOptionsWithOtherEncoding, + callback: (error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void, + ): ChildProcess; + function execFile( + file: string, + args: ReadonlyArray | undefined | null, + options: ExecFileOptionsWithOtherEncoding, + callback: (error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void, + ): ChildProcess; + + // `options` without an `encoding` means stdout/stderr are definitely `string`. + function execFile(file: string, options: ExecFileOptions, callback: (error: ExecFileException | null, stdout: string, stderr: string) => void): ChildProcess; + function execFile( + file: string, + args: ReadonlyArray | undefined | null, + options: ExecFileOptions, + callback: (error: ExecFileException | null, stdout: string, stderr: string) => void + ): ChildProcess; + + // fallback if nothing else matches. Worst case is always `string | Buffer`. + function execFile( + file: string, + options: (BaseEncodingOptions & ExecFileOptions) | undefined | null, + callback: ((error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void) | undefined | null, + ): ChildProcess; + function execFile( + file: string, + args: ReadonlyArray | undefined | null, + options: (BaseEncodingOptions & ExecFileOptions) | undefined | null, + callback: ((error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void) | undefined | null, + ): ChildProcess; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + namespace execFile { + function __promisify__(file: string): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, args: ReadonlyArray | undefined | null): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, options: ExecFileOptionsWithBufferEncoding): PromiseWithChild<{ stdout: Buffer, stderr: Buffer }>; + function __promisify__(file: string, args: ReadonlyArray | undefined | null, options: ExecFileOptionsWithBufferEncoding): PromiseWithChild<{ stdout: Buffer, stderr: Buffer }>; + function __promisify__(file: string, options: ExecFileOptionsWithStringEncoding): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, args: ReadonlyArray | undefined | null, options: ExecFileOptionsWithStringEncoding): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, options: ExecFileOptionsWithOtherEncoding): PromiseWithChild<{ stdout: string | Buffer, stderr: string | Buffer }>; + function __promisify__( + file: string, + args: ReadonlyArray | undefined | null, + options: ExecFileOptionsWithOtherEncoding, + ): PromiseWithChild<{ stdout: string | Buffer, stderr: string | Buffer }>; + function __promisify__(file: string, options: ExecFileOptions): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, args: ReadonlyArray | undefined | null, options: ExecFileOptions): PromiseWithChild<{ stdout: string, stderr: string }>; + function __promisify__(file: string, options: (BaseEncodingOptions & ExecFileOptions) | undefined | null): PromiseWithChild<{ stdout: string | Buffer, stderr: string | Buffer }>; + function __promisify__( + file: string, + args: ReadonlyArray | undefined | null, + options: (BaseEncodingOptions & ExecFileOptions) | undefined | null, + ): PromiseWithChild<{ stdout: string | Buffer, stderr: string | Buffer }>; + } + + interface ForkOptions extends ProcessEnvOptions, MessagingOptions { + execPath?: string; + execArgv?: string[]; + silent?: boolean; + stdio?: StdioOptions; + detached?: boolean; + windowsVerbatimArguments?: boolean; + } + function fork(modulePath: string, options?: ForkOptions): ChildProcess; + function fork(modulePath: string, args?: ReadonlyArray, options?: ForkOptions): ChildProcess; + + interface SpawnSyncOptions extends CommonSpawnOptions { + input?: string | NodeJS.ArrayBufferView; + killSignal?: NodeJS.Signals | number; + maxBuffer?: number; + encoding?: BufferEncoding | 'buffer' | null; + } + interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { + encoding: BufferEncoding; + } + interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { + encoding?: 'buffer' | null; + } + interface SpawnSyncReturns { + pid: number; + output: string[]; + stdout: T; + stderr: T; + status: number | null; + signal: NodeJS.Signals | null; + error?: Error; + } + function spawnSync(command: string): SpawnSyncReturns; + function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; + function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; + function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; + function spawnSync(command: string, args?: ReadonlyArray, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; + function spawnSync(command: string, args?: ReadonlyArray, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; + function spawnSync(command: string, args?: ReadonlyArray, options?: SpawnSyncOptions): SpawnSyncReturns; + + interface ExecSyncOptions extends CommonOptions { + input?: string | Uint8Array; + stdio?: StdioOptions; + shell?: string; + killSignal?: NodeJS.Signals | number; + maxBuffer?: number; + encoding?: BufferEncoding | 'buffer' | null; + } + interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { + encoding: BufferEncoding; + } + interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { + encoding?: 'buffer' | null; + } + function execSync(command: string): Buffer; + function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; + function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; + function execSync(command: string, options?: ExecSyncOptions): Buffer; + + interface ExecFileSyncOptions extends CommonOptions { + input?: string | NodeJS.ArrayBufferView; + stdio?: StdioOptions; + killSignal?: NodeJS.Signals | number; + maxBuffer?: number; + encoding?: BufferEncoding; + shell?: boolean | string; + } + interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { + encoding: BufferEncoding; + } + interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { + encoding: BufferEncoding; // specify `null`. + } + function execFileSync(command: string): Buffer; + function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; + function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; + function execFileSync(command: string, args?: ReadonlyArray, options?: ExecFileSyncOptionsWithStringEncoding): string; + function execFileSync(command: string, args?: ReadonlyArray, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + function execFileSync(command: string, args?: ReadonlyArray, options?: ExecFileSyncOptions): Buffer; +} diff --git a/node_modules/@types/node/cluster.d.ts b/node_modules/@types/node/cluster.d.ts new file mode 100755 index 0000000..c09ccd6 --- /dev/null +++ b/node_modules/@types/node/cluster.d.ts @@ -0,0 +1,266 @@ +declare module 'node:cluster' { + export * from 'cluster'; +} + +declare module 'cluster' { + import * as child from 'node:child_process'; + import EventEmitter = require('node:events'); + import * as net from 'node:net'; + + // interfaces + interface ClusterSettings { + execArgv?: string[]; // default: process.execArgv + exec?: string; + args?: string[]; + silent?: boolean; + stdio?: any[]; + uid?: number; + gid?: number; + inspectPort?: number | (() => number); + } + + interface Address { + address: string; + port: number; + addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6" + } + + class Worker extends EventEmitter { + id: number; + process: child.ChildProcess; + send(message: child.Serializable, sendHandle?: child.SendHandle, callback?: (error: Error | null) => void): boolean; + kill(signal?: string): void; + destroy(signal?: string): void; + disconnect(): void; + isConnected(): boolean; + isDead(): boolean; + exitedAfterDisconnect: boolean; + + /** + * events.EventEmitter + * 1. disconnect + * 2. error + * 3. exit + * 4. listening + * 5. message + * 6. online + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "disconnect", listener: () => void): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "exit", listener: (code: number, signal: string) => void): this; + addListener(event: "listening", listener: (address: Address) => void): this; + addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + addListener(event: "online", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "disconnect"): boolean; + emit(event: "error", error: Error): boolean; + emit(event: "exit", code: number, signal: string): boolean; + emit(event: "listening", address: Address): boolean; + emit(event: "message", message: any, handle: net.Socket | net.Server): boolean; + emit(event: "online"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "disconnect", listener: () => void): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "exit", listener: (code: number, signal: string) => void): this; + on(event: "listening", listener: (address: Address) => void): this; + on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + on(event: "online", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "disconnect", listener: () => void): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "exit", listener: (code: number, signal: string) => void): this; + once(event: "listening", listener: (address: Address) => void): this; + once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + once(event: "online", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "disconnect", listener: () => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependListener(event: "listening", listener: (address: Address) => void): this; + prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependListener(event: "online", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "disconnect", listener: () => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependOnceListener(event: "listening", listener: (address: Address) => void): this; + prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependOnceListener(event: "online", listener: () => void): this; + } + + interface Cluster extends EventEmitter { + Worker: Worker; + disconnect(callback?: () => void): void; + fork(env?: any): Worker; + isMaster: boolean; + isWorker: boolean; + schedulingPolicy: number; + settings: ClusterSettings; + setupMaster(settings?: ClusterSettings): void; + worker?: Worker; + workers?: NodeJS.Dict; + + readonly SCHED_NONE: number; + readonly SCHED_RR: number; + + /** + * events.EventEmitter + * 1. disconnect + * 2. exit + * 3. fork + * 4. listening + * 5. message + * 6. online + * 7. setup + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "disconnect", listener: (worker: Worker) => void): this; + addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + addListener(event: "fork", listener: (worker: Worker) => void): this; + addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + addListener(event: "online", listener: (worker: Worker) => void): this; + addListener(event: "setup", listener: (settings: ClusterSettings) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "disconnect", worker: Worker): boolean; + emit(event: "exit", worker: Worker, code: number, signal: string): boolean; + emit(event: "fork", worker: Worker): boolean; + emit(event: "listening", worker: Worker, address: Address): boolean; + emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean; + emit(event: "online", worker: Worker): boolean; + emit(event: "setup", settings: ClusterSettings): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "disconnect", listener: (worker: Worker) => void): this; + on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + on(event: "fork", listener: (worker: Worker) => void): this; + on(event: "listening", listener: (worker: Worker, address: Address) => void): this; + on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + on(event: "online", listener: (worker: Worker) => void): this; + on(event: "setup", listener: (settings: ClusterSettings) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "disconnect", listener: (worker: Worker) => void): this; + once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + once(event: "fork", listener: (worker: Worker) => void): this; + once(event: "listening", listener: (worker: Worker, address: Address) => void): this; + once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + once(event: "online", listener: (worker: Worker) => void): this; + once(event: "setup", listener: (settings: ClusterSettings) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "disconnect", listener: (worker: Worker) => void): this; + prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + prependListener(event: "fork", listener: (worker: Worker) => void): this; + prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependListener(event: "online", listener: (worker: Worker) => void): this; + prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this; + prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + prependOnceListener(event: "fork", listener: (worker: Worker) => void): this; + prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + // the handle is a net.Socket or net.Server object, or undefined. + prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; + prependOnceListener(event: "online", listener: (worker: Worker) => void): this; + prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): this; + } + + const SCHED_NONE: number; + const SCHED_RR: number; + + function disconnect(callback?: () => void): void; + function fork(env?: any): Worker; + const isMaster: boolean; + const isWorker: boolean; + let schedulingPolicy: number; + const settings: ClusterSettings; + function setupMaster(settings?: ClusterSettings): void; + const worker: Worker; + const workers: NodeJS.Dict; + + /** + * events.EventEmitter + * 1. disconnect + * 2. exit + * 3. fork + * 4. listening + * 5. message + * 6. online + * 7. setup + */ + function addListener(event: string, listener: (...args: any[]) => void): Cluster; + function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + function addListener(event: "fork", listener: (worker: Worker) => void): Cluster; + function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + // the handle is a net.Socket or net.Server object, or undefined. + function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; + function addListener(event: "online", listener: (worker: Worker) => void): Cluster; + function addListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster; + + function emit(event: string | symbol, ...args: any[]): boolean; + function emit(event: "disconnect", worker: Worker): boolean; + function emit(event: "exit", worker: Worker, code: number, signal: string): boolean; + function emit(event: "fork", worker: Worker): boolean; + function emit(event: "listening", worker: Worker, address: Address): boolean; + function emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean; + function emit(event: "online", worker: Worker): boolean; + function emit(event: "setup", settings: ClusterSettings): boolean; + + function on(event: string, listener: (...args: any[]) => void): Cluster; + function on(event: "disconnect", listener: (worker: Worker) => void): Cluster; + function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + function on(event: "fork", listener: (worker: Worker) => void): Cluster; + function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + function on(event: "online", listener: (worker: Worker) => void): Cluster; + function on(event: "setup", listener: (settings: ClusterSettings) => void): Cluster; + + function once(event: string, listener: (...args: any[]) => void): Cluster; + function once(event: "disconnect", listener: (worker: Worker) => void): Cluster; + function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + function once(event: "fork", listener: (worker: Worker) => void): Cluster; + function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + function once(event: "online", listener: (worker: Worker) => void): Cluster; + function once(event: "setup", listener: (settings: ClusterSettings) => void): Cluster; + + function removeListener(event: string, listener: (...args: any[]) => void): Cluster; + function removeAllListeners(event?: string): Cluster; + function setMaxListeners(n: number): Cluster; + function getMaxListeners(): number; + function listeners(event: string): Function[]; + function listenerCount(type: string): number; + + function prependListener(event: string, listener: (...args: any[]) => void): Cluster; + function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster; + function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + // the handle is a net.Socket or net.Server object, or undefined. + function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; + function prependListener(event: "online", listener: (worker: Worker) => void): Cluster; + function prependListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster; + + function prependOnceListener(event: string, listener: (...args: any[]) => void): Cluster; + function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster; + function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + // the handle is a net.Socket or net.Server object, or undefined. + function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; + function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster; + function prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster; + + function eventNames(): string[]; +} diff --git a/node_modules/@types/node/console.d.ts b/node_modules/@types/node/console.d.ts new file mode 100755 index 0000000..2851e99 --- /dev/null +++ b/node_modules/@types/node/console.d.ts @@ -0,0 +1,137 @@ +declare module 'node:console' { + export = console; +} + +declare module 'console' { + import { InspectOptions } from 'node:util'; + + global { + // This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build + interface Console { + Console: NodeJS.ConsoleConstructor; + /** + * A simple assertion test that verifies whether `value` is truthy. + * If it is not, an `AssertionError` is thrown. + * If provided, the error `message` is formatted using `util.format()` and used as the error message. + */ + assert(value: any, message?: string, ...optionalParams: any[]): void; + /** + * When `stdout` is a TTY, calling `console.clear()` will attempt to clear the TTY. + * When `stdout` is not a TTY, this method does nothing. + */ + clear(): void; + /** + * Maintains an internal counter specific to `label` and outputs to `stdout` the number of times `console.count()` has been called with the given `label`. + */ + count(label?: string): void; + /** + * Resets the internal counter specific to `label`. + */ + countReset(label?: string): void; + /** + * The `console.debug()` function is an alias for {@link console.log()}. + */ + debug(message?: any, ...optionalParams: any[]): void; + /** + * Uses {@link util.inspect()} on `obj` and prints the resulting string to `stdout`. + * This function bypasses any custom `inspect()` function defined on `obj`. + */ + dir(obj: any, options?: InspectOptions): void; + /** + * This method calls {@link console.log()} passing it the arguments received. Please note that this method does not produce any XML formatting + */ + dirxml(...data: any[]): void; + /** + * Prints to `stderr` with newline. + */ + error(message?: any, ...optionalParams: any[]): void; + /** + * Increases indentation of subsequent lines by two spaces. + * If one or more `label`s are provided, those are printed first without the additional indentation. + */ + group(...label: any[]): void; + /** + * The `console.groupCollapsed()` function is an alias for {@link console.group()}. + */ + groupCollapsed(...label: any[]): void; + /** + * Decreases indentation of subsequent lines by two spaces. + */ + groupEnd(): void; + /** + * The {@link console.info()} function is an alias for {@link console.log()}. + */ + info(message?: any, ...optionalParams: any[]): void; + /** + * Prints to `stdout` with newline. + */ + log(message?: any, ...optionalParams: any[]): void; + /** + * This method does not display anything unless used in the inspector. + * Prints to `stdout` the array `array` formatted as a table. + */ + table(tabularData: any, properties?: ReadonlyArray): void; + /** + * Starts a timer that can be used to compute the duration of an operation. Timers are identified by a unique `label`. + */ + time(label?: string): void; + /** + * Stops a timer that was previously started by calling {@link console.time()} and prints the result to `stdout`. + */ + timeEnd(label?: string): void; + /** + * For a timer that was previously started by calling {@link console.time()}, prints the elapsed time and other `data` arguments to `stdout`. + */ + timeLog(label?: string, ...data: any[]): void; + /** + * Prints to `stderr` the string 'Trace :', followed by the {@link util.format()} formatted message and stack trace to the current position in the code. + */ + trace(message?: any, ...optionalParams: any[]): void; + /** + * The {@link console.warn()} function is an alias for {@link console.error()}. + */ + warn(message?: any, ...optionalParams: any[]): void; + + // --- Inspector mode only --- + /** + * This method does not display anything unless used in the inspector. + * Starts a JavaScript CPU profile with an optional label. + */ + profile(label?: string): void; + /** + * This method does not display anything unless used in the inspector. + * Stops the current JavaScript CPU profiling session if one has been started and prints the report to the Profiles panel of the inspector. + */ + profileEnd(label?: string): void; + /** + * This method does not display anything unless used in the inspector. + * Adds an event with the label `label` to the Timeline panel of the inspector. + */ + timeStamp(label?: string): void; + } + + var console: Console; + + namespace NodeJS { + interface ConsoleConstructorOptions { + stdout: WritableStream; + stderr?: WritableStream; + ignoreErrors?: boolean; + colorMode?: boolean | 'auto'; + inspectOptions?: InspectOptions; + } + + interface ConsoleConstructor { + prototype: Console; + new(stdout: WritableStream, stderr?: WritableStream, ignoreErrors?: boolean): Console; + new(options: ConsoleConstructorOptions): Console; + } + + interface Global { + console: typeof console; + } + } + } + + export = console; +} diff --git a/node_modules/@types/node/constants.d.ts b/node_modules/@types/node/constants.d.ts new file mode 100755 index 0000000..5d0b7a7 --- /dev/null +++ b/node_modules/@types/node/constants.d.ts @@ -0,0 +1,19 @@ +/** @deprecated since v6.3.0 - use constants property exposed by the relevant module instead. */ +declare module 'node:constants' { + import exp = require('constants'); + export = exp; +} + +/** @deprecated since v6.3.0 - use constants property exposed by the relevant module instead. */ +declare module 'constants' { + import { constants as osConstants, SignalConstants } from 'node:os'; + import { constants as cryptoConstants } from 'node:crypto'; + import { constants as fsConstants } from 'node:fs'; + + const exp: typeof osConstants.errno & + typeof osConstants.priority & + SignalConstants & + typeof cryptoConstants & + typeof fsConstants; + export = exp; +} diff --git a/node_modules/@types/node/crypto.d.ts b/node_modules/@types/node/crypto.d.ts new file mode 100755 index 0000000..a6887ab --- /dev/null +++ b/node_modules/@types/node/crypto.d.ts @@ -0,0 +1,1274 @@ +declare module 'node:crypto' { + export * from 'crypto'; +} + +declare module 'crypto' { + import * as stream from 'node:stream'; + + interface Certificate { + /** + * @deprecated + * @param spkac + * @returns The challenge component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportChallenge(spkac: BinaryLike): Buffer; + /** + * @deprecated + * @param spkac + * @param encoding The encoding of the spkac string. + * @returns The public key component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer; + /** + * @deprecated + * @param spkac + * @returns `true` if the given `spkac` data structure is valid, + * `false` otherwise. + */ + verifySpkac(spkac: NodeJS.ArrayBufferView): boolean; + } + const Certificate: Certificate & { + /** @deprecated since v14.9.0 - Use static methods of `crypto.Certificate` instead. */ + new(): Certificate; + /** @deprecated since v14.9.0 - Use static methods of `crypto.Certificate` instead. */ + (): Certificate; + + /** + * @param spkac + * @returns The challenge component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportChallenge(spkac: BinaryLike): Buffer; + /** + * @param spkac + * @param encoding The encoding of the spkac string. + * @returns The public key component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer; + /** + * @param spkac + * @returns `true` if the given `spkac` data structure is valid, + * `false` otherwise. + */ + verifySpkac(spkac: NodeJS.ArrayBufferView): boolean; + }; + + namespace constants { + // https://nodejs.org/dist/latest-v10.x/docs/api/crypto.html#crypto_crypto_constants + const OPENSSL_VERSION_NUMBER: number; + + /** Applies multiple bug workarounds within OpenSSL. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html for detail. */ + const SSL_OP_ALL: number; + /** Allows legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; + /** Attempts to use the server's preferences instead of the client's when selecting a cipher. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + const SSL_OP_CIPHER_SERVER_PREFERENCE: number; + /** Instructs OpenSSL to use Cisco's "speshul" version of DTLS_BAD_VER. */ + const SSL_OP_CISCO_ANYCONNECT: number; + /** Instructs OpenSSL to turn on cookie exchange. */ + const SSL_OP_COOKIE_EXCHANGE: number; + /** Instructs OpenSSL to add server-hello extension from an early version of the cryptopro draft. */ + const SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; + /** Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d. */ + const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; + /** Instructs OpenSSL to always use the tmp_rsa key when performing RSA operations. */ + const SSL_OP_EPHEMERAL_RSA: number; + /** Allows initial connection to servers that do not support RI. */ + const SSL_OP_LEGACY_SERVER_CONNECT: number; + const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; + const SSL_OP_MICROSOFT_SESS_ID_BUG: number; + /** Instructs OpenSSL to disable the workaround for a man-in-the-middle protocol-version vulnerability in the SSL 2.0 server implementation. */ + const SSL_OP_MSIE_SSLV2_RSA_PADDING: number; + const SSL_OP_NETSCAPE_CA_DN_BUG: number; + const SSL_OP_NETSCAPE_CHALLENGE_BUG: number; + const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; + const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; + /** Instructs OpenSSL to disable support for SSL/TLS compression. */ + const SSL_OP_NO_COMPRESSION: number; + const SSL_OP_NO_QUERY_MTU: number; + /** Instructs OpenSSL to always start a new session when performing renegotiation. */ + const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; + const SSL_OP_NO_SSLv2: number; + const SSL_OP_NO_SSLv3: number; + const SSL_OP_NO_TICKET: number; + const SSL_OP_NO_TLSv1: number; + const SSL_OP_NO_TLSv1_1: number; + const SSL_OP_NO_TLSv1_2: number; + const SSL_OP_PKCS1_CHECK_1: number; + const SSL_OP_PKCS1_CHECK_2: number; + /** Instructs OpenSSL to always create a new key when using temporary/ephemeral DH parameters. */ + const SSL_OP_SINGLE_DH_USE: number; + /** Instructs OpenSSL to always create a new key when using temporary/ephemeral ECDH parameters. */ + const SSL_OP_SINGLE_ECDH_USE: number; + const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; + const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; + const SSL_OP_TLS_BLOCK_PADDING_BUG: number; + const SSL_OP_TLS_D5_BUG: number; + /** Instructs OpenSSL to disable version rollback attack detection. */ + const SSL_OP_TLS_ROLLBACK_BUG: number; + + const ENGINE_METHOD_RSA: number; + const ENGINE_METHOD_DSA: number; + const ENGINE_METHOD_DH: number; + const ENGINE_METHOD_RAND: number; + const ENGINE_METHOD_EC: number; + const ENGINE_METHOD_CIPHERS: number; + const ENGINE_METHOD_DIGESTS: number; + const ENGINE_METHOD_PKEY_METHS: number; + const ENGINE_METHOD_PKEY_ASN1_METHS: number; + const ENGINE_METHOD_ALL: number; + const ENGINE_METHOD_NONE: number; + + const DH_CHECK_P_NOT_SAFE_PRIME: number; + const DH_CHECK_P_NOT_PRIME: number; + const DH_UNABLE_TO_CHECK_GENERATOR: number; + const DH_NOT_SUITABLE_GENERATOR: number; + + const ALPN_ENABLED: number; + + const RSA_PKCS1_PADDING: number; + const RSA_SSLV23_PADDING: number; + const RSA_NO_PADDING: number; + const RSA_PKCS1_OAEP_PADDING: number; + const RSA_X931_PADDING: number; + const RSA_PKCS1_PSS_PADDING: number; + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the digest size when signing or verifying. */ + const RSA_PSS_SALTLEN_DIGEST: number; + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the maximum permissible value when signing data. */ + const RSA_PSS_SALTLEN_MAX_SIGN: number; + /** Causes the salt length for RSA_PKCS1_PSS_PADDING to be determined automatically when verifying a signature. */ + const RSA_PSS_SALTLEN_AUTO: number; + + const POINT_CONVERSION_COMPRESSED: number; + const POINT_CONVERSION_UNCOMPRESSED: number; + const POINT_CONVERSION_HYBRID: number; + + /** Specifies the built-in default cipher list used by Node.js (colon-separated values). */ + const defaultCoreCipherList: string; + /** Specifies the active default cipher list used by the current Node.js process (colon-separated values). */ + const defaultCipherList: string; + } + + interface HashOptions extends stream.TransformOptions { + /** + * For XOF hash functions such as `shake256`, the + * outputLength option can be used to specify the desired output length in bytes. + */ + outputLength?: number; + } + + /** @deprecated since v10.0.0 */ + const fips: boolean; + + function createHash(algorithm: string, options?: HashOptions): Hash; + function createHmac(algorithm: string, key: BinaryLike | KeyObject, options?: stream.TransformOptions): Hmac; + + // https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings + type BinaryToTextEncoding = 'base64' | 'hex'; + type CharacterEncoding = 'utf8' | 'utf-8' | 'utf16le' | 'latin1'; + type LegacyCharacterEncoding = 'ascii' | 'binary' | 'ucs2' | 'ucs-2'; + + type Encoding = BinaryToTextEncoding | CharacterEncoding | LegacyCharacterEncoding; + + type ECDHKeyFormat = 'compressed' | 'uncompressed' | 'hybrid'; + + class Hash extends stream.Transform { + private constructor(); + copy(): Hash; + update(data: BinaryLike): Hash; + update(data: string, input_encoding: Encoding): Hash; + digest(): Buffer; + digest(encoding: BinaryToTextEncoding): string; + } + class Hmac extends stream.Transform { + private constructor(); + update(data: BinaryLike): Hmac; + update(data: string, input_encoding: Encoding): Hmac; + digest(): Buffer; + digest(encoding: BinaryToTextEncoding): string; + } + + type KeyObjectType = 'secret' | 'public' | 'private'; + + interface KeyExportOptions { + type: 'pkcs1' | 'spki' | 'pkcs8' | 'sec1'; + format: T; + cipher?: string; + passphrase?: string | Buffer; + } + + class KeyObject { + private constructor(); + asymmetricKeyType?: KeyType; + /** + * For asymmetric keys, this property represents the size of the embedded key in + * bytes. This property is `undefined` for symmetric keys. + */ + asymmetricKeySize?: number; + export(options: KeyExportOptions<'pem'>): string | Buffer; + export(options?: KeyExportOptions<'der'>): Buffer; + symmetricKeySize?: number; + type: KeyObjectType; + } + + type CipherCCMTypes = 'aes-128-ccm' | 'aes-192-ccm' | 'aes-256-ccm' | 'chacha20-poly1305'; + type CipherGCMTypes = 'aes-128-gcm' | 'aes-192-gcm' | 'aes-256-gcm'; + + type BinaryLike = string | NodeJS.ArrayBufferView; + + type CipherKey = BinaryLike | KeyObject; + + interface CipherCCMOptions extends stream.TransformOptions { + authTagLength: number; + } + interface CipherGCMOptions extends stream.TransformOptions { + authTagLength?: number; + } + /** @deprecated since v10.0.0 use `createCipheriv()` */ + function createCipher(algorithm: CipherCCMTypes, password: BinaryLike, options: CipherCCMOptions): CipherCCM; + /** @deprecated since v10.0.0 use `createCipheriv()` */ + function createCipher(algorithm: CipherGCMTypes, password: BinaryLike, options?: CipherGCMOptions): CipherGCM; + /** @deprecated since v10.0.0 use `createCipheriv()` */ + function createCipher(algorithm: string, password: BinaryLike, options?: stream.TransformOptions): Cipher; + + function createCipheriv( + algorithm: CipherCCMTypes, + key: CipherKey, + iv: BinaryLike | null, + options: CipherCCMOptions, + ): CipherCCM; + function createCipheriv( + algorithm: CipherGCMTypes, + key: CipherKey, + iv: BinaryLike | null, + options?: CipherGCMOptions, + ): CipherGCM; + function createCipheriv( + algorithm: string, + key: CipherKey, + iv: BinaryLike | null, + options?: stream.TransformOptions, + ): Cipher; + + class Cipher extends stream.Transform { + private constructor(); + update(data: BinaryLike): Buffer; + update(data: string, input_encoding: Encoding): Buffer; + update(data: NodeJS.ArrayBufferView, input_encoding: undefined, output_encoding: Encoding): string; + update(data: string, input_encoding: Encoding | undefined, output_encoding: Encoding): string; + final(): Buffer; + final(output_encoding: BufferEncoding): string; + setAutoPadding(auto_padding?: boolean): this; + // getAuthTag(): Buffer; + // setAAD(buffer: NodeJS.ArrayBufferView): this; + } + interface CipherCCM extends Cipher { + setAAD(buffer: NodeJS.ArrayBufferView, options: { plaintextLength: number }): this; + getAuthTag(): Buffer; + } + interface CipherGCM extends Cipher { + setAAD(buffer: NodeJS.ArrayBufferView, options?: { plaintextLength: number }): this; + getAuthTag(): Buffer; + } + /** @deprecated since v10.0.0 use `createDecipheriv()` */ + function createDecipher(algorithm: CipherCCMTypes, password: BinaryLike, options: CipherCCMOptions): DecipherCCM; + /** @deprecated since v10.0.0 use `createDecipheriv()` */ + function createDecipher(algorithm: CipherGCMTypes, password: BinaryLike, options?: CipherGCMOptions): DecipherGCM; + /** @deprecated since v10.0.0 use `createDecipheriv()` */ + function createDecipher(algorithm: string, password: BinaryLike, options?: stream.TransformOptions): Decipher; + + function createDecipheriv( + algorithm: CipherCCMTypes, + key: CipherKey, + iv: BinaryLike | null, + options: CipherCCMOptions, + ): DecipherCCM; + function createDecipheriv( + algorithm: CipherGCMTypes, + key: CipherKey, + iv: BinaryLike | null, + options?: CipherGCMOptions, + ): DecipherGCM; + function createDecipheriv( + algorithm: string, + key: CipherKey, + iv: BinaryLike | null, + options?: stream.TransformOptions, + ): Decipher; + + class Decipher extends stream.Transform { + private constructor(); + update(data: NodeJS.ArrayBufferView): Buffer; + update(data: string, input_encoding: Encoding): Buffer; + update(data: NodeJS.ArrayBufferView, input_encoding: undefined, output_encoding: Encoding): string; + update(data: string, input_encoding: Encoding | undefined, output_encoding: Encoding): string; + final(): Buffer; + final(output_encoding: BufferEncoding): string; + setAutoPadding(auto_padding?: boolean): this; + // setAuthTag(tag: NodeJS.ArrayBufferView): this; + // setAAD(buffer: NodeJS.ArrayBufferView): this; + } + interface DecipherCCM extends Decipher { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD(buffer: NodeJS.ArrayBufferView, options: { plaintextLength: number }): this; + } + interface DecipherGCM extends Decipher { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD(buffer: NodeJS.ArrayBufferView, options?: { plaintextLength: number }): this; + } + + interface PrivateKeyInput { + key: string | Buffer; + format?: KeyFormat; + type?: 'pkcs1' | 'pkcs8' | 'sec1'; + passphrase?: string | Buffer; + } + + interface PublicKeyInput { + key: string | Buffer; + format?: KeyFormat; + type?: 'pkcs1' | 'spki'; + } + + function createPrivateKey(key: PrivateKeyInput | string | Buffer): KeyObject; + function createPublicKey(key: PublicKeyInput | string | Buffer | KeyObject): KeyObject; + function createSecretKey(key: NodeJS.ArrayBufferView): KeyObject; + + function createSign(algorithm: string, options?: stream.WritableOptions): Signer; + + type DSAEncoding = 'der' | 'ieee-p1363'; + + interface SigningOptions { + /** + * @See crypto.constants.RSA_PKCS1_PADDING + */ + padding?: number; + saltLength?: number; + dsaEncoding?: DSAEncoding; + } + + interface SignPrivateKeyInput extends PrivateKeyInput, SigningOptions { } + interface SignKeyObjectInput extends SigningOptions { + key: KeyObject; + } + interface VerifyPublicKeyInput extends PublicKeyInput, SigningOptions { } + interface VerifyKeyObjectInput extends SigningOptions { + key: KeyObject; + } + + type KeyLike = string | Buffer | KeyObject; + + class Signer extends stream.Writable { + private constructor(); + + update(data: BinaryLike): Signer; + update(data: string, input_encoding: Encoding): Signer; + sign(private_key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput): Buffer; + sign( + private_key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput, + output_format: BinaryToTextEncoding, + ): string; + } + + function createVerify(algorithm: string, options?: stream.WritableOptions): Verify; + class Verify extends stream.Writable { + private constructor(); + + update(data: BinaryLike): Verify; + update(data: string, input_encoding: Encoding): Verify; + verify( + object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, + signature: NodeJS.ArrayBufferView, + ): boolean; + verify( + object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, + signature: string, + signature_format?: BinaryToTextEncoding, + ): boolean; + // https://nodejs.org/api/crypto.html#crypto_verifier_verify_object_signature_signature_format + // The signature field accepts a TypedArray type, but it is only available starting ES2017 + } + function createDiffieHellman(prime_length: number, generator?: number | NodeJS.ArrayBufferView): DiffieHellman; + function createDiffieHellman(prime: NodeJS.ArrayBufferView): DiffieHellman; + function createDiffieHellman(prime: string, prime_encoding: BinaryToTextEncoding): DiffieHellman; + function createDiffieHellman( + prime: string, + prime_encoding: BinaryToTextEncoding, + generator: number | NodeJS.ArrayBufferView, + ): DiffieHellman; + function createDiffieHellman( + prime: string, + prime_encoding: BinaryToTextEncoding, + generator: string, + generator_encoding: BinaryToTextEncoding, + ): DiffieHellman; + class DiffieHellman { + private constructor(); + generateKeys(): Buffer; + generateKeys(encoding: BinaryToTextEncoding): string; + computeSecret(other_public_key: NodeJS.ArrayBufferView): Buffer; + computeSecret(other_public_key: string, input_encoding: BinaryToTextEncoding): Buffer; + computeSecret(other_public_key: NodeJS.ArrayBufferView, output_encoding: BinaryToTextEncoding): string; + computeSecret( + other_public_key: string, + input_encoding: BinaryToTextEncoding, + output_encoding: BinaryToTextEncoding, + ): string; + getPrime(): Buffer; + getPrime(encoding: BinaryToTextEncoding): string; + getGenerator(): Buffer; + getGenerator(encoding: BinaryToTextEncoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: BinaryToTextEncoding): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: BinaryToTextEncoding): string; + setPublicKey(public_key: NodeJS.ArrayBufferView): void; + setPublicKey(public_key: string, encoding: BufferEncoding): void; + setPrivateKey(private_key: NodeJS.ArrayBufferView): void; + setPrivateKey(private_key: string, encoding: BufferEncoding): void; + verifyError: number; + } + function getDiffieHellman(group_name: string): DiffieHellman; + function pbkdf2( + password: BinaryLike, + salt: BinaryLike, + iterations: number, + keylen: number, + digest: string, + callback: (err: Error | null, derivedKey: Buffer) => any, + ): void; + function pbkdf2Sync( + password: BinaryLike, + salt: BinaryLike, + iterations: number, + keylen: number, + digest: string, + ): Buffer; + + function randomBytes(size: number): Buffer; + function randomBytes(size: number, callback: (err: Error | null, buf: Buffer) => void): void; + function pseudoRandomBytes(size: number): Buffer; + function pseudoRandomBytes(size: number, callback: (err: Error | null, buf: Buffer) => void): void; + + function randomInt(max: number): number; + function randomInt(min: number, max: number): number; + function randomInt(max: number, callback: (err: Error | null, value: number) => void): void; + function randomInt(min: number, max: number, callback: (err: Error | null, value: number) => void): void; + + function randomFillSync(buffer: T, offset?: number, size?: number): T; + function randomFill( + buffer: T, + callback: (err: Error | null, buf: T) => void, + ): void; + function randomFill( + buffer: T, + offset: number, + callback: (err: Error | null, buf: T) => void, + ): void; + function randomFill( + buffer: T, + offset: number, + size: number, + callback: (err: Error | null, buf: T) => void, + ): void; + + interface ScryptOptions { + cost?: number; + blockSize?: number; + parallelization?: number; + N?: number; + r?: number; + p?: number; + maxmem?: number; + } + function scrypt( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + callback: (err: Error | null, derivedKey: Buffer) => void, + ): void; + function scrypt( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + options: ScryptOptions, + callback: (err: Error | null, derivedKey: Buffer) => void, + ): void; + function scryptSync(password: BinaryLike, salt: BinaryLike, keylen: number, options?: ScryptOptions): Buffer; + + interface RsaPublicKey { + key: KeyLike; + padding?: number; + } + interface RsaPrivateKey { + key: KeyLike; + passphrase?: string; + /** + * @default 'sha1' + */ + oaepHash?: string; + oaepLabel?: NodeJS.TypedArray; + padding?: number; + } + function publicEncrypt(key: RsaPublicKey | RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function publicDecrypt(key: RsaPublicKey | RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function privateDecrypt(private_key: RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function privateEncrypt(private_key: RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function getCiphers(): string[]; + function getCurves(): string[]; + function getFips(): 1 | 0; + function getHashes(): string[]; + class ECDH { + private constructor(); + static convertKey( + key: BinaryLike, + curve: string, + inputEncoding?: BinaryToTextEncoding, + outputEncoding?: 'latin1' | 'hex' | 'base64', + format?: 'uncompressed' | 'compressed' | 'hybrid', + ): Buffer | string; + generateKeys(): Buffer; + generateKeys(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; + computeSecret(other_public_key: NodeJS.ArrayBufferView): Buffer; + computeSecret(other_public_key: string, input_encoding: BinaryToTextEncoding): Buffer; + computeSecret(other_public_key: NodeJS.ArrayBufferView, output_encoding: BinaryToTextEncoding): string; + computeSecret( + other_public_key: string, + input_encoding: BinaryToTextEncoding, + output_encoding: BinaryToTextEncoding, + ): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: BinaryToTextEncoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; + setPrivateKey(private_key: NodeJS.ArrayBufferView): void; + setPrivateKey(private_key: string, encoding: BinaryToTextEncoding): void; + } + function createECDH(curve_name: string): ECDH; + function timingSafeEqual(a: NodeJS.ArrayBufferView, b: NodeJS.ArrayBufferView): boolean; + /** @deprecated since v10.0.0 */ + const DEFAULT_ENCODING: BufferEncoding; + + type KeyType = 'rsa' | 'dsa' | 'ec' | 'ed25519' | 'ed448' | 'x25519' | 'x448'; + type KeyFormat = 'pem' | 'der'; + + interface BasePrivateKeyEncodingOptions { + format: T; + cipher?: string; + passphrase?: string; + } + + interface KeyPairKeyObjectResult { + publicKey: KeyObject; + privateKey: KeyObject; + } + + interface ED25519KeyPairKeyObjectOptions { + /** + * No options. + */ + } + + interface ED448KeyPairKeyObjectOptions { + /** + * No options. + */ + } + + interface X25519KeyPairKeyObjectOptions { + /** + * No options. + */ + } + + interface X448KeyPairKeyObjectOptions { + /** + * No options. + */ + } + + interface ECKeyPairKeyObjectOptions { + /** + * Name of the curve to use. + */ + namedCurve: string; + } + + interface RSAKeyPairKeyObjectOptions { + /** + * Key size in bits + */ + modulusLength: number; + + /** + * @default 0x10001 + */ + publicExponent?: number; + } + + interface DSAKeyPairKeyObjectOptions { + /** + * Key size in bits + */ + modulusLength: number; + + /** + * Size of q in bits + */ + divisorLength: number; + } + + interface RSAKeyPairOptions { + /** + * Key size in bits + */ + modulusLength: number; + /** + * @default 0x10001 + */ + publicExponent?: number; + + publicKeyEncoding: { + type: 'pkcs1' | 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs1' | 'pkcs8'; + }; + } + + interface DSAKeyPairOptions { + /** + * Key size in bits + */ + modulusLength: number; + /** + * Size of q in bits + */ + divisorLength: number; + + publicKeyEncoding: { + type: 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs8'; + }; + } + + interface ECKeyPairOptions { + /** + * Name of the curve to use. + */ + namedCurve: string; + + publicKeyEncoding: { + type: 'pkcs1' | 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'sec1' | 'pkcs8'; + }; + } + + interface ED25519KeyPairOptions { + publicKeyEncoding: { + type: 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs8'; + }; + } + + interface ED448KeyPairOptions { + publicKeyEncoding: { + type: 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs8'; + }; + } + + interface X25519KeyPairOptions { + publicKeyEncoding: { + type: 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs8'; + }; + } + + interface X448KeyPairOptions { + publicKeyEncoding: { + type: 'spki'; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: 'pkcs8'; + }; + } + + interface KeyPairSyncResult { + publicKey: T1; + privateKey: T2; + } + + function generateKeyPairSync( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'rsa', options: RSAKeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'dsa', options: DSAKeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'ec', + options: ECKeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ec', + options: ECKeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ec', + options: ECKeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ec', + options: ECKeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'ec', options: ECKeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'ed25519', options?: ED25519KeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'ed448', options?: ED448KeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'x25519', options?: X25519KeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPairSync( + type: 'x448', + options: X448KeyPairOptions<'pem', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x448', + options: X448KeyPairOptions<'pem', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x448', + options: X448KeyPairOptions<'der', 'pem'>, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: 'x448', + options: X448KeyPairOptions<'der', 'der'>, + ): KeyPairSyncResult; + function generateKeyPairSync(type: 'x448', options?: X448KeyPairKeyObjectOptions): KeyPairKeyObjectResult; + + function generateKeyPair( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'rsa', + options: RSAKeyPairKeyObjectOptions, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'dsa', + options: DSAKeyPairKeyObjectOptions, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'ec', + options: ECKeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ec', + options: ECKeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ec', + options: ECKeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ec', + options: ECKeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ec', + options: ECKeyPairKeyObjectOptions, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ed25519', + options: ED25519KeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'ed448', + options: ED448KeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'x25519', + options: X25519KeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + function generateKeyPair( + type: 'x448', + options: X448KeyPairOptions<'pem', 'pem'>, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'x448', + options: X448KeyPairOptions<'pem', 'der'>, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'x448', + options: X448KeyPairOptions<'der', 'pem'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: 'x448', + options: X448KeyPairOptions<'der', 'der'>, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: 'x448', + options: X448KeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + + namespace generateKeyPair { + function __promisify__( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'rsa', + options: RSAKeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'rsa', + options: RSAKeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__(type: 'rsa', options: RSAKeyPairKeyObjectOptions): Promise; + + function __promisify__( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'dsa', + options: DSAKeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'dsa', + options: DSAKeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__(type: 'dsa', options: DSAKeyPairKeyObjectOptions): Promise; + + function __promisify__( + type: 'ec', + options: ECKeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'ec', + options: ECKeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'ec', + options: ECKeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'ec', + options: ECKeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__(type: 'ec', options: ECKeyPairKeyObjectOptions): Promise; + + function __promisify__( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'ed25519', + options: ED25519KeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'ed25519', + options: ED25519KeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__( + type: 'ed25519', + options?: ED25519KeyPairKeyObjectOptions, + ): Promise; + + function __promisify__( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'ed448', + options: ED448KeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'ed448', + options: ED448KeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__(type: 'ed448', options?: ED448KeyPairKeyObjectOptions): Promise; + + function __promisify__( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'x25519', + options: X25519KeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'x25519', + options: X25519KeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__( + type: 'x25519', + options?: X25519KeyPairKeyObjectOptions, + ): Promise; + + function __promisify__( + type: 'x448', + options: X448KeyPairOptions<'pem', 'pem'>, + ): Promise<{ publicKey: string; privateKey: string }>; + function __promisify__( + type: 'x448', + options: X448KeyPairOptions<'pem', 'der'>, + ): Promise<{ publicKey: string; privateKey: Buffer }>; + function __promisify__( + type: 'x448', + options: X448KeyPairOptions<'der', 'pem'>, + ): Promise<{ publicKey: Buffer; privateKey: string }>; + function __promisify__( + type: 'x448', + options: X448KeyPairOptions<'der', 'der'>, + ): Promise<{ publicKey: Buffer; privateKey: Buffer }>; + function __promisify__(type: 'x448', options?: X448KeyPairKeyObjectOptions): Promise; + } + + /** + * Calculates and returns the signature for `data` using the given private key and + * algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is + * dependent upon the key type (especially Ed25519 and Ed448). + * + * If `key` is not a [`KeyObject`][], this function behaves as if `key` had been + * passed to [`crypto.createPrivateKey()`][]. + */ + function sign( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput, + ): Buffer; + + /** + * Calculates and returns the signature for `data` using the given private key and + * algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is + * dependent upon the key type (especially Ed25519 and Ed448). + * + * If `key` is not a [`KeyObject`][], this function behaves as if `key` had been + * passed to [`crypto.createPublicKey()`][]. + */ + function verify( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, + signature: NodeJS.ArrayBufferView, + ): boolean; + + /** + * Computes the Diffie-Hellman secret based on a privateKey and a publicKey. + * Both keys must have the same asymmetricKeyType, which must be one of + * 'dh' (for Diffie-Hellman), 'ec' (for ECDH), 'x448', or 'x25519' (for ECDH-ES). + */ + function diffieHellman(options: { privateKey: KeyObject; publicKey: KeyObject }): Buffer; + + type CipherMode = 'cbc' | 'ccm' | 'cfb' | 'ctr' | 'ecb' | 'gcm' | 'ocb' | 'ofb' | 'stream' | 'wrap' | 'xts'; + + interface CipherInfoOptions { + /** + * A test key length. + */ + keyLength?: number; + /** + * A test IV length. + */ + ivLength?: number; + } + + interface CipherInfo { + /** + * The name of the cipher. + */ + name: string; + /** + * The nid of the cipher. + */ + nid: number; + /** + * The block size of the cipher in bytes. + * This property is omitted when mode is 'stream'. + */ + blockSize?: number; + /** + * The expected or default initialization vector length in bytes. + * This property is omitted if the cipher does not use an initialization vector. + */ + ivLength?: number; + /** + * The expected or default key length in bytes. + */ + keyLength: number; + /** + * The cipher mode. + */ + mode: CipherMode; + } + + /** + * Returns information about a given cipher. + * + * Some ciphers accept variable length keys and initialization vectors. + * By default, the `crypto.getCipherInfo()` method will return the default + * values for these ciphers. To test if a given key length or iv length + * is acceptable for given cipher, use the `keyLenth` and `ivLenth` options. + * If the given values are unacceptable, `undefined` will be returned. + * @param nameOrNid The name or nid of the cipher to query. + */ + function getCipherInfo(nameOrNid: string | number, options?: CipherInfoOptions): CipherInfo | undefined; + + /** + * HKDF is a simple key derivation function defined in RFC 5869. + * The given `key`, `salt` and `info` are used with the `digest` to derive a key of `keylen` bytes. + * + * The supplied `callback` function is called with two arguments: `err` and `derivedKey`. + * If an errors occurs while deriving the key, `err` will be set; otherwise `err` will be `null`. + * The successfully generated `derivedKey` will be passed to the callback as an [`ArrayBuffer`][]. + * An error will be thrown if any of the input aguments specify invalid values or types. + */ + function hkdf(digest: string, key: BinaryLike | KeyObject, salt: BinaryLike, info: BinaryLike, keylen: number, callback: (err: Error | null, derivedKey: ArrayBuffer) => any): void; + + /** + * Provides a synchronous HKDF key derivation function as defined in RFC 5869. + * The given `key`, `salt` and `info` are used with the `digest` to derive a key of `keylen` bytes. + * + * The successfully generated `derivedKey` will be returned as an [`ArrayBuffer`][]. + * An error will be thrown if any of the input aguments specify invalid values or types, + * or if the derived key cannot be generated. + */ + function hkdfSync(digest: string, key: BinaryLike | KeyObject, salt: BinaryLike, info: BinaryLike, keylen: number): ArrayBuffer; +} diff --git a/node_modules/@types/node/dgram.d.ts b/node_modules/@types/node/dgram.d.ts new file mode 100755 index 0000000..d84a1ee --- /dev/null +++ b/node_modules/@types/node/dgram.d.ts @@ -0,0 +1,145 @@ +declare module 'node:dgram' { + export * from 'dgram'; +} + +declare module 'dgram' { + import { AddressInfo } from 'node:net'; + import * as dns from 'node:dns'; + import EventEmitter = require('node:events'); + + interface RemoteInfo { + address: string; + family: 'IPv4' | 'IPv6'; + port: number; + size: number; + } + + interface BindOptions { + port?: number; + address?: string; + exclusive?: boolean; + fd?: number; + } + + type SocketType = "udp4" | "udp6"; + + interface SocketOptions { + type: SocketType; + reuseAddr?: boolean; + /** + * @default false + */ + ipv6Only?: boolean; + recvBufferSize?: number; + sendBufferSize?: number; + lookup?: (hostname: string, options: dns.LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void) => void; + } + + function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + + class Socket extends EventEmitter { + addMembership(multicastAddress: string, multicastInterface?: string): void; + address(): AddressInfo; + bind(port?: number, address?: string, callback?: () => void): void; + bind(port?: number, callback?: () => void): void; + bind(callback?: () => void): void; + bind(options: BindOptions, callback?: () => void): void; + close(callback?: () => void): void; + connect(port: number, address?: string, callback?: () => void): void; + connect(port: number, callback: () => void): void; + disconnect(): void; + dropMembership(multicastAddress: string, multicastInterface?: string): void; + getRecvBufferSize(): number; + getSendBufferSize(): number; + ref(): this; + remoteAddress(): AddressInfo; + send(msg: string | Uint8Array | ReadonlyArray, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void; + send(msg: string | Uint8Array | ReadonlyArray, port?: number, callback?: (error: Error | null, bytes: number) => void): void; + send(msg: string | Uint8Array | ReadonlyArray, callback?: (error: Error | null, bytes: number) => void): void; + send(msg: string | Uint8Array, offset: number, length: number, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void; + send(msg: string | Uint8Array, offset: number, length: number, port?: number, callback?: (error: Error | null, bytes: number) => void): void; + send(msg: string | Uint8Array, offset: number, length: number, callback?: (error: Error | null, bytes: number) => void): void; + setBroadcast(flag: boolean): void; + setMulticastInterface(multicastInterface: string): void; + setMulticastLoopback(flag: boolean): void; + setMulticastTTL(ttl: number): void; + setRecvBufferSize(size: number): void; + setSendBufferSize(size: number): void; + setTTL(ttl: number): void; + unref(): this; + /** + * Tells the kernel to join a source-specific multicast channel at the given + * `sourceAddress` and `groupAddress`, using the `multicastInterface` with the + * `IP_ADD_SOURCE_MEMBERSHIP` socket option. + * If the `multicastInterface` argument + * is not specified, the operating system will choose one interface and will add + * membership to it. + * To add membership to every available interface, call + * `socket.addSourceSpecificMembership()` multiple times, once per interface. + */ + addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void; + + /** + * Instructs the kernel to leave a source-specific multicast channel at the given + * `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` + * socket option. This method is automatically called by the kernel when the + * socket is closed or the process terminates, so most apps will never have + * reason to call this. + * + * If `multicastInterface` is not specified, the operating system will attempt to + * drop membership on all valid interfaces. + */ + dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void; + + /** + * events.EventEmitter + * 1. close + * 2. connect + * 3. error + * 4. listening + * 5. message + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "connect", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "listening", listener: () => void): this; + addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "connect"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "listening"): boolean; + emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "connect", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "listening", listener: () => void): this; + on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "connect", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "listening", listener: () => void): this; + once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "connect", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "listening", listener: () => void): this; + prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "connect", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "listening", listener: () => void): this; + prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + } +} diff --git a/node_modules/@types/node/dns.d.ts b/node_modules/@types/node/dns.d.ts new file mode 100755 index 0000000..e5e3aeb --- /dev/null +++ b/node_modules/@types/node/dns.d.ts @@ -0,0 +1,326 @@ +declare module 'node:dns' { + export * from 'dns'; +} + +declare module 'dns' { + import * as dnsPromises from "node:dns/promises"; + + // Supported getaddrinfo flags. + export const ADDRCONFIG: number; + export const V4MAPPED: number; + /** + * If `dns.V4MAPPED` is specified, return resolved IPv6 addresses as + * well as IPv4 mapped IPv6 addresses. + */ + export const ALL: number; + + export interface LookupOptions { + family?: number; + hints?: number; + all?: boolean; + verbatim?: boolean; + } + + export interface LookupOneOptions extends LookupOptions { + all?: false; + } + + export interface LookupAllOptions extends LookupOptions { + all: true; + } + + export interface LookupAddress { + address: string; + family: number; + } + + export function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void; + export function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void; + export function lookup(hostname: string, options: LookupAllOptions, callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void): void; + export function lookup(hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family: number) => void): void; + export function lookup(hostname: string, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace lookup { + function __promisify__(hostname: string, options: LookupAllOptions): Promise; + function __promisify__(hostname: string, options?: LookupOneOptions | number): Promise; + function __promisify__(hostname: string, options: LookupOptions): Promise; + } + + export function lookupService(address: string, port: number, callback: (err: NodeJS.ErrnoException | null, hostname: string, service: string) => void): void; + + export namespace lookupService { + function __promisify__(address: string, port: number): Promise<{ hostname: string, service: string }>; + } + + export interface ResolveOptions { + ttl: boolean; + } + + export interface ResolveWithTtlOptions extends ResolveOptions { + ttl: true; + } + + export interface RecordWithTtl { + address: string; + ttl: number; + } + + /** @deprecated Use `AnyARecord` or `AnyAaaaRecord` instead. */ + export type AnyRecordWithTtl = AnyARecord | AnyAaaaRecord; + + export interface AnyARecord extends RecordWithTtl { + type: "A"; + } + + export interface AnyAaaaRecord extends RecordWithTtl { + type: "AAAA"; + } + + export interface CaaRecord { + critial: number; + issue?: string; + issuewild?: string; + iodef?: string; + contactemail?: string; + contactphone?: string; + } + + export interface MxRecord { + priority: number; + exchange: string; + } + + export interface AnyMxRecord extends MxRecord { + type: "MX"; + } + + export interface NaptrRecord { + flags: string; + service: string; + regexp: string; + replacement: string; + order: number; + preference: number; + } + + export interface AnyNaptrRecord extends NaptrRecord { + type: "NAPTR"; + } + + export interface SoaRecord { + nsname: string; + hostmaster: string; + serial: number; + refresh: number; + retry: number; + expire: number; + minttl: number; + } + + export interface AnySoaRecord extends SoaRecord { + type: "SOA"; + } + + export interface SrvRecord { + priority: number; + weight: number; + port: number; + name: string; + } + + export interface AnySrvRecord extends SrvRecord { + type: "SRV"; + } + + export interface AnyTxtRecord { + type: "TXT"; + entries: string[]; + } + + export interface AnyNsRecord { + type: "NS"; + value: string; + } + + export interface AnyPtrRecord { + type: "PTR"; + value: string; + } + + export interface AnyCnameRecord { + type: "CNAME"; + value: string; + } + + export type AnyRecord = AnyARecord | + AnyAaaaRecord | + AnyCnameRecord | + AnyMxRecord | + AnyNaptrRecord | + AnyNsRecord | + AnyPtrRecord | + AnySoaRecord | + AnySrvRecord | + AnyTxtRecord; + + export function resolve(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "A", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "AAAA", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "ANY", callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "CNAME", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "MX", callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "NAPTR", callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "NS", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "PTR", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "SOA", callback: (err: NodeJS.ErrnoException | null, addresses: SoaRecord) => void): void; + export function resolve(hostname: string, rrtype: "SRV", callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "TXT", callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void): void; + export function resolve( + hostname: string, + rrtype: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[] | MxRecord[] | NaptrRecord[] | SoaRecord | SrvRecord[] | string[][] | AnyRecord[]) => void, + ): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace resolve { + function __promisify__(hostname: string, rrtype?: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise; + function __promisify__(hostname: string, rrtype: "ANY"): Promise; + function __promisify__(hostname: string, rrtype: "MX"): Promise; + function __promisify__(hostname: string, rrtype: "NAPTR"): Promise; + function __promisify__(hostname: string, rrtype: "SOA"): Promise; + function __promisify__(hostname: string, rrtype: "SRV"): Promise; + function __promisify__(hostname: string, rrtype: "TXT"): Promise; + function __promisify__(hostname: string, rrtype: string): Promise; + } + + export function resolve4(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve4(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void): void; + export function resolve4(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace resolve4 { + function __promisify__(hostname: string): Promise; + function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise; + function __promisify__(hostname: string, options?: ResolveOptions): Promise; + } + + export function resolve6(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export function resolve6(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void): void; + export function resolve6(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace resolve6 { + function __promisify__(hostname: string): Promise; + function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise; + function __promisify__(hostname: string, options?: ResolveOptions): Promise; + } + + export function resolveCname(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export namespace resolveCname { + function __promisify__(hostname: string): Promise; + } + + export function resolveCaa(hostname: string, callback: (err: NodeJS.ErrnoException | null, records: CaaRecord[]) => void): void; + export namespace resolveCaa { + function __promisify__(hostname: string): Promise; + } + + export function resolveMx(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void): void; + export namespace resolveMx { + function __promisify__(hostname: string): Promise; + } + + export function resolveNaptr(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void): void; + export namespace resolveNaptr { + function __promisify__(hostname: string): Promise; + } + + export function resolveNs(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export namespace resolveNs { + function __promisify__(hostname: string): Promise; + } + + export function resolvePtr(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void): void; + export namespace resolvePtr { + function __promisify__(hostname: string): Promise; + } + + export function resolveSoa(hostname: string, callback: (err: NodeJS.ErrnoException | null, address: SoaRecord) => void): void; + export namespace resolveSoa { + function __promisify__(hostname: string): Promise; + } + + export function resolveSrv(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void): void; + export namespace resolveSrv { + function __promisify__(hostname: string): Promise; + } + + export function resolveTxt(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void): void; + export namespace resolveTxt { + function __promisify__(hostname: string): Promise; + } + + export function resolveAny(hostname: string, callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void): void; + export namespace resolveAny { + function __promisify__(hostname: string): Promise; + } + + export function reverse(ip: string, callback: (err: NodeJS.ErrnoException | null, hostnames: string[]) => void): void; + export function setServers(servers: ReadonlyArray): void; + export function getServers(): string[]; + + // Error codes + export const NODATA: string; + export const FORMERR: string; + export const SERVFAIL: string; + export const NOTFOUND: string; + export const NOTIMP: string; + export const REFUSED: string; + export const BADQUERY: string; + export const BADNAME: string; + export const BADFAMILY: string; + export const BADRESP: string; + export const CONNREFUSED: string; + export const TIMEOUT: string; + export const EOF: string; + export const FILE: string; + export const NOMEM: string; + export const DESTRUCTION: string; + export const BADSTR: string; + export const BADFLAGS: string; + export const NONAME: string; + export const BADHINTS: string; + export const NOTINITIALIZED: string; + export const LOADIPHLPAPI: string; + export const ADDRGETNETWORKPARAMS: string; + export const CANCELLED: string; + + export interface ResolverOptions { + timeout?: number; + } + + export class Resolver { + constructor(options?: ResolverOptions); + + cancel(): void; + getServers: typeof getServers; + resolve: typeof resolve; + resolve4: typeof resolve4; + resolve6: typeof resolve6; + resolveAny: typeof resolveAny; + resolveCname: typeof resolveCname; + resolveMx: typeof resolveMx; + resolveNaptr: typeof resolveNaptr; + resolveNs: typeof resolveNs; + resolvePtr: typeof resolvePtr; + resolveSoa: typeof resolveSoa; + resolveSrv: typeof resolveSrv; + resolveTxt: typeof resolveTxt; + reverse: typeof reverse; + setLocalAddress(ipv4?: string, ipv6?: string): void; + setServers: typeof setServers; + } + + export { dnsPromises as promises }; +} diff --git a/node_modules/@types/node/dns/promises.d.ts b/node_modules/@types/node/dns/promises.d.ts new file mode 100755 index 0000000..73cf041 --- /dev/null +++ b/node_modules/@types/node/dns/promises.d.ts @@ -0,0 +1,101 @@ +declare module "node:dns/promises" { + export * from "dns/promises"; +} + +declare module "dns/promises" { + import { + LookupAddress, + LookupOneOptions, + LookupAllOptions, + LookupOptions, + AnyRecord, + CaaRecord, + MxRecord, + NaptrRecord, + SoaRecord, + SrvRecord, + ResolveWithTtlOptions, + RecordWithTtl, + ResolveOptions, + ResolverOptions, + } from "node:dns"; + + function getServers(): string[]; + + function lookup(hostname: string, family: number): Promise; + function lookup(hostname: string, options: LookupOneOptions): Promise; + function lookup(hostname: string, options: LookupAllOptions): Promise; + function lookup(hostname: string, options: LookupOptions): Promise; + function lookup(hostname: string): Promise; + + function lookupService(address: string, port: number): Promise<{ hostname: string, service: string }>; + + function resolve(hostname: string): Promise; + function resolve(hostname: string, rrtype: "A"): Promise; + function resolve(hostname: string, rrtype: "AAAA"): Promise; + function resolve(hostname: string, rrtype: "ANY"): Promise; + function resolve(hostname: string, rrtype: "CAA"): Promise; + function resolve(hostname: string, rrtype: "CNAME"): Promise; + function resolve(hostname: string, rrtype: "MX"): Promise; + function resolve(hostname: string, rrtype: "NAPTR"): Promise; + function resolve(hostname: string, rrtype: "NS"): Promise; + function resolve(hostname: string, rrtype: "PTR"): Promise; + function resolve(hostname: string, rrtype: "SOA"): Promise; + function resolve(hostname: string, rrtype: "SRV"): Promise; + function resolve(hostname: string, rrtype: "TXT"): Promise; + function resolve(hostname: string, rrtype: string): Promise; + + function resolve4(hostname: string): Promise; + function resolve4(hostname: string, options: ResolveWithTtlOptions): Promise; + function resolve4(hostname: string, options: ResolveOptions): Promise; + + function resolve6(hostname: string): Promise; + function resolve6(hostname: string, options: ResolveWithTtlOptions): Promise; + function resolve6(hostname: string, options: ResolveOptions): Promise; + + function resolveAny(hostname: string): Promise; + + function resolveCaa(hostname: string): Promise; + + function resolveCname(hostname: string): Promise; + + function resolveMx(hostname: string): Promise; + + function resolveNaptr(hostname: string): Promise; + + function resolveNs(hostname: string): Promise; + + function resolvePtr(hostname: string): Promise; + + function resolveSoa(hostname: string): Promise; + + function resolveSrv(hostname: string): Promise; + + function resolveTxt(hostname: string): Promise; + + function reverse(ip: string): Promise; + + function setServers(servers: ReadonlyArray): void; + + class Resolver { + constructor(options?: ResolverOptions); + + cancel(): void; + getServers: typeof getServers; + resolve: typeof resolve; + resolve4: typeof resolve4; + resolve6: typeof resolve6; + resolveAny: typeof resolveAny; + resolveCname: typeof resolveCname; + resolveMx: typeof resolveMx; + resolveNaptr: typeof resolveNaptr; + resolveNs: typeof resolveNs; + resolvePtr: typeof resolvePtr; + resolveSoa: typeof resolveSoa; + resolveSrv: typeof resolveSrv; + resolveTxt: typeof resolveTxt; + reverse: typeof reverse; + setLocalAddress(ipv4?: string, ipv6?: string): void; + setServers: typeof setServers; + } +} diff --git a/node_modules/@types/node/domain.d.ts b/node_modules/@types/node/domain.d.ts new file mode 100755 index 0000000..4d5f153 --- /dev/null +++ b/node_modules/@types/node/domain.d.ts @@ -0,0 +1,28 @@ +declare module 'node:domain' { + export * from 'domain'; +} + +declare module 'domain' { + import EventEmitter = require('node:events'); + + global { + namespace NodeJS { + interface Domain extends EventEmitter { + run(fn: (...args: any[]) => T, ...args: any[]): T; + add(emitter: EventEmitter | Timer): void; + remove(emitter: EventEmitter | Timer): void; + bind(cb: T): T; + intercept(cb: T): T; + } + } + } + + interface Domain extends NodeJS.Domain {} + class Domain extends EventEmitter { + members: Array; + enter(): void; + exit(): void; + } + + function create(): Domain; +} diff --git a/node_modules/@types/node/events.d.ts b/node_modules/@types/node/events.d.ts new file mode 100755 index 0000000..1d4e119 --- /dev/null +++ b/node_modules/@types/node/events.d.ts @@ -0,0 +1,87 @@ +declare module 'node:events' { + import EventEmitter = require('events'); + export = EventEmitter; +} + +declare module 'events' { + interface EventEmitterOptions { + /** + * Enables automatic capturing of promise rejection. + */ + captureRejections?: boolean; + } + + interface NodeEventTarget { + once(event: string | symbol, listener: (...args: any[]) => void): this; + } + + interface DOMEventTarget { + addEventListener(event: string, listener: (...args: any[]) => void, opts?: { once: boolean }): any; + } + + interface StaticEventEmitterOptions { + signal?: AbortSignal; + } + + interface EventEmitter extends NodeJS.EventEmitter {} + class EventEmitter { + constructor(options?: EventEmitterOptions); + + static once(emitter: NodeEventTarget, event: string | symbol, options?: StaticEventEmitterOptions): Promise; + static once(emitter: DOMEventTarget, event: string, options?: StaticEventEmitterOptions): Promise; + static on(emitter: NodeJS.EventEmitter, event: string, options?: StaticEventEmitterOptions): AsyncIterableIterator; + + /** @deprecated since v4.0.0 */ + static listenerCount(emitter: NodeJS.EventEmitter, event: string | symbol): number; + + /** + * This symbol shall be used to install a listener for only monitoring `'error'` + * events. Listeners installed using this symbol are called before the regular + * `'error'` listeners are called. + * + * Installing a listener using this symbol does not change the behavior once an + * `'error'` event is emitted, therefore the process will still crash if no + * regular `'error'` listener is installed. + */ + static readonly errorMonitor: unique symbol; + static readonly captureRejectionSymbol: unique symbol; + + /** + * Sets or gets the default captureRejection value for all emitters. + */ + // TODO: These should be described using static getter/setter pairs: + static captureRejections: boolean; + static defaultMaxListeners: number; + } + + import internal = require('events'); + namespace EventEmitter { + // Should just be `export { EventEmitter }`, but that doesn't work in TypeScript 3.4 + export { internal as EventEmitter }; + } + + global { + namespace NodeJS { + interface EventEmitter { + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; + removeAllListeners(event?: string | symbol): this; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string | symbol): Function[]; + rawListeners(event: string | symbol): Function[]; + emit(event: string | symbol, ...args: any[]): boolean; + listenerCount(event: string | symbol): number; + // Added in Node 6... + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + eventNames(): Array; + } + } + } + + export = EventEmitter; +} diff --git a/node_modules/@types/node/fs.d.ts b/node_modules/@types/node/fs.d.ts new file mode 100755 index 0000000..384acfd --- /dev/null +++ b/node_modules/@types/node/fs.d.ts @@ -0,0 +1,2261 @@ +declare module 'node:fs' { + export * from 'fs'; +} + +declare module 'fs' { + import * as stream from 'node:stream'; + import EventEmitter = require('node:events'); + import { URL } from 'node:url'; + import * as promises from 'node:fs/promises'; + + export { promises }; + /** + * Valid types for path values in "fs". + */ + export type PathLike = string | Buffer | URL; + + export type NoParamCallback = (err: NodeJS.ErrnoException | null) => void; + + export type BufferEncodingOption = 'buffer' | { encoding: 'buffer' }; + + export interface BaseEncodingOptions { + encoding?: BufferEncoding | null; + } + + export type OpenMode = number | string; + + export type Mode = number | string; + + export interface StatsBase { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + + dev: T; + ino: T; + mode: T; + nlink: T; + uid: T; + gid: T; + rdev: T; + size: T; + blksize: T; + blocks: T; + atimeMs: T; + mtimeMs: T; + ctimeMs: T; + birthtimeMs: T; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + + export interface Stats extends StatsBase { + } + + export class Stats { + } + + export class Dirent { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + name: string; + } + + /** + * A class representing a directory stream. + */ + export class Dir { + readonly path: string; + + /** + * Asynchronously iterates over the directory via `readdir(3)` until all entries have been read. + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Asynchronously close the directory's underlying resource handle. + * Subsequent reads will result in errors. + */ + close(): Promise; + close(cb: NoParamCallback): void; + + /** + * Synchronously close the directory's underlying resource handle. + * Subsequent reads will result in errors. + */ + closeSync(): void; + + /** + * Asynchronously read the next directory entry via `readdir(3)` as an `Dirent`. + * After the read is completed, a value is returned that will be resolved with an `Dirent`, or `null` if there are no more directory entries to read. + * Directory entries returned by this function are in no particular order as provided by the operating system's underlying directory mechanisms. + */ + read(): Promise; + read(cb: (err: NodeJS.ErrnoException | null, dirEnt: Dirent | null) => void): void; + + /** + * Synchronously read the next directory entry via `readdir(3)` as a `Dirent`. + * If there are no more directory entries to read, null will be returned. + * Directory entries returned by this function are in no particular order as provided by the operating system's underlying directory mechanisms. + */ + readSync(): Dirent | null; + } + + export interface FSWatcher extends EventEmitter { + close(): void; + + /** + * events.EventEmitter + * 1. change + * 2. error + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "close", listener: () => void): this; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "close", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "close", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "close", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + } + + export class ReadStream extends stream.Readable { + close(): void; + bytesRead: number; + path: string | Buffer; + pending: boolean; + + /** + * events.EventEmitter + * 1. open + * 2. close + * 3. ready + */ + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: Buffer | string) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "open", listener: (fd: number) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "ready", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: Buffer | string) => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "open", listener: (fd: number) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "ready", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: Buffer | string) => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "open", listener: (fd: number) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "ready", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "open", listener: (fd: number) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "ready", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "open", listener: (fd: number) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "ready", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export class WriteStream extends stream.Writable { + close(): void; + bytesWritten: number; + path: string | Buffer; + pending: boolean; + + /** + * events.EventEmitter + * 1. open + * 2. close + * 3. ready + */ + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "open", listener: (fd: number) => void): this; + addListener(event: "pipe", listener: (src: stream.Readable) => void): this; + addListener(event: "ready", listener: () => void): this; + addListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "open", listener: (fd: number) => void): this; + on(event: "pipe", listener: (src: stream.Readable) => void): this; + on(event: "ready", listener: () => void): this; + on(event: "unpipe", listener: (src: stream.Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "open", listener: (fd: number) => void): this; + once(event: "pipe", listener: (src: stream.Readable) => void): this; + once(event: "ready", listener: () => void): this; + once(event: "unpipe", listener: (src: stream.Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "open", listener: (fd: number) => void): this; + prependListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependListener(event: "ready", listener: () => void): this; + prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "open", listener: (fd: number) => void): this; + prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: "ready", listener: () => void): this; + prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + /** + * Asynchronous rename(2) - Change the name or location of a file or directory. + * @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function rename(oldPath: PathLike, newPath: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace rename { + /** + * Asynchronous rename(2) - Change the name or location of a file or directory. + * @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(oldPath: PathLike, newPath: PathLike): Promise; + } + + /** + * Synchronous rename(2) - Change the name or location of a file or directory. + * @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function renameSync(oldPath: PathLike, newPath: PathLike): void; + + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param len If not specified, defaults to `0`. + */ + export function truncate(path: PathLike, len: number | undefined | null, callback: NoParamCallback): void; + + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function truncate(path: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace truncate { + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param len If not specified, defaults to `0`. + */ + function __promisify__(path: PathLike, len?: number | null): Promise; + } + + /** + * Synchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param len If not specified, defaults to `0`. + */ + export function truncateSync(path: PathLike, len?: number | null): void; + + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + * @param len If not specified, defaults to `0`. + */ + export function ftruncate(fd: number, len: number | undefined | null, callback: NoParamCallback): void; + + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + */ + export function ftruncate(fd: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace ftruncate { + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + * @param len If not specified, defaults to `0`. + */ + function __promisify__(fd: number, len?: number | null): Promise; + } + + /** + * Synchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + * @param len If not specified, defaults to `0`. + */ + export function ftruncateSync(fd: number, len?: number | null): void; + + /** + * Asynchronous chown(2) - Change ownership of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function chown(path: PathLike, uid: number, gid: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace chown { + /** + * Asynchronous chown(2) - Change ownership of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, uid: number, gid: number): Promise; + } + + /** + * Synchronous chown(2) - Change ownership of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function chownSync(path: PathLike, uid: number, gid: number): void; + + /** + * Asynchronous fchown(2) - Change ownership of a file. + * @param fd A file descriptor. + */ + export function fchown(fd: number, uid: number, gid: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace fchown { + /** + * Asynchronous fchown(2) - Change ownership of a file. + * @param fd A file descriptor. + */ + function __promisify__(fd: number, uid: number, gid: number): Promise; + } + + /** + * Synchronous fchown(2) - Change ownership of a file. + * @param fd A file descriptor. + */ + export function fchownSync(fd: number, uid: number, gid: number): void; + + /** + * Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function lchown(path: PathLike, uid: number, gid: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace lchown { + /** + * Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, uid: number, gid: number): Promise; + } + + /** + * Synchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function lchownSync(path: PathLike, uid: number, gid: number): void; + + /** + * Changes the access and modification times of a file in the same way as `fs.utimes()`, + * with the difference that if the path refers to a symbolic link, then the link is not + * dereferenced: instead, the timestamps of the symbolic link itself are changed. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function lutimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace lutimes { + /** + * Changes the access and modification times of a file in the same way as `fsPromises.utimes()`, + * with the difference that if the path refers to a symbolic link, then the link is not + * dereferenced: instead, the timestamps of the symbolic link itself are changed. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise; + } + + /** + * Change the file system timestamps of the symbolic link referenced by `path`. Returns `undefined`, + * or throws an exception when parameters are incorrect or the operation fails. + * This is the synchronous version of `fs.lutimes()`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function lutimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void; + + /** + * Asynchronous chmod(2) - Change permissions of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function chmod(path: PathLike, mode: Mode, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace chmod { + /** + * Asynchronous chmod(2) - Change permissions of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(path: PathLike, mode: Mode): Promise; + } + + /** + * Synchronous chmod(2) - Change permissions of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function chmodSync(path: PathLike, mode: Mode): void; + + /** + * Asynchronous fchmod(2) - Change permissions of a file. + * @param fd A file descriptor. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function fchmod(fd: number, mode: Mode, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace fchmod { + /** + * Asynchronous fchmod(2) - Change permissions of a file. + * @param fd A file descriptor. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(fd: number, mode: Mode): Promise; + } + + /** + * Synchronous fchmod(2) - Change permissions of a file. + * @param fd A file descriptor. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function fchmodSync(fd: number, mode: Mode): void; + + /** + * Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function lchmod(path: PathLike, mode: Mode, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace lchmod { + /** + * Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(path: PathLike, mode: Mode): Promise; + } + + /** + * Synchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + export function lchmodSync(path: PathLike, mode: Mode): void; + + /** + * Asynchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function stat(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function stat(path: PathLike, options: StatOptions & { bigint?: false } | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function stat(path: PathLike, options: StatOptions & { bigint: true }, callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void): void; + export function stat(path: PathLike, options: StatOptions | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace stat { + /** + * Asynchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, options?: StatOptions & { bigint?: false }): Promise; + function __promisify__(path: PathLike, options: StatOptions & { bigint: true }): Promise; + function __promisify__(path: PathLike, options?: StatOptions): Promise; + } + + /** + * Synchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function statSync(path: PathLike, options?: StatOptions & { bigint?: false }): Stats; + export function statSync(path: PathLike, options: StatOptions & { bigint: true }): BigIntStats; + export function statSync(path: PathLike, options?: StatOptions): Stats | BigIntStats; + + /** + * Asynchronous fstat(2) - Get file status. + * @param fd A file descriptor. + */ + export function fstat(fd: number, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function fstat(fd: number, options: StatOptions & { bigint?: false } | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function fstat(fd: number, options: StatOptions & { bigint: true }, callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void): void; + export function fstat(fd: number, options: StatOptions | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace fstat { + /** + * Asynchronous fstat(2) - Get file status. + * @param fd A file descriptor. + */ + function __promisify__(fd: number, options?: StatOptions & { bigint?: false }): Promise; + function __promisify__(fd: number, options: StatOptions & { bigint: true }): Promise; + function __promisify__(fd: number, options?: StatOptions): Promise; + } + + /** + * Synchronous fstat(2) - Get file status. + * @param fd A file descriptor. + */ + export function fstatSync(fd: number, options?: StatOptions & { bigint?: false }): Stats; + export function fstatSync(fd: number, options: StatOptions & { bigint: true }): BigIntStats; + export function fstatSync(fd: number, options?: StatOptions): Stats | BigIntStats; + + /** + * Asynchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function lstat(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function lstat(path: PathLike, options: StatOptions & { bigint?: false } | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + export function lstat(path: PathLike, options: StatOptions & { bigint: true }, callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void): void; + export function lstat(path: PathLike, options: StatOptions | undefined, callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace lstat { + /** + * Asynchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, options?: StatOptions & { bigint?: false }): Promise; + function __promisify__(path: PathLike, options: StatOptions & { bigint: true }): Promise; + function __promisify__(path: PathLike, options?: StatOptions): Promise; + } + + /** + * Synchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function lstatSync(path: PathLike, options?: StatOptions & { bigint?: false }): Stats; + export function lstatSync(path: PathLike, options: StatOptions & { bigint: true }): BigIntStats; + export function lstatSync(path: PathLike, options?: StatOptions): Stats | BigIntStats; + + /** + * Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file. + * @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function link(existingPath: PathLike, newPath: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace link { + /** + * Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file. + * @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(existingPath: PathLike, newPath: PathLike): Promise; + } + + /** + * Synchronous link(2) - Create a new link (also known as a hard link) to an existing file. + * @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function linkSync(existingPath: PathLike, newPath: PathLike): void; + + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + * @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). + * When using `'junction'`, the `target` argument will automatically be normalized to an absolute path. + */ + export function symlink(target: PathLike, path: PathLike, type: symlink.Type | undefined | null, callback: NoParamCallback): void; + + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + */ + export function symlink(target: PathLike, path: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace symlink { + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + * @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). + * When using `'junction'`, the `target` argument will automatically be normalized to an absolute path. + */ + function __promisify__(target: PathLike, path: PathLike, type?: string | null): Promise; + + type Type = "dir" | "file" | "junction"; + } + + /** + * Synchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + * @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). + * When using `'junction'`, the `target` argument will automatically be normalized to an absolute path. + */ + export function symlinkSync(target: PathLike, path: PathLike, type?: symlink.Type | null): void; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlink( + path: PathLike, + options: BaseEncodingOptions | BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, linkString: string) => void + ): void; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlink(path: PathLike, options: BufferEncodingOption, callback: (err: NodeJS.ErrnoException | null, linkString: Buffer) => void): void; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlink(path: PathLike, options: BaseEncodingOptions | string | undefined | null, callback: (err: NodeJS.ErrnoException | null, linkString: string | Buffer) => void): void; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function readlink(path: PathLike, callback: (err: NodeJS.ErrnoException | null, linkString: string) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace readlink { + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: BaseEncodingOptions | string | null): Promise; + } + + /** + * Synchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlinkSync(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): string; + + /** + * Synchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlinkSync(path: PathLike, options: BufferEncodingOption): Buffer; + + /** + * Synchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readlinkSync(path: PathLike, options?: BaseEncodingOptions | string | null): string | Buffer; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpath( + path: PathLike, + options: BaseEncodingOptions | BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void + ): void; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpath(path: PathLike, options: BufferEncodingOption, callback: (err: NodeJS.ErrnoException | null, resolvedPath: Buffer) => void): void; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpath(path: PathLike, options: BaseEncodingOptions | string | undefined | null, callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | Buffer) => void): void; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function realpath(path: PathLike, callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace realpath { + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: BaseEncodingOptions | string | null): Promise; + + function native( + path: PathLike, + options: BaseEncodingOptions | BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void + ): void; + function native(path: PathLike, options: BufferEncodingOption, callback: (err: NodeJS.ErrnoException | null, resolvedPath: Buffer) => void): void; + function native(path: PathLike, options: BaseEncodingOptions | string | undefined | null, callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | Buffer) => void): void; + function native(path: PathLike, callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void): void; + } + + /** + * Synchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpathSync(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): string; + + /** + * Synchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpathSync(path: PathLike, options: BufferEncodingOption): Buffer; + + /** + * Synchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function realpathSync(path: PathLike, options?: BaseEncodingOptions | string | null): string | Buffer; + + export namespace realpathSync { + function native(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): string; + function native(path: PathLike, options: BufferEncodingOption): Buffer; + function native(path: PathLike, options?: BaseEncodingOptions | string | null): string | Buffer; + } + + /** + * Asynchronous unlink(2) - delete a name and possibly the file it refers to. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function unlink(path: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace unlink { + /** + * Asynchronous unlink(2) - delete a name and possibly the file it refers to. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike): Promise; + } + + /** + * Synchronous unlink(2) - delete a name and possibly the file it refers to. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function unlinkSync(path: PathLike): void; + + export interface RmDirOptions { + /** + * If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + * `EPERM` error is encountered, Node.js will retry the operation with a linear + * backoff wait of `retryDelay` ms longer on each try. This option represents the + * number of retries. This option is ignored if the `recursive` option is not + * `true`. + * @default 0 + */ + maxRetries?: number; + /** + * @deprecated since v14.14.0 In future versions of Node.js, + * `fs.rmdir(path, { recursive: true })` will throw if `path` does not exist or is a file. + * Use `fs.rm(path, { recursive: true, force: true })` instead. + * + * If `true`, perform a recursive directory removal. In + * recursive mode, errors are not reported if `path` does not exist, and + * operations are retried on failure. + * @default false + */ + recursive?: boolean; + /** + * The amount of time in milliseconds to wait between retries. + * This option is ignored if the `recursive` option is not `true`. + * @default 100 + */ + retryDelay?: number; + } + + /** + * Asynchronous rmdir(2) - delete a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function rmdir(path: PathLike, callback: NoParamCallback): void; + export function rmdir(path: PathLike, options: RmDirOptions, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace rmdir { + /** + * Asynchronous rmdir(2) - delete a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, options?: RmDirOptions): Promise; + } + + /** + * Synchronous rmdir(2) - delete a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function rmdirSync(path: PathLike, options?: RmDirOptions): void; + + export interface RmOptions { + /** + * When `true`, exceptions will be ignored if `path` does not exist. + * @default false + */ + force?: boolean; + /** + * If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + * `EPERM` error is encountered, Node.js will retry the operation with a linear + * backoff wait of `retryDelay` ms longer on each try. This option represents the + * number of retries. This option is ignored if the `recursive` option is not + * `true`. + * @default 0 + */ + maxRetries?: number; + /** + * If `true`, perform a recursive directory removal. In + * recursive mode, errors are not reported if `path` does not exist, and + * operations are retried on failure. + * @default false + */ + recursive?: boolean; + /** + * The amount of time in milliseconds to wait between retries. + * This option is ignored if the `recursive` option is not `true`. + * @default 100 + */ + retryDelay?: number; + } + + /** + * Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). + */ + export function rm(path: PathLike, callback: NoParamCallback): void; + export function rm(path: PathLike, options: RmOptions, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace rm { + /** + * Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). + */ + function __promisify__(path: PathLike, options?: RmOptions): Promise; + } + + /** + * Synchronously removes files and directories (modeled on the standard POSIX `rm` utility). + */ + export function rmSync(path: PathLike, options?: RmOptions): void; + + export interface MakeDirectoryOptions { + /** + * Indicates whether parent folders should be created. + * If a folder was created, the path to the first created folder will be returned. + * @default false + */ + recursive?: boolean; + /** + * A file mode. If a string is passed, it is parsed as an octal integer. If not specified + * @default 0o777 + */ + mode?: Mode; + } + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true }, callback: (err: NodeJS.ErrnoException | null, path?: string) => void): void; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdir(path: PathLike, options: Mode | (MakeDirectoryOptions & { recursive?: false; }) | null | undefined, callback: NoParamCallback): void; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdir(path: PathLike, options: Mode | MakeDirectoryOptions | null | undefined, callback: (err: NodeJS.ErrnoException | null, path?: string) => void): void; + + /** + * Asynchronous mkdir(2) - create a directory with a mode of `0o777`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function mkdir(path: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace mkdir { + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__(path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false; }) | null): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__(path: PathLike, options?: Mode | MakeDirectoryOptions | null): Promise; + } + + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdirSync(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): string | undefined; + + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdirSync(path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false; }) | null): void; + + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + export function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtemp(prefix: string, options: BaseEncodingOptions | BufferEncoding | undefined | null, callback: (err: NodeJS.ErrnoException | null, folder: string) => void): void; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtemp(prefix: string, options: "buffer" | { encoding: "buffer" }, callback: (err: NodeJS.ErrnoException | null, folder: Buffer) => void): void; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtemp(prefix: string, options: BaseEncodingOptions | string | undefined | null, callback: (err: NodeJS.ErrnoException | null, folder: string | Buffer) => void): void; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + */ + export function mkdtemp(prefix: string, callback: (err: NodeJS.ErrnoException | null, folder: string) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace mkdtemp { + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options: BufferEncodingOption): Promise; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options?: BaseEncodingOptions | string | null): Promise; + } + + /** + * Synchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtempSync(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): string; + + /** + * Synchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtempSync(prefix: string, options: BufferEncodingOption): Buffer; + + /** + * Synchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function mkdtempSync(prefix: string, options?: BaseEncodingOptions | string | null): string | Buffer; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdir( + path: PathLike, + options: { encoding: BufferEncoding | null; withFileTypes?: false } | BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, files: string[]) => void, + ): void; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer", callback: (err: NodeJS.ErrnoException | null, files: Buffer[]) => void): void; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdir( + path: PathLike, + options: BaseEncodingOptions & { withFileTypes?: false } | BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, files: string[] | Buffer[]) => void, + ): void; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function readdir(path: PathLike, callback: (err: NodeJS.ErrnoException | null, files: string[]) => void): void; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + export function readdir(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }, callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace readdir { + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: { encoding: BufferEncoding | null; withFileTypes?: false } | BufferEncoding | null): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options: "buffer" | { encoding: "buffer"; withFileTypes?: false }): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false } | BufferEncoding | null): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent + */ + function __promisify__(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }): Promise; + } + + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdirSync(path: PathLike, options?: { encoding: BufferEncoding | null; withFileTypes?: false } | BufferEncoding | null): string[]; + + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdirSync(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Buffer[]; + + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + export function readdirSync(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false } | BufferEncoding | null): string[] | Buffer[]; + + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + export function readdirSync(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }): Dirent[]; + + /** + * Asynchronous close(2) - close a file descriptor. + * @param fd A file descriptor. + */ + export function close(fd: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace close { + /** + * Asynchronous close(2) - close a file descriptor. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise; + } + + /** + * Synchronous close(2) - close a file descriptor. + * @param fd A file descriptor. + */ + export function closeSync(fd: number): void; + + /** + * Asynchronous open(2) - open and possibly create a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not supplied, defaults to `0o666`. + */ + export function open(path: PathLike, flags: OpenMode, mode: Mode | undefined | null, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void; + + /** + * Asynchronous open(2) - open and possibly create a file. If the file is created, its mode will be `0o666`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + export function open(path: PathLike, flags: OpenMode, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace open { + /** + * Asynchronous open(2) - open and possibly create a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not supplied, defaults to `0o666`. + */ + function __promisify__(path: PathLike, flags: OpenMode, mode?: Mode | null): Promise; + } + + /** + * Synchronous open(2) - open and possibly create a file, returning a file descriptor.. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not supplied, defaults to `0o666`. + */ + export function openSync(path: PathLike, flags: OpenMode, mode?: Mode | null): number; + + /** + * Asynchronously change file timestamps of the file referenced by the supplied path. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace utimes { + /** + * Asynchronously change file timestamps of the file referenced by the supplied path. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise; + } + + /** + * Synchronously change file timestamps of the file referenced by the supplied path. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function utimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void; + + /** + * Asynchronously change file timestamps of the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function futimes(fd: number, atime: string | number | Date, mtime: string | number | Date, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace futimes { + /** + * Asynchronously change file timestamps of the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(fd: number, atime: string | number | Date, mtime: string | number | Date): Promise; + } + + /** + * Synchronously change file timestamps of the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + export function futimesSync(fd: number, atime: string | number | Date, mtime: string | number | Date): void; + + /** + * Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + * @param fd A file descriptor. + */ + export function fsync(fd: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace fsync { + /** + * Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise; + } + + /** + * Synchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + * @param fd A file descriptor. + */ + export function fsyncSync(fd: number): void; + + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + export function write( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + length: number | undefined | null, + position: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + */ + export function write( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + length: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + */ + export function write( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void + ): void; + + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + */ + export function write(fd: number, buffer: TBuffer, callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void): void; + + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + export function write( + fd: number, + string: string, + position: number | undefined | null, + encoding: BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void, + ): void; + + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + export function write(fd: number, string: string, position: number | undefined | null, callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void): void; + + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + */ + export function write(fd: number, string: string, callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace write { + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function __promisify__( + fd: number, + buffer?: TBuffer, + offset?: number, + length?: number, + position?: number | null, + ): Promise<{ bytesWritten: number, buffer: TBuffer }>; + + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + function __promisify__(fd: number, string: string, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>; + } + + /** + * Synchronously writes `buffer` to the file referenced by the supplied file descriptor, returning the number of bytes written. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + export function writeSync(fd: number, buffer: NodeJS.ArrayBufferView, offset?: number | null, length?: number | null, position?: number | null): number; + + /** + * Synchronously writes `string` to the file referenced by the supplied file descriptor, returning the number of bytes written. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + export function writeSync(fd: number, string: string, position?: number | null, encoding?: BufferEncoding | null): number; + + /** + * Asynchronously reads data from the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position. + */ + export function read( + fd: number, + buffer: TBuffer, + offset: number, + length: number, + position: number | null, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void, + ): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace read { + /** + * @param fd A file descriptor. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position. + */ + function __promisify__( + fd: number, + buffer: TBuffer, + offset: number, + length: number, + position: number | null + ): Promise<{ bytesRead: number, buffer: TBuffer }>; + } + + export interface ReadSyncOptions { + /** + * @default 0 + */ + offset?: number; + /** + * @default `length of buffer` + */ + length?: number; + /** + * @default null + */ + position?: number | null; + } + + /** + * Synchronously reads data from the file referenced by the supplied file descriptor, returning the number of bytes read. + * @param fd A file descriptor. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position. + */ + export function readSync(fd: number, buffer: NodeJS.ArrayBufferView, offset: number, length: number, position: number | null): number; + + /** + * Similar to the above `fs.readSync` function, this version takes an optional `options` object. + * If no `options` object is specified, it will default with the above values. + */ + export function readSync(fd: number, buffer: NodeJS.ArrayBufferView, opts?: ReadSyncOptions): number; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + export function readFile(path: PathLike | number, options: { encoding?: null; flag?: string; } | undefined | null, callback: (err: NodeJS.ErrnoException | null, data: Buffer) => void): void; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + export function readFile(path: PathLike | number, options: { encoding: BufferEncoding; flag?: string; } | string, callback: (err: NodeJS.ErrnoException | null, data: string) => void): void; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + export function readFile( + path: PathLike | number, + options: BaseEncodingOptions & { flag?: string; } | string | undefined | null, + callback: (err: NodeJS.ErrnoException | null, data: string | Buffer) => void, + ): void; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + */ + export function readFile(path: PathLike | number, callback: (err: NodeJS.ErrnoException | null, data: Buffer) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace readFile { + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__(path: PathLike | number, options?: { encoding?: null; flag?: string; } | null): Promise; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__(path: PathLike | number, options: { encoding: BufferEncoding; flag?: string; } | string): Promise; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__(path: PathLike | number, options?: BaseEncodingOptions & { flag?: string; } | string | null): Promise; + } + + /** + * Synchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. If a flag is not provided, it defaults to `'r'`. + */ + export function readFileSync(path: PathLike | number, options?: { encoding?: null; flag?: string; } | null): Buffer; + + /** + * Synchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + export function readFileSync(path: PathLike | number, options: { encoding: BufferEncoding; flag?: string; } | BufferEncoding): string; + + /** + * Synchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + export function readFileSync(path: PathLike | number, options?: BaseEncodingOptions & { flag?: string; } | BufferEncoding | null): string | Buffer; + + export type WriteFileOptions = BaseEncodingOptions & { mode?: Mode; flag?: string; } | string | null; + + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + export function writeFile(path: PathLike | number, data: string | NodeJS.ArrayBufferView, options: WriteFileOptions, callback: NoParamCallback): void; + + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + */ + export function writeFile(path: PathLike | number, data: string | NodeJS.ArrayBufferView, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace writeFile { + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + function __promisify__(path: PathLike | number, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): Promise; + } + + /** + * Synchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + export function writeFileSync(path: PathLike | number, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void; + + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + export function appendFile(file: PathLike | number, data: string | Uint8Array, options: WriteFileOptions, callback: NoParamCallback): void; + + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + */ + export function appendFile(file: PathLike | number, data: string | Uint8Array, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace appendFile { + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + function __promisify__(file: PathLike | number, data: string | Uint8Array, options?: WriteFileOptions): Promise; + } + + /** + * Synchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + export function appendFileSync(file: PathLike | number, data: string | Uint8Array, options?: WriteFileOptions): void; + + /** + * Watch for changes on `filename`. The callback `listener` will be called each time the file is accessed. + */ + export function watchFile(filename: PathLike, options: { persistent?: boolean; interval?: number; } | undefined, listener: (curr: Stats, prev: Stats) => void): void; + + /** + * Watch for changes on `filename`. The callback `listener` will be called each time the file is accessed. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function watchFile(filename: PathLike, listener: (curr: Stats, prev: Stats) => void): void; + + /** + * Stop watching for changes on `filename`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function unwatchFile(filename: PathLike, listener?: (curr: Stats, prev: Stats) => void): void; + + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `persistent` is not supplied, the default of `true` is used. + * If `recursive` is not supplied, the default of `false` is used. + */ + export function watch( + filename: PathLike, + options: { encoding?: BufferEncoding | null, persistent?: boolean, recursive?: boolean } | BufferEncoding | undefined | null, + listener?: (event: "rename" | "change", filename: string) => void, + ): FSWatcher; + + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `persistent` is not supplied, the default of `true` is used. + * If `recursive` is not supplied, the default of `false` is used. + */ + export function watch( + filename: PathLike, + options: { encoding: "buffer", persistent?: boolean, recursive?: boolean; } | "buffer", + listener?: (event: "rename" | "change", filename: Buffer) => void + ): FSWatcher; + + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `persistent` is not supplied, the default of `true` is used. + * If `recursive` is not supplied, the default of `false` is used. + */ + export function watch( + filename: PathLike, + options: { encoding?: BufferEncoding | null, persistent?: boolean, recursive?: boolean } | string | null, + listener?: (event: "rename" | "change", filename: string | Buffer) => void, + ): FSWatcher; + + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function watch(filename: PathLike, listener?: (event: "rename" | "change", filename: string) => any): FSWatcher; + + /** + * Asynchronously tests whether or not the given path exists by checking with the file system. + * @deprecated since v1.0.0 Use `fs.stat()` or `fs.access()` instead + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function exists(path: PathLike, callback: (exists: boolean) => void): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace exists { + /** + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(path: PathLike): Promise; + } + + /** + * Synchronously tests whether or not the given path exists by checking with the file system. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function existsSync(path: PathLike): boolean; + + export namespace constants { + // File Access Constants + + /** Constant for fs.access(). File is visible to the calling process. */ + const F_OK: number; + + /** Constant for fs.access(). File can be read by the calling process. */ + const R_OK: number; + + /** Constant for fs.access(). File can be written by the calling process. */ + const W_OK: number; + + /** Constant for fs.access(). File can be executed by the calling process. */ + const X_OK: number; + + // File Copy Constants + + /** Constant for fs.copyFile. Flag indicating the destination file should not be overwritten if it already exists. */ + const COPYFILE_EXCL: number; + + /** + * Constant for fs.copyFile. copy operation will attempt to create a copy-on-write reflink. + * If the underlying platform does not support copy-on-write, then a fallback copy mechanism is used. + */ + const COPYFILE_FICLONE: number; + + /** + * Constant for fs.copyFile. Copy operation will attempt to create a copy-on-write reflink. + * If the underlying platform does not support copy-on-write, then the operation will fail with an error. + */ + const COPYFILE_FICLONE_FORCE: number; + + // File Open Constants + + /** Constant for fs.open(). Flag indicating to open a file for read-only access. */ + const O_RDONLY: number; + + /** Constant for fs.open(). Flag indicating to open a file for write-only access. */ + const O_WRONLY: number; + + /** Constant for fs.open(). Flag indicating to open a file for read-write access. */ + const O_RDWR: number; + + /** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ + const O_CREAT: number; + + /** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ + const O_EXCL: number; + + /** + * Constant for fs.open(). Flag indicating that if path identifies a terminal device, + * opening the path shall not cause that terminal to become the controlling terminal for the process + * (if the process does not already have one). + */ + const O_NOCTTY: number; + + /** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ + const O_TRUNC: number; + + /** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ + const O_APPEND: number; + + /** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ + const O_DIRECTORY: number; + + /** + * constant for fs.open(). + * Flag indicating reading accesses to the file system will no longer result in + * an update to the atime information associated with the file. + * This flag is available on Linux operating systems only. + */ + const O_NOATIME: number; + + /** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ + const O_NOFOLLOW: number; + + /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ + const O_SYNC: number; + + /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ + const O_DSYNC: number; + + /** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ + const O_SYMLINK: number; + + /** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ + const O_DIRECT: number; + + /** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ + const O_NONBLOCK: number; + + // File Type Constants + + /** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ + const S_IFMT: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ + const S_IFREG: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ + const S_IFDIR: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ + const S_IFCHR: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ + const S_IFBLK: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ + const S_IFIFO: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ + const S_IFLNK: number; + + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ + const S_IFSOCK: number; + + // File Mode Constants + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ + const S_IRWXU: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ + const S_IRUSR: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ + const S_IWUSR: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ + const S_IXUSR: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ + const S_IRWXG: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ + const S_IRGRP: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ + const S_IWGRP: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ + const S_IXGRP: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ + const S_IRWXO: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ + const S_IROTH: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ + const S_IWOTH: number; + + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ + const S_IXOTH: number; + + /** + * When set, a memory file mapping is used to access the file. This flag + * is available on Windows operating systems only. On other operating systems, + * this flag is ignored. + */ + const UV_FS_O_FILEMAP: number; + } + + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function access(path: PathLike, mode: number | undefined, callback: NoParamCallback): void; + + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function access(path: PathLike, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace access { + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(path: PathLike, mode?: number): Promise; + } + + /** + * Synchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function accessSync(path: PathLike, mode?: number): void; + + /** + * Returns a new `ReadStream` object. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function createReadStream(path: PathLike, options?: string | { + flags?: string; + encoding?: BufferEncoding; + fd?: number; + mode?: number; + autoClose?: boolean; + /** + * @default false + */ + emitClose?: boolean; + start?: number; + end?: number; + highWaterMark?: number; + }): ReadStream; + + /** + * Returns a new `WriteStream` object. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + export function createWriteStream(path: PathLike, options?: string | { + flags?: string; + encoding?: BufferEncoding; + fd?: number; + mode?: number; + autoClose?: boolean; + emitClose?: boolean; + start?: number; + highWaterMark?: number; + }): WriteStream; + + /** + * Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device. + * @param fd A file descriptor. + */ + export function fdatasync(fd: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace fdatasync { + /** + * Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise; + } + + /** + * Synchronous fdatasync(2) - synchronize a file's in-core state with storage device. + * @param fd A file descriptor. + */ + export function fdatasyncSync(fd: number): void; + + /** + * Asynchronously copies src to dest. By default, dest is overwritten if it already exists. + * No arguments other than a possible exception are given to the callback function. + * Node.js makes no guarantees about the atomicity of the copy operation. + * If an error occurs after the destination file has been opened for writing, Node.js will attempt + * to remove the destination. + * @param src A path to the source file. + * @param dest A path to the destination file. + */ + export function copyFile(src: PathLike, dest: PathLike, callback: NoParamCallback): void; + /** + * Asynchronously copies src to dest. By default, dest is overwritten if it already exists. + * No arguments other than a possible exception are given to the callback function. + * Node.js makes no guarantees about the atomicity of the copy operation. + * If an error occurs after the destination file has been opened for writing, Node.js will attempt + * to remove the destination. + * @param src A path to the source file. + * @param dest A path to the destination file. + * @param flags An integer that specifies the behavior of the copy operation. The only supported flag is fs.constants.COPYFILE_EXCL, which causes the copy operation to fail if dest already exists. + */ + export function copyFile(src: PathLike, dest: PathLike, flags: number, callback: NoParamCallback): void; + + // NOTE: This namespace provides design-time support for util.promisify. Exported members do not exist at runtime. + export namespace copyFile { + /** + * Asynchronously copies src to dest. By default, dest is overwritten if it already exists. + * No arguments other than a possible exception are given to the callback function. + * Node.js makes no guarantees about the atomicity of the copy operation. + * If an error occurs after the destination file has been opened for writing, Node.js will attempt + * to remove the destination. + * @param src A path to the source file. + * @param dest A path to the destination file. + * @param flags An optional integer that specifies the behavior of the copy operation. + * The only supported flag is fs.constants.COPYFILE_EXCL, + * which causes the copy operation to fail if dest already exists. + */ + function __promisify__(src: PathLike, dst: PathLike, flags?: number): Promise; + } + + /** + * Synchronously copies src to dest. By default, dest is overwritten if it already exists. + * Node.js makes no guarantees about the atomicity of the copy operation. + * If an error occurs after the destination file has been opened for writing, Node.js will attempt + * to remove the destination. + * @param src A path to the source file. + * @param dest A path to the destination file. + * @param flags An optional integer that specifies the behavior of the copy operation. + * The only supported flag is fs.constants.COPYFILE_EXCL, which causes the copy operation to fail if dest already exists. + */ + export function copyFileSync(src: PathLike, dest: PathLike, flags?: number): void; + + /** + * Write an array of ArrayBufferViews to the file specified by fd using writev(). + * position is the offset from the beginning of the file where this data should be written. + * It is unsafe to use fs.writev() multiple times on the same file without waiting for the callback. For this scenario, use fs.createWriteStream(). + * On Linux, positional writes don't work when the file is opened in append mode. + * The kernel ignores the position argument and always appends the data to the end of the file. + */ + export function writev( + fd: number, + buffers: ReadonlyArray, + cb: (err: NodeJS.ErrnoException | null, bytesWritten: number, buffers: NodeJS.ArrayBufferView[]) => void + ): void; + export function writev( + fd: number, + buffers: ReadonlyArray, + position: number, + cb: (err: NodeJS.ErrnoException | null, bytesWritten: number, buffers: NodeJS.ArrayBufferView[]) => void + ): void; + + export interface WriteVResult { + bytesWritten: number; + buffers: NodeJS.ArrayBufferView[]; + } + + export namespace writev { + function __promisify__(fd: number, buffers: ReadonlyArray, position?: number): Promise; + } + + /** + * See `writev`. + */ + export function writevSync(fd: number, buffers: ReadonlyArray, position?: number): number; + + export function readv( + fd: number, + buffers: ReadonlyArray, + cb: (err: NodeJS.ErrnoException | null, bytesRead: number, buffers: NodeJS.ArrayBufferView[]) => void + ): void; + export function readv( + fd: number, + buffers: ReadonlyArray, + position: number, + cb: (err: NodeJS.ErrnoException | null, bytesRead: number, buffers: NodeJS.ArrayBufferView[]) => void + ): void; + + export interface ReadVResult { + bytesRead: number; + buffers: NodeJS.ArrayBufferView[]; + } + + export namespace readv { + function __promisify__(fd: number, buffers: ReadonlyArray, position?: number): Promise; + } + + /** + * See `readv`. + */ + export function readvSync(fd: number, buffers: ReadonlyArray, position?: number): number; + + export interface OpenDirOptions { + encoding?: BufferEncoding; + /** + * Number of directory entries that are buffered + * internally when reading from the directory. Higher values lead to better + * performance but higher memory usage. + * @default 32 + */ + bufferSize?: number; + } + + export function opendirSync(path: string, options?: OpenDirOptions): Dir; + + export function opendir(path: string, cb: (err: NodeJS.ErrnoException | null, dir: Dir) => void): void; + export function opendir(path: string, options: OpenDirOptions, cb: (err: NodeJS.ErrnoException | null, dir: Dir) => void): void; + + export namespace opendir { + function __promisify__(path: string, options?: OpenDirOptions): Promise; + } + + export interface BigIntStats extends StatsBase { + } + + export class BigIntStats { + atimeNs: bigint; + mtimeNs: bigint; + ctimeNs: bigint; + birthtimeNs: bigint; + } + + export interface BigIntOptions { + bigint: true; + } + + export interface StatOptions { + bigint?: boolean; + } +} diff --git a/node_modules/@types/node/fs/promises.d.ts b/node_modules/@types/node/fs/promises.d.ts new file mode 100755 index 0000000..8d12c89 --- /dev/null +++ b/node_modules/@types/node/fs/promises.d.ts @@ -0,0 +1,561 @@ +declare module 'fs/promises' { + export * from 'node:fs/promises'; +} + +declare module 'node:fs/promises' { + import { + Stats, + BigIntStats, + StatOptions, + WriteVResult, + ReadVResult, + PathLike, + RmDirOptions, + RmOptions, + MakeDirectoryOptions, + Dirent, + OpenDirOptions, + Dir, + BaseEncodingOptions, + BufferEncodingOption, + OpenMode, + Mode, + } from 'node:fs'; + + interface FileHandle { + /** + * Gets the file descriptor for this file handle. + */ + readonly fd: number; + + /** + * Asynchronously append data to a file, creating the file if it does not exist. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for appending. + * @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + appendFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode, flag?: OpenMode } | BufferEncoding | null): Promise; + + /** + * Asynchronous fchown(2) - Change ownership of a file. + */ + chown(uid: number, gid: number): Promise; + + /** + * Asynchronous fchmod(2) - Change permissions of a file. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + chmod(mode: Mode): Promise; + + /** + * Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device. + */ + datasync(): Promise; + + /** + * Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + */ + sync(): Promise; + + /** + * Asynchronously reads data from the file. + * The `FileHandle` must have been opened for reading. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position. + */ + read(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesRead: number, buffer: TBuffer }>; + + /** + * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for reading. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + readFile(options?: { encoding?: null, flag?: OpenMode } | null): Promise; + + /** + * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for reading. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + readFile(options: { encoding: BufferEncoding, flag?: OpenMode } | BufferEncoding): Promise; + + /** + * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for reading. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + readFile(options?: BaseEncodingOptions & { flag?: OpenMode } | BufferEncoding | null): Promise; + + /** + * Asynchronous fstat(2) - Get file status. + */ + stat(opts?: StatOptions & { bigint?: false }): Promise; + stat(opts: StatOptions & { bigint: true }): Promise; + stat(opts?: StatOptions): Promise; + + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param len If not specified, defaults to `0`. + */ + truncate(len?: number): Promise; + + /** + * Asynchronously change file timestamps of the file. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + utimes(atime: string | number | Date, mtime: string | number | Date): Promise; + + /** + * Asynchronously writes `buffer` to the file. + * The `FileHandle` must have been opened for writing. + * @param buffer The buffer that the data will be written to. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + write(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>; + + /** + * Asynchronously writes `string` to the file. + * The `FileHandle` must have been opened for writing. + * It is unsafe to call `write()` multiple times on the same file without waiting for the `Promise` + * to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + write(data: string | Uint8Array, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>; + + /** + * Asynchronously writes data to a file, replacing the file if it already exists. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for writing. + * It is unsafe to call `writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected). + * @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + writeFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode, flag?: OpenMode } | BufferEncoding | null): Promise; + + /** + * See `fs.writev` promisified version. + */ + writev(buffers: ReadonlyArray, position?: number): Promise; + + /** + * See `fs.readv` promisified version. + */ + readv(buffers: ReadonlyArray, position?: number): Promise; + + /** + * Asynchronous close(2) - close a `FileHandle`. + */ + close(): Promise; + } + + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function access(path: PathLike, mode?: number): Promise; + + /** + * Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it already exists. + * Node.js makes no guarantees about the atomicity of the copy operation. + * If an error occurs after the destination file has been opened for writing, Node.js will attempt + * to remove the destination. + * @param src A path to the source file. + * @param dest A path to the destination file. + * @param flags An optional integer that specifies the behavior of the copy operation. The only + * supported flag is `fs.constants.COPYFILE_EXCL`, which causes the copy operation to fail if + * `dest` already exists. + */ + function copyFile(src: PathLike, dest: PathLike, flags?: number): Promise; + + /** + * Asynchronous open(2) - open and possibly create a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not + * supplied, defaults to `0o666`. + */ + function open(path: PathLike, flags: string | number, mode?: Mode): Promise; + + /** + * Asynchronously reads data from the file referenced by the supplied `FileHandle`. + * @param handle A `FileHandle`. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If + * `null`, data will be read from the current position. + */ + function read( + handle: FileHandle, + buffer: TBuffer, + offset?: number | null, + length?: number | null, + position?: number | null, + ): Promise<{ bytesRead: number, buffer: TBuffer }>; + + /** + * Asynchronously writes `buffer` to the file referenced by the supplied `FileHandle`. + * It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise` + * to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended. + * @param handle A `FileHandle`. + * @param buffer The buffer that the data will be written to. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function write( + handle: FileHandle, + buffer: TBuffer, + offset?: number | null, + length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>; + + /** + * Asynchronously writes `string` to the file referenced by the supplied `FileHandle`. + * It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise` + * to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended. + * @param handle A `FileHandle`. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + function write(handle: FileHandle, string: string, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>; + + /** + * Asynchronous rename(2) - Change the name or location of a file or directory. + * @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function rename(oldPath: PathLike, newPath: PathLike): Promise; + + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param len If not specified, defaults to `0`. + */ + function truncate(path: PathLike, len?: number): Promise; + + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param handle A `FileHandle`. + * @param len If not specified, defaults to `0`. + */ + function ftruncate(handle: FileHandle, len?: number): Promise; + + /** + * Asynchronous rmdir(2) - delete a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function rmdir(path: PathLike, options?: RmDirOptions): Promise; + + /** + * Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). + */ + function rm(path: PathLike, options?: RmOptions): Promise; + + /** + * Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device. + * @param handle A `FileHandle`. + */ + function fdatasync(handle: FileHandle): Promise; + + /** + * Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + * @param handle A `FileHandle`. + */ + function fsync(handle: FileHandle): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false; }) | null): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options?: Mode | MakeDirectoryOptions | null): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false } | BufferEncoding | null): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false } | BufferEncoding | null): Promise; + + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + function readdir(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }): Promise; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink(path: PathLike, options: BufferEncodingOption): Promise; + + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink(path: PathLike, options?: BaseEncodingOptions | string | null): Promise; + + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + * @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). + * When using `'junction'`, the `target` argument will automatically be normalized to an absolute path. + */ + function symlink(target: PathLike, path: PathLike, type?: string | null): Promise; + + /** + * Asynchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function lstat(path: PathLike, opts?: StatOptions & { bigint?: false }): Promise; + function lstat(path: PathLike, opts: StatOptions & { bigint: true }): Promise; + function lstat(path: PathLike, opts?: StatOptions): Promise; + + /** + * Asynchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function stat(path: PathLike, opts?: StatOptions & { bigint?: false }): Promise; + function stat(path: PathLike, opts: StatOptions & { bigint: true }): Promise; + function stat(path: PathLike, opts?: StatOptions): Promise; + + /** + * Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file. + * @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function link(existingPath: PathLike, newPath: PathLike): Promise; + + /** + * Asynchronous unlink(2) - delete a name and possibly the file it refers to. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function unlink(path: PathLike): Promise; + + /** + * Asynchronous fchmod(2) - Change permissions of a file. + * @param handle A `FileHandle`. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function fchmod(handle: FileHandle, mode: Mode): Promise; + + /** + * Asynchronous chmod(2) - Change permissions of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function chmod(path: PathLike, mode: Mode): Promise; + + /** + * Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function lchmod(path: PathLike, mode: Mode): Promise; + + /** + * Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function lchown(path: PathLike, uid: number, gid: number): Promise; + + /** + * Changes the access and modification times of a file in the same way as `fsPromises.utimes()`, + * with the difference that if the path refers to a symbolic link, then the link is not + * dereferenced: instead, the timestamps of the symbolic link itself are changed. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function lutimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise; + + /** + * Asynchronous fchown(2) - Change ownership of a file. + * @param handle A `FileHandle`. + */ + function fchown(handle: FileHandle, uid: number, gid: number): Promise; + + /** + * Asynchronous chown(2) - Change ownership of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function chown(path: PathLike, uid: number, gid: number): Promise; + + /** + * Asynchronously change file timestamps of the file referenced by the supplied path. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise; + + /** + * Asynchronously change file timestamps of the file referenced by the supplied `FileHandle`. + * @param handle A `FileHandle`. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function futimes(handle: FileHandle, atime: string | number | Date, mtime: string | number | Date): Promise; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath(path: PathLike, options: BufferEncodingOption): Promise; + + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp(prefix: string, options: BufferEncodingOption): Promise; + + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise; + + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * It is unsafe to call `fsPromises.writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected). + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + function writeFile(path: PathLike | FileHandle, data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode, flag?: OpenMode } | BufferEncoding | null): Promise; + + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + function appendFile(path: PathLike | FileHandle, data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode, flag?: OpenMode } | BufferEncoding | null): Promise; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile(path: PathLike | FileHandle, options?: { encoding?: null, flag?: OpenMode } | null): Promise; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile(path: PathLike | FileHandle, options: { encoding: BufferEncoding, flag?: OpenMode } | BufferEncoding): Promise; + + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile(path: PathLike | FileHandle, options?: BaseEncodingOptions & { flag?: OpenMode } | BufferEncoding | null): Promise; + + function opendir(path: string, options?: OpenDirOptions): Promise; +} diff --git a/node_modules/@types/node/globals.d.ts b/node_modules/@types/node/globals.d.ts new file mode 100755 index 0000000..4f78edd --- /dev/null +++ b/node_modules/@types/node/globals.d.ts @@ -0,0 +1,649 @@ +// Declare "static" methods in Error +interface ErrorConstructor { + /** Create .stack property on a target object */ + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: (err: Error, stackTraces: NodeJS.CallSite[]) => any; + + stackTraceLimit: number; +} + +// Node.js ESNEXT support +interface String { + /** Removes whitespace from the left end of a string. */ + trimLeft(): string; + /** Removes whitespace from the right end of a string. */ + trimRight(): string; + + /** Returns a copy with leading whitespace removed. */ + trimStart(): string; + /** Returns a copy with trailing whitespace removed. */ + trimEnd(): string; +} + +interface ImportMeta { + url: string; +} + +/*-----------------------------------------------* + * * + * GLOBAL * + * * + ------------------------------------------------*/ + +// For backwards compability +interface NodeRequire extends NodeJS.Require {} +interface RequireResolve extends NodeJS.RequireResolve {} +interface NodeModule extends NodeJS.Module {} + +declare var process: NodeJS.Process; +declare var console: Console; + +declare var __filename: string; +declare var __dirname: string; + +declare function setTimeout(callback: (...args: any[]) => void, ms?: number, ...args: any[]): NodeJS.Timeout; +declare namespace setTimeout { + function __promisify__(ms: number): Promise; + function __promisify__(ms: number, value: T): Promise; +} +declare function clearTimeout(timeoutId: NodeJS.Timeout): void; +declare function setInterval(callback: (...args: any[]) => void, ms?: number, ...args: any[]): NodeJS.Timeout; +declare function clearInterval(intervalId: NodeJS.Timeout): void; +declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): NodeJS.Immediate; +declare namespace setImmediate { + function __promisify__(): Promise; + function __promisify__(value: T): Promise; +} +declare function clearImmediate(immediateId: NodeJS.Immediate): void; + +declare function queueMicrotask(callback: () => void): void; + +declare var require: NodeRequire; +declare var module: NodeModule; + +// Same as module.exports +declare var exports: any; + +// Buffer class +type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex"; + +type WithImplicitCoercion = T | { valueOf(): T }; + +/** + * Raw data is stored in instances of the Buffer class. + * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. + * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + */ +declare class Buffer extends Uint8Array { + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + * @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead. + */ + constructor(str: string, encoding?: BufferEncoding); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`). + */ + constructor(size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. + */ + constructor(array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}/{SharedArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + * @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead. + */ + constructor(arrayBuffer: ArrayBuffer | SharedArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. + */ + constructor(array: ReadonlyArray); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + * @deprecated since v10.0.0 - Use `Buffer.from(buffer)` instead. + */ + constructor(buffer: Buffer); + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of any TypedArray or a new ArrayBuffer() + */ + static from(arrayBuffer: WithImplicitCoercion, byteOffset?: number, length?: number): Buffer; + /** + * Creates a new Buffer using the passed {data} + * @param data data to create a new Buffer + */ + static from(data: Uint8Array | ReadonlyArray): Buffer; + static from(data: WithImplicitCoercion | string>): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + */ + static from(str: WithImplicitCoercion | { [Symbol.toPrimitive](hint: 'string'): string }, encoding?: BufferEncoding): Buffer; + /** + * Creates a new Buffer using the passed {data} + * @param values to create a new Buffer + */ + static of(...items: number[]): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): encoding is BufferEncoding; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength( + string: string | NodeJS.ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + encoding?: BufferEncoding + ): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: ReadonlyArray, totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Uint8Array, buf2: Uint8Array): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initalizing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: BufferEncoding): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; + /** + * This is the number of bytes used to determine the size of pre-allocated, internal Buffer instances used for pooling. This value may be modified. + */ + static poolSize: number; + + write(string: string, encoding?: BufferEncoding): number; + write(string: string, offset: number, encoding?: BufferEncoding): number; + write(string: string, offset: number, length: number, encoding?: BufferEncoding): number; + toString(encoding?: BufferEncoding, start?: number, end?: number): string; + toJSON(): { type: 'Buffer'; data: number[] }; + equals(otherBuffer: Uint8Array): boolean; + compare( + otherBuffer: Uint8Array, + targetStart?: number, + targetEnd?: number, + sourceStart?: number, + sourceEnd?: number + ): number; + copy(targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + /** + * Returns a new `Buffer` that references **the same memory as the original**, but offset and cropped by the start and end indices. + * + * This method is incompatible with `Uint8Array#slice()`, which returns a copy of the original memory. + * + * @param begin Where the new `Buffer` will start. Default: `0`. + * @param end Where the new `Buffer` will end (not inclusive). Default: `buf.length`. + */ + slice(begin?: number, end?: number): Buffer; + /** + * Returns a new `Buffer` that references **the same memory as the original**, but offset and cropped by the start and end indices. + * + * This method is compatible with `Uint8Array#subarray()`. + * + * @param begin Where the new `Buffer` will start. Default: `0`. + * @param end Where the new `Buffer` will end (not inclusive). Default: `buf.length`. + */ + subarray(begin?: number, end?: number): Buffer; + writeBigInt64BE(value: bigint, offset?: number): number; + writeBigInt64LE(value: bigint, offset?: number): number; + writeBigUInt64BE(value: bigint, offset?: number): number; + writeBigUInt64LE(value: bigint, offset?: number): number; + writeUIntLE(value: number, offset: number, byteLength: number): number; + writeUIntBE(value: number, offset: number, byteLength: number): number; + writeIntLE(value: number, offset: number, byteLength: number): number; + writeIntBE(value: number, offset: number, byteLength: number): number; + readBigUInt64BE(offset?: number): bigint; + readBigUInt64LE(offset?: number): bigint; + readBigInt64BE(offset?: number): bigint; + readBigInt64LE(offset?: number): bigint; + readUIntLE(offset: number, byteLength: number): number; + readUIntBE(offset: number, byteLength: number): number; + readIntLE(offset: number, byteLength: number): number; + readIntBE(offset: number, byteLength: number): number; + readUInt8(offset?: number): number; + readUInt16LE(offset?: number): number; + readUInt16BE(offset?: number): number; + readUInt32LE(offset?: number): number; + readUInt32BE(offset?: number): number; + readInt8(offset?: number): number; + readInt16LE(offset?: number): number; + readInt16BE(offset?: number): number; + readInt32LE(offset?: number): number; + readInt32BE(offset?: number): number; + readFloatLE(offset?: number): number; + readFloatBE(offset?: number): number; + readDoubleLE(offset?: number): number; + readDoubleBE(offset?: number): number; + reverse(): this; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset?: number): number; + writeUInt16LE(value: number, offset?: number): number; + writeUInt16BE(value: number, offset?: number): number; + writeUInt32LE(value: number, offset?: number): number; + writeUInt32BE(value: number, offset?: number): number; + writeInt8(value: number, offset?: number): number; + writeInt16LE(value: number, offset?: number): number; + writeInt16BE(value: number, offset?: number): number; + writeInt32LE(value: number, offset?: number): number; + writeInt32BE(value: number, offset?: number): number; + writeFloatLE(value: number, offset?: number): number; + writeFloatBE(value: number, offset?: number): number; + writeDoubleLE(value: number, offset?: number): number; + writeDoubleBE(value: number, offset?: number): number; + + fill(value: string | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this; + + indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + entries(): IterableIterator<[number, number]>; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: BufferEncoding): boolean; + keys(): IterableIterator; + values(): IterableIterator; +} + +//#region borrowed +// from https://github.com/microsoft/TypeScript/blob/38da7c600c83e7b31193a62495239a0fe478cb67/lib/lib.webworker.d.ts#L633 until moved to separate lib +/** A controller object that allows you to abort one or more DOM requests as and when desired. */ +interface AbortController { + /** + * Returns the AbortSignal object associated with this object. + */ + readonly signal: AbortSignal; + /** + * Invoking this method will set this object's AbortSignal's aborted flag and signal to any observers that the associated activity is to be aborted. + */ + abort(): void; +} + +/** A signal object that allows you to communicate with a DOM request (such as a Fetch) and abort it if required via an AbortController object. */ +interface AbortSignal { + /** + * Returns true if this AbortSignal's AbortController has signaled to abort, and false otherwise. + */ + readonly aborted: boolean; +} + +declare var AbortController: { + prototype: AbortController; + new(): AbortController; +}; + +declare var AbortSignal: { + prototype: AbortSignal; + new(): AbortSignal; +}; +//#endregion borrowed + +/*----------------------------------------------* +* * +* GLOBAL INTERFACES * +* * +*-----------------------------------------------*/ +declare namespace NodeJS { + interface InspectOptions { + /** + * If set to `true`, getters are going to be + * inspected as well. If set to `'get'` only getters without setter are going + * to be inspected. If set to `'set'` only getters having a corresponding + * setter are going to be inspected. This might cause side effects depending on + * the getter function. + * @default `false` + */ + getters?: 'get' | 'set' | boolean; + showHidden?: boolean; + /** + * @default 2 + */ + depth?: number | null; + colors?: boolean; + customInspect?: boolean; + showProxy?: boolean; + maxArrayLength?: number | null; + /** + * Specifies the maximum number of characters to + * include when formatting. Set to `null` or `Infinity` to show all elements. + * Set to `0` or negative to show no characters. + * @default 10000 + */ + maxStringLength?: number | null; + breakLength?: number; + /** + * Setting this to `false` causes each object key + * to be displayed on a new line. It will also add new lines to text that is + * longer than `breakLength`. If set to a number, the most `n` inner elements + * are united on a single line as long as all properties fit into + * `breakLength`. Short array elements are also grouped together. Note that no + * text will be reduced below 16 characters, no matter the `breakLength` size. + * For more information, see the example below. + * @default `true` + */ + compact?: boolean | number; + sorted?: boolean | ((a: string, b: string) => number); + } + + interface CallSite { + /** + * Value of "this" + */ + getThis(): any; + + /** + * Type of "this" as a string. + * This is the name of the function stored in the constructor field of + * "this", if available. Otherwise the object's [[Class]] internal + * property. + */ + getTypeName(): string | null; + + /** + * Current function + */ + getFunction(): Function | undefined; + + /** + * Name of the current function, typically its name property. + * If a name property is not available an attempt will be made to try + * to infer a name from the function's context. + */ + getFunctionName(): string | null; + + /** + * Name of the property [of "this" or one of its prototypes] that holds + * the current function + */ + getMethodName(): string | null; + + /** + * Name of the script [if this function was defined in a script] + */ + getFileName(): string | null; + + /** + * Current line number [if this function was defined in a script] + */ + getLineNumber(): number | null; + + /** + * Current column number [if this function was defined in a script] + */ + getColumnNumber(): number | null; + + /** + * A call site object representing the location where eval was called + * [if this function was created using a call to eval] + */ + getEvalOrigin(): string | undefined; + + /** + * Is this a toplevel invocation, that is, is "this" the global object? + */ + isToplevel(): boolean; + + /** + * Does this call take place in code defined by a call to eval? + */ + isEval(): boolean; + + /** + * Is this call in native V8 code? + */ + isNative(): boolean; + + /** + * Is this a constructor call? + */ + isConstructor(): boolean; + } + + interface ErrnoException extends Error { + errno?: number; + code?: string; + path?: string; + syscall?: string; + stack?: string; + } + + interface ReadableStream extends EventEmitter { + readable: boolean; + read(size?: number): string | Buffer; + setEncoding(encoding: BufferEncoding): this; + pause(): this; + resume(): this; + isPaused(): boolean; + pipe(destination: T, options?: { end?: boolean; }): T; + unpipe(destination?: WritableStream): this; + unshift(chunk: string | Uint8Array, encoding?: BufferEncoding): void; + wrap(oldStream: ReadableStream): this; + [Symbol.asyncIterator](): AsyncIterableIterator; + } + + interface WritableStream extends EventEmitter { + writable: boolean; + write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean; + write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean; + end(cb?: () => void): void; + end(data: string | Uint8Array, cb?: () => void): void; + end(str: string, encoding?: BufferEncoding, cb?: () => void): void; + } + + interface ReadWriteStream extends ReadableStream, WritableStream { } + + interface Global { + AbortController: typeof AbortController; + AbortSignal: typeof AbortSignal; + Array: typeof Array; + ArrayBuffer: typeof ArrayBuffer; + Boolean: typeof Boolean; + Buffer: typeof Buffer; + DataView: typeof DataView; + Date: typeof Date; + Error: typeof Error; + EvalError: typeof EvalError; + Float32Array: typeof Float32Array; + Float64Array: typeof Float64Array; + Function: typeof Function; + Infinity: typeof Infinity; + Int16Array: typeof Int16Array; + Int32Array: typeof Int32Array; + Int8Array: typeof Int8Array; + Intl: typeof Intl; + JSON: typeof JSON; + Map: MapConstructor; + Math: typeof Math; + NaN: typeof NaN; + Number: typeof Number; + Object: typeof Object; + Promise: typeof Promise; + RangeError: typeof RangeError; + ReferenceError: typeof ReferenceError; + RegExp: typeof RegExp; + Set: SetConstructor; + String: typeof String; + Symbol: Function; + SyntaxError: typeof SyntaxError; + TypeError: typeof TypeError; + URIError: typeof URIError; + Uint16Array: typeof Uint16Array; + Uint32Array: typeof Uint32Array; + Uint8Array: typeof Uint8Array; + Uint8ClampedArray: typeof Uint8ClampedArray; + WeakMap: WeakMapConstructor; + WeakSet: WeakSetConstructor; + clearImmediate: (immediateId: Immediate) => void; + clearInterval: (intervalId: Timeout) => void; + clearTimeout: (timeoutId: Timeout) => void; + decodeURI: typeof decodeURI; + decodeURIComponent: typeof decodeURIComponent; + encodeURI: typeof encodeURI; + encodeURIComponent: typeof encodeURIComponent; + escape: (str: string) => string; + eval: typeof eval; + global: Global; + isFinite: typeof isFinite; + isNaN: typeof isNaN; + parseFloat: typeof parseFloat; + parseInt: typeof parseInt; + setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => Immediate; + setInterval: (callback: (...args: any[]) => void, ms?: number, ...args: any[]) => Timeout; + setTimeout: (callback: (...args: any[]) => void, ms?: number, ...args: any[]) => Timeout; + queueMicrotask: typeof queueMicrotask; + undefined: typeof undefined; + unescape: (str: string) => string; + gc: () => void; + v8debug?: any; + } + + interface RefCounted { + ref(): this; + unref(): this; + } + + // compatibility with older typings + interface Timer extends RefCounted { + hasRef(): boolean; + refresh(): this; + [Symbol.toPrimitive](): number; + } + + interface Immediate extends RefCounted { + hasRef(): boolean; + _onImmediate: Function; // to distinguish it from the Timeout class + } + + interface Timeout extends Timer { + hasRef(): boolean; + refresh(): this; + [Symbol.toPrimitive](): number; + } + + type TypedArray = + | Uint8Array + | Uint8ClampedArray + | Uint16Array + | Uint32Array + | Int8Array + | Int16Array + | Int32Array + | BigUint64Array + | BigInt64Array + | Float32Array + | Float64Array; + type ArrayBufferView = TypedArray | DataView; + + interface Require { + (id: string): any; + resolve: RequireResolve; + cache: Dict; + /** + * @deprecated + */ + extensions: RequireExtensions; + main: Module | undefined; + } + + interface RequireResolve { + (id: string, options?: { paths?: string[]; }): string; + paths(request: string): string[] | null; + } + + interface RequireExtensions extends Dict<(m: Module, filename: string) => any> { + '.js': (m: Module, filename: string) => any; + '.json': (m: Module, filename: string) => any; + '.node': (m: Module, filename: string) => any; + } + interface Module { + exports: any; + require: Require; + id: string; + filename: string; + loaded: boolean; + /** @deprecated since 14.6.0 Please use `require.main` and `module.children` instead. */ + parent: Module | null | undefined; + children: Module[]; + /** + * @since 11.14.0 + * + * The directory name of the module. This is usually the same as the path.dirname() of the module.id. + */ + path: string; + paths: string[]; + } + + interface Dict { + [key: string]: T | undefined; + } + + interface ReadOnlyDict { + readonly [key: string]: T | undefined; + } +} diff --git a/node_modules/@types/node/globals.global.d.ts b/node_modules/@types/node/globals.global.d.ts new file mode 100755 index 0000000..d66acba --- /dev/null +++ b/node_modules/@types/node/globals.global.d.ts @@ -0,0 +1 @@ +declare var global: NodeJS.Global & typeof globalThis; diff --git a/node_modules/@types/node/http.d.ts b/node_modules/@types/node/http.d.ts new file mode 100755 index 0000000..615f2d9 --- /dev/null +++ b/node_modules/@types/node/http.d.ts @@ -0,0 +1,428 @@ +declare module 'node:http' { + export * from 'http'; +} + +declare module 'http' { + import * as stream from 'node:stream'; + import { URL } from 'node:url'; + import { Socket, Server as NetServer } from 'node:net'; + + // incoming headers will never contain number + interface IncomingHttpHeaders extends NodeJS.Dict { + 'accept'?: string; + 'accept-language'?: string; + 'accept-patch'?: string; + 'accept-ranges'?: string; + 'access-control-allow-credentials'?: string; + 'access-control-allow-headers'?: string; + 'access-control-allow-methods'?: string; + 'access-control-allow-origin'?: string; + 'access-control-expose-headers'?: string; + 'access-control-max-age'?: string; + 'access-control-request-headers'?: string; + 'access-control-request-method'?: string; + 'age'?: string; + 'allow'?: string; + 'alt-svc'?: string; + 'authorization'?: string; + 'cache-control'?: string; + 'connection'?: string; + 'content-disposition'?: string; + 'content-encoding'?: string; + 'content-language'?: string; + 'content-length'?: string; + 'content-location'?: string; + 'content-range'?: string; + 'content-type'?: string; + 'cookie'?: string; + 'date'?: string; + 'etag'?: string; + 'expect'?: string; + 'expires'?: string; + 'forwarded'?: string; + 'from'?: string; + 'host'?: string; + 'if-match'?: string; + 'if-modified-since'?: string; + 'if-none-match'?: string; + 'if-unmodified-since'?: string; + 'last-modified'?: string; + 'location'?: string; + 'origin'?: string; + 'pragma'?: string; + 'proxy-authenticate'?: string; + 'proxy-authorization'?: string; + 'public-key-pins'?: string; + 'range'?: string; + 'referer'?: string; + 'retry-after'?: string; + 'sec-websocket-accept'?: string; + 'sec-websocket-extensions'?: string; + 'sec-websocket-key'?: string; + 'sec-websocket-protocol'?: string; + 'sec-websocket-version'?: string; + 'set-cookie'?: string[]; + 'strict-transport-security'?: string; + 'tk'?: string; + 'trailer'?: string; + 'transfer-encoding'?: string; + 'upgrade'?: string; + 'user-agent'?: string; + 'vary'?: string; + 'via'?: string; + 'warning'?: string; + 'www-authenticate'?: string; + } + + // outgoing headers allows numbers (as they are converted internally to strings) + type OutgoingHttpHeader = number | string | string[]; + + interface OutgoingHttpHeaders extends NodeJS.Dict { + } + + interface ClientRequestArgs { + protocol?: string | null; + host?: string | null; + hostname?: string | null; + family?: number; + port?: number | string | null; + defaultPort?: number | string; + localAddress?: string; + socketPath?: string; + /** + * @default 8192 + */ + maxHeaderSize?: number; + method?: string; + path?: string | null; + headers?: OutgoingHttpHeaders; + auth?: string | null; + agent?: Agent | boolean; + _defaultAgent?: Agent; + timeout?: number; + setHost?: boolean; + // https://github.com/nodejs/node/blob/master/lib/_http_client.js#L278 + createConnection?: (options: ClientRequestArgs, oncreate: (err: Error, socket: Socket) => void) => Socket; + } + + interface ServerOptions { + IncomingMessage?: typeof IncomingMessage; + ServerResponse?: typeof ServerResponse; + /** + * Optionally overrides the value of + * [`--max-http-header-size`][] for requests received by this server, i.e. + * the maximum length of request headers in bytes. + * @default 8192 + */ + maxHeaderSize?: number; + /** + * Use an insecure HTTP parser that accepts invalid HTTP headers when true. + * Using the insecure parser should be avoided. + * See --insecure-http-parser for more information. + * @default false + */ + insecureHTTPParser?: boolean; + } + + type RequestListener = (req: IncomingMessage, res: ServerResponse) => void; + + interface HttpBase { + setTimeout(msecs?: number, callback?: () => void): this; + setTimeout(callback: () => void): this; + /** + * Limits maximum incoming headers count. If set to 0, no limit will be applied. + * @default 2000 + * {@link https://nodejs.org/api/http.html#http_server_maxheaderscount} + */ + maxHeadersCount: number | null; + timeout: number; + /** + * Limit the amount of time the parser will wait to receive the complete HTTP headers. + * @default 60000 + * {@link https://nodejs.org/api/http.html#http_server_headerstimeout} + */ + headersTimeout: number; + keepAliveTimeout: number; + /** + * Sets the timeout value in milliseconds for receiving the entire request from the client. + * @default 0 + * {@link https://nodejs.org/api/http.html#http_server_requesttimeout} + */ + requestTimeout: number; + } + + interface Server extends HttpBase {} + class Server extends NetServer { + constructor(requestListener?: RequestListener); + constructor(options: ServerOptions, requestListener?: RequestListener); + } + + // https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js + class OutgoingMessage extends stream.Writable { + upgrading: boolean; + chunkedEncoding: boolean; + shouldKeepAlive: boolean; + useChunkedEncodingByDefault: boolean; + sendDate: boolean; + /** + * @deprecated Use `writableEnded` instead. + */ + finished: boolean; + headersSent: boolean; + /** + * @deprecate Use `socket` instead. + */ + connection: Socket | null; + socket: Socket | null; + + constructor(); + + setTimeout(msecs: number, callback?: () => void): this; + setHeader(name: string, value: number | string | ReadonlyArray): void; + getHeader(name: string): number | string | string[] | undefined; + getHeaders(): OutgoingHttpHeaders; + getHeaderNames(): string[]; + hasHeader(name: string): boolean; + removeHeader(name: string): void; + addTrailers(headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>): void; + flushHeaders(): void; + } + + // https://github.com/nodejs/node/blob/master/lib/_http_server.js#L108-L256 + class ServerResponse extends OutgoingMessage { + statusCode: number; + statusMessage: string; + + constructor(req: IncomingMessage); + + assignSocket(socket: Socket): void; + detachSocket(socket: Socket): void; + // https://github.com/nodejs/node/blob/master/test/parallel/test-http-write-callbacks.js#L53 + // no args in writeContinue callback + writeContinue(callback?: () => void): void; + writeHead(statusCode: number, reasonPhrase?: string, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this; + writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this; + writeProcessing(): void; + } + + interface InformationEvent { + statusCode: number; + statusMessage: string; + httpVersion: string; + httpVersionMajor: number; + httpVersionMinor: number; + headers: IncomingHttpHeaders; + rawHeaders: string[]; + } + + // https://github.com/nodejs/node/blob/master/lib/_http_client.js#L77 + class ClientRequest extends OutgoingMessage { + aborted: boolean; + host: string; + protocol: string; + + constructor(url: string | URL | ClientRequestArgs, cb?: (res: IncomingMessage) => void); + + method: string; + path: string; + /** @deprecated since v14.1.0 Use `request.destroy()` instead. */ + abort(): void; + onSocket(socket: Socket): void; + setTimeout(timeout: number, callback?: () => void): this; + setNoDelay(noDelay?: boolean): void; + setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; + + addListener(event: 'abort', listener: () => void): this; + addListener(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + addListener(event: 'continue', listener: () => void): this; + addListener(event: 'information', listener: (info: InformationEvent) => void): this; + addListener(event: 'response', listener: (response: IncomingMessage) => void): this; + addListener(event: 'socket', listener: (socket: Socket) => void): this; + addListener(event: 'timeout', listener: () => void): this; + addListener(event: 'upgrade', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + addListener(event: 'close', listener: () => void): this; + addListener(event: 'drain', listener: () => void): this; + addListener(event: 'error', listener: (err: Error) => void): this; + addListener(event: 'finish', listener: () => void): this; + addListener(event: 'pipe', listener: (src: stream.Readable) => void): this; + addListener(event: 'unpipe', listener: (src: stream.Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + on(event: 'abort', listener: () => void): this; + on(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + on(event: 'continue', listener: () => void): this; + on(event: 'information', listener: (info: InformationEvent) => void): this; + on(event: 'response', listener: (response: IncomingMessage) => void): this; + on(event: 'socket', listener: (socket: Socket) => void): this; + on(event: 'timeout', listener: () => void): this; + on(event: 'upgrade', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + on(event: 'close', listener: () => void): this; + on(event: 'drain', listener: () => void): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'finish', listener: () => void): this; + on(event: 'pipe', listener: (src: stream.Readable) => void): this; + on(event: 'unpipe', listener: (src: stream.Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: 'abort', listener: () => void): this; + once(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + once(event: 'continue', listener: () => void): this; + once(event: 'information', listener: (info: InformationEvent) => void): this; + once(event: 'response', listener: (response: IncomingMessage) => void): this; + once(event: 'socket', listener: (socket: Socket) => void): this; + once(event: 'timeout', listener: () => void): this; + once(event: 'upgrade', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + once(event: 'close', listener: () => void): this; + once(event: 'drain', listener: () => void): this; + once(event: 'error', listener: (err: Error) => void): this; + once(event: 'finish', listener: () => void): this; + once(event: 'pipe', listener: (src: stream.Readable) => void): this; + once(event: 'unpipe', listener: (src: stream.Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: 'abort', listener: () => void): this; + prependListener(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + prependListener(event: 'continue', listener: () => void): this; + prependListener(event: 'information', listener: (info: InformationEvent) => void): this; + prependListener(event: 'response', listener: (response: IncomingMessage) => void): this; + prependListener(event: 'socket', listener: (socket: Socket) => void): this; + prependListener(event: 'timeout', listener: () => void): this; + prependListener(event: 'upgrade', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + prependListener(event: 'close', listener: () => void): this; + prependListener(event: 'drain', listener: () => void): this; + prependListener(event: 'error', listener: (err: Error) => void): this; + prependListener(event: 'finish', listener: () => void): this; + prependListener(event: 'pipe', listener: (src: stream.Readable) => void): this; + prependListener(event: 'unpipe', listener: (src: stream.Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: 'abort', listener: () => void): this; + prependOnceListener(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + prependOnceListener(event: 'continue', listener: () => void): this; + prependOnceListener(event: 'information', listener: (info: InformationEvent) => void): this; + prependOnceListener(event: 'response', listener: (response: IncomingMessage) => void): this; + prependOnceListener(event: 'socket', listener: (socket: Socket) => void): this; + prependOnceListener(event: 'timeout', listener: () => void): this; + prependOnceListener(event: 'upgrade', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this; + prependOnceListener(event: 'close', listener: () => void): this; + prependOnceListener(event: 'drain', listener: () => void): this; + prependOnceListener(event: 'error', listener: (err: Error) => void): this; + prependOnceListener(event: 'finish', listener: () => void): this; + prependOnceListener(event: 'pipe', listener: (src: stream.Readable) => void): this; + prependOnceListener(event: 'unpipe', listener: (src: stream.Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + class IncomingMessage extends stream.Readable { + constructor(socket: Socket); + + aborted: boolean; + httpVersion: string; + httpVersionMajor: number; + httpVersionMinor: number; + complete: boolean; + /** + * @deprecated since v13.0.0 - Use `socket` instead. + */ + connection: Socket; + socket: Socket; + headers: IncomingHttpHeaders; + rawHeaders: string[]; + trailers: NodeJS.Dict; + rawTrailers: string[]; + setTimeout(msecs: number, callback?: () => void): this; + /** + * Only valid for request obtained from http.Server. + */ + method?: string; + /** + * Only valid for request obtained from http.Server. + */ + url?: string; + /** + * Only valid for response obtained from http.ClientRequest. + */ + statusCode?: number; + /** + * Only valid for response obtained from http.ClientRequest. + */ + statusMessage?: string; + destroy(error?: Error): void; + } + + interface AgentOptions { + /** + * Keep sockets around in a pool to be used by other requests in the future. Default = false + */ + keepAlive?: boolean; + /** + * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. + * Only relevant if keepAlive is set to true. + */ + keepAliveMsecs?: number; + /** + * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity + */ + maxSockets?: number; + /** + * Maximum number of sockets allowed for all hosts in total. Each request will use a new socket until the maximum is reached. Default: Infinity. + */ + maxTotalSockets?: number; + /** + * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. + */ + maxFreeSockets?: number; + /** + * Socket timeout in milliseconds. This will set the timeout after the socket is connected. + */ + timeout?: number; + /** + * Scheduling strategy to apply when picking the next free socket to use. Default: 'fifo'. + */ + scheduling?: 'fifo' | 'lifo'; + } + + class Agent { + maxFreeSockets: number; + maxSockets: number; + maxTotalSockets: number; + readonly freeSockets: NodeJS.ReadOnlyDict; + readonly sockets: NodeJS.ReadOnlyDict; + readonly requests: NodeJS.ReadOnlyDict; + + constructor(opts?: AgentOptions); + + /** + * Destroy any sockets that are currently in use by the agent. + * It is usually not necessary to do this. However, if you are using an agent with KeepAlive enabled, + * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, + * sockets may hang open for quite a long time before the server terminates them. + */ + destroy(): void; + } + + const METHODS: string[]; + + const STATUS_CODES: { + [errorCode: number]: string | undefined; + [errorCode: string]: string | undefined; + }; + + function createServer(requestListener?: RequestListener): Server; + function createServer(options: ServerOptions, requestListener?: RequestListener): Server; + + // although RequestOptions are passed as ClientRequestArgs to ClientRequest directly, + // create interface RequestOptions would make the naming more clear to developers + interface RequestOptions extends ClientRequestArgs { } + function request(options: RequestOptions | string | URL, callback?: (res: IncomingMessage) => void): ClientRequest; + function request(url: string | URL, options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; + function get(options: RequestOptions | string | URL, callback?: (res: IncomingMessage) => void): ClientRequest; + function get(url: string | URL, options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; + let globalAgent: Agent; + + /** + * Read-only property specifying the maximum allowed size of HTTP headers in bytes. + * Defaults to 16KB. Configurable using the [`--max-http-header-size`][] CLI option. + */ + const maxHeaderSize: number; +} diff --git a/node_modules/@types/node/http2.d.ts b/node_modules/@types/node/http2.d.ts new file mode 100755 index 0000000..214d6ff --- /dev/null +++ b/node_modules/@types/node/http2.d.ts @@ -0,0 +1,968 @@ +declare module 'node:http2' { + export * from 'http2'; +} + +declare module 'http2' { + import EventEmitter = require('node:events'); + import * as fs from 'node:fs'; + import * as net from 'node:net'; + import * as stream from 'node:stream'; + import * as tls from 'node:tls'; + import * as url from 'node:url'; + + import { + IncomingHttpHeaders as Http1IncomingHttpHeaders, + OutgoingHttpHeaders, + IncomingMessage, + ServerResponse, + } from 'node:http'; + export { OutgoingHttpHeaders } from 'node:http'; + + export interface IncomingHttpStatusHeader { + ":status"?: number; + } + + export interface IncomingHttpHeaders extends Http1IncomingHttpHeaders { + ":path"?: string; + ":method"?: string; + ":authority"?: string; + ":scheme"?: string; + } + + // Http2Stream + + export interface StreamPriorityOptions { + exclusive?: boolean; + parent?: number; + weight?: number; + silent?: boolean; + } + + export interface StreamState { + localWindowSize?: number; + state?: number; + localClose?: number; + remoteClose?: number; + sumDependencyWeight?: number; + weight?: number; + } + + export interface ServerStreamResponseOptions { + endStream?: boolean; + waitForTrailers?: boolean; + } + + export interface StatOptions { + offset: number; + length: number; + } + + export interface ServerStreamFileResponseOptions { + statCheck?(stats: fs.Stats, headers: OutgoingHttpHeaders, statOptions: StatOptions): void | boolean; + waitForTrailers?: boolean; + offset?: number; + length?: number; + } + + export interface ServerStreamFileResponseOptionsWithError extends ServerStreamFileResponseOptions { + onError?(err: NodeJS.ErrnoException): void; + } + + export interface Http2Stream extends stream.Duplex { + readonly aborted: boolean; + readonly bufferSize: number; + readonly closed: boolean; + readonly destroyed: boolean; + /** + * Set the true if the END_STREAM flag was set in the request or response HEADERS frame received, + * indicating that no additional data should be received and the readable side of the Http2Stream will be closed. + */ + readonly endAfterHeaders: boolean; + readonly id?: number; + readonly pending: boolean; + readonly rstCode: number; + readonly sentHeaders: OutgoingHttpHeaders; + readonly sentInfoHeaders?: OutgoingHttpHeaders[]; + readonly sentTrailers?: OutgoingHttpHeaders; + readonly session: Http2Session; + readonly state: StreamState; + + close(code?: number, callback?: () => void): void; + priority(options: StreamPriorityOptions): void; + setTimeout(msecs: number, callback?: () => void): void; + sendTrailers(headers: OutgoingHttpHeaders): void; + + addListener(event: "aborted", listener: () => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: Buffer | string) => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this; + addListener(event: "pipe", listener: (src: stream.Readable) => void): this; + addListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + addListener(event: "streamClosed", listener: (code: number) => void): this; + addListener(event: "timeout", listener: () => void): this; + addListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this; + addListener(event: "wantTrailers", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "aborted"): boolean; + emit(event: "close"): boolean; + emit(event: "data", chunk: Buffer | string): boolean; + emit(event: "drain"): boolean; + emit(event: "end"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "frameError", frameType: number, errorCode: number): boolean; + emit(event: "pipe", src: stream.Readable): boolean; + emit(event: "unpipe", src: stream.Readable): boolean; + emit(event: "streamClosed", code: number): boolean; + emit(event: "timeout"): boolean; + emit(event: "trailers", trailers: IncomingHttpHeaders, flags: number): boolean; + emit(event: "wantTrailers"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "aborted", listener: () => void): this; + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: Buffer | string) => void): this; + on(event: "drain", listener: () => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "frameError", listener: (frameType: number, errorCode: number) => void): this; + on(event: "pipe", listener: (src: stream.Readable) => void): this; + on(event: "unpipe", listener: (src: stream.Readable) => void): this; + on(event: "streamClosed", listener: (code: number) => void): this; + on(event: "timeout", listener: () => void): this; + on(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this; + on(event: "wantTrailers", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "aborted", listener: () => void): this; + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: Buffer | string) => void): this; + once(event: "drain", listener: () => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "frameError", listener: (frameType: number, errorCode: number) => void): this; + once(event: "pipe", listener: (src: stream.Readable) => void): this; + once(event: "unpipe", listener: (src: stream.Readable) => void): this; + once(event: "streamClosed", listener: (code: number) => void): this; + once(event: "timeout", listener: () => void): this; + once(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this; + once(event: "wantTrailers", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "aborted", listener: () => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this; + prependListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependListener(event: "streamClosed", listener: (code: number) => void): this; + prependListener(event: "timeout", listener: () => void): this; + prependListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this; + prependListener(event: "wantTrailers", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "aborted", listener: () => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this; + prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: "streamClosed", listener: (code: number) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + prependOnceListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this; + prependOnceListener(event: "wantTrailers", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export interface ClientHttp2Stream extends Http2Stream { + addListener(event: "continue", listener: () => {}): this; + addListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + addListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this; + addListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "continue"): boolean; + emit(event: "headers", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean; + emit(event: "push", headers: IncomingHttpHeaders, flags: number): boolean; + emit(event: "response", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "continue", listener: () => {}): this; + on(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + on(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this; + on(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "continue", listener: () => {}): this; + once(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + once(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this; + once(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "continue", listener: () => {}): this; + prependListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this; + prependListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "continue", listener: () => {}): this; + prependOnceListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependOnceListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this; + prependOnceListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export interface ServerHttp2Stream extends Http2Stream { + readonly headersSent: boolean; + readonly pushAllowed: boolean; + additionalHeaders(headers: OutgoingHttpHeaders): void; + pushStream(headers: OutgoingHttpHeaders, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void; + pushStream(headers: OutgoingHttpHeaders, options?: StreamPriorityOptions, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void; + respond(headers?: OutgoingHttpHeaders, options?: ServerStreamResponseOptions): void; + respondWithFD(fd: number | fs.promises.FileHandle, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptions): void; + respondWithFile(path: string, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptionsWithError): void; + } + + // Http2Session + + export interface Settings { + headerTableSize?: number; + enablePush?: boolean; + initialWindowSize?: number; + maxFrameSize?: number; + maxConcurrentStreams?: number; + maxHeaderListSize?: number; + enableConnectProtocol?: boolean; + } + + export interface ClientSessionRequestOptions { + endStream?: boolean; + exclusive?: boolean; + parent?: number; + weight?: number; + waitForTrailers?: boolean; + } + + export interface SessionState { + effectiveLocalWindowSize?: number; + effectiveRecvDataLength?: number; + nextStreamID?: number; + localWindowSize?: number; + lastProcStreamID?: number; + remoteWindowSize?: number; + outboundQueueSize?: number; + deflateDynamicTableSize?: number; + inflateDynamicTableSize?: number; + } + + export interface Http2Session extends EventEmitter { + readonly alpnProtocol?: string; + readonly closed: boolean; + readonly connecting: boolean; + readonly destroyed: boolean; + readonly encrypted?: boolean; + readonly localSettings: Settings; + readonly originSet?: string[]; + readonly pendingSettingsAck: boolean; + readonly remoteSettings: Settings; + readonly socket: net.Socket | tls.TLSSocket; + readonly state: SessionState; + readonly type: number; + + close(callback?: () => void): void; + destroy(error?: Error, code?: number): void; + goaway(code?: number, lastStreamID?: number, opaqueData?: NodeJS.ArrayBufferView): void; + ping(callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean; + ping(payload: NodeJS.ArrayBufferView, callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean; + ref(): void; + setLocalWindowSize(windowSize: number): void; + setTimeout(msecs: number, callback?: () => void): void; + settings(settings: Settings): void; + unref(): void; + + addListener(event: "close", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this; + addListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this; + addListener(event: "localSettings", listener: (settings: Settings) => void): this; + addListener(event: "ping", listener: () => void): this; + addListener(event: "remoteSettings", listener: (settings: Settings) => void): this; + addListener(event: "timeout", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "close"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "frameError", frameType: number, errorCode: number, streamID: number): boolean; + emit(event: "goaway", errorCode: number, lastStreamID: number, opaqueData: Buffer): boolean; + emit(event: "localSettings", settings: Settings): boolean; + emit(event: "ping"): boolean; + emit(event: "remoteSettings", settings: Settings): boolean; + emit(event: "timeout"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "close", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this; + on(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this; + on(event: "localSettings", listener: (settings: Settings) => void): this; + on(event: "ping", listener: () => void): this; + on(event: "remoteSettings", listener: (settings: Settings) => void): this; + on(event: "timeout", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this; + once(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this; + once(event: "localSettings", listener: (settings: Settings) => void): this; + once(event: "ping", listener: () => void): this; + once(event: "remoteSettings", listener: (settings: Settings) => void): this; + once(event: "timeout", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this; + prependListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this; + prependListener(event: "localSettings", listener: (settings: Settings) => void): this; + prependListener(event: "ping", listener: () => void): this; + prependListener(event: "remoteSettings", listener: (settings: Settings) => void): this; + prependListener(event: "timeout", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this; + prependOnceListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this; + prependOnceListener(event: "localSettings", listener: (settings: Settings) => void): this; + prependOnceListener(event: "ping", listener: () => void): this; + prependOnceListener(event: "remoteSettings", listener: (settings: Settings) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export interface ClientHttp2Session extends Http2Session { + request(headers?: OutgoingHttpHeaders, options?: ClientSessionRequestOptions): ClientHttp2Stream; + + addListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this; + addListener(event: "origin", listener: (origins: string[]) => void): this; + addListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + addListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "altsvc", alt: string, origin: string, stream: number): boolean; + emit(event: "origin", origins: ReadonlyArray): boolean; + emit(event: "connect", session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket): boolean; + emit(event: "stream", stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this; + on(event: "origin", listener: (origins: string[]) => void): this; + on(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + on(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this; + once(event: "origin", listener: (origins: string[]) => void): this; + once(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + once(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this; + prependListener(event: "origin", listener: (origins: string[]) => void): this; + prependListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + prependListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this; + prependOnceListener(event: "origin", listener: (origins: string[]) => void): this; + prependOnceListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + prependOnceListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export interface AlternativeServiceOptions { + origin: number | string | url.URL; + } + + export interface ServerHttp2Session extends Http2Session { + readonly server: Http2Server | Http2SecureServer; + + altsvc(alt: string, originOrStream: number | string | url.URL | AlternativeServiceOptions): void; + origin(...args: Array): void; + + addListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "connect", session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket): boolean; + emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this; + prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + // Http2Server + + export interface SessionOptions { + maxDeflateDynamicTableSize?: number; + maxSessionMemory?: number; + maxHeaderListPairs?: number; + maxOutstandingPings?: number; + maxSendHeaderBlockLength?: number; + paddingStrategy?: number; + peerMaxConcurrentStreams?: number; + settings?: Settings; + + selectPadding?(frameLen: number, maxFrameLen: number): number; + createConnection?(authority: url.URL, option: SessionOptions): stream.Duplex; + } + + export interface ClientSessionOptions extends SessionOptions { + maxReservedRemoteStreams?: number; + createConnection?: (authority: url.URL, option: SessionOptions) => stream.Duplex; + protocol?: 'http:' | 'https:'; + } + + export interface ServerSessionOptions extends SessionOptions { + Http1IncomingMessage?: typeof IncomingMessage; + Http1ServerResponse?: typeof ServerResponse; + Http2ServerRequest?: typeof Http2ServerRequest; + Http2ServerResponse?: typeof Http2ServerResponse; + } + + export interface SecureClientSessionOptions extends ClientSessionOptions, tls.ConnectionOptions { } + export interface SecureServerSessionOptions extends ServerSessionOptions, tls.TlsOptions { } + + export interface ServerOptions extends ServerSessionOptions { } + + export interface SecureServerOptions extends SecureServerSessionOptions { + allowHTTP1?: boolean; + origins?: string[]; + } + + export interface Http2Server extends net.Server { + addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + addListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + addListener(event: "sessionError", listener: (err: Error) => void): this; + addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + addListener(event: "timeout", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean; + emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean; + emit(event: "session", session: ServerHttp2Session): boolean; + emit(event: "sessionError", err: Error): boolean; + emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean; + emit(event: "timeout"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + on(event: "session", listener: (session: ServerHttp2Session) => void): this; + on(event: "sessionError", listener: (err: Error) => void): this; + on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + on(event: "timeout", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + once(event: "session", listener: (session: ServerHttp2Session) => void): this; + once(event: "sessionError", listener: (err: Error) => void): this; + once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + once(event: "timeout", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + prependListener(event: "sessionError", listener: (err: Error) => void): this; + prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependListener(event: "timeout", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + prependOnceListener(event: "sessionError", listener: (err: Error) => void): this; + prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + setTimeout(msec?: number, callback?: () => void): this; + } + + export interface Http2SecureServer extends tls.Server { + addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + addListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + addListener(event: "sessionError", listener: (err: Error) => void): this; + addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + addListener(event: "timeout", listener: () => void): this; + addListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean; + emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean; + emit(event: "session", session: ServerHttp2Session): boolean; + emit(event: "sessionError", err: Error): boolean; + emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean; + emit(event: "timeout"): boolean; + emit(event: "unknownProtocol", socket: tls.TLSSocket): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + on(event: "session", listener: (session: ServerHttp2Session) => void): this; + on(event: "sessionError", listener: (err: Error) => void): this; + on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + on(event: "timeout", listener: () => void): this; + on(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + once(event: "session", listener: (session: ServerHttp2Session) => void): this; + once(event: "sessionError", listener: (err: Error) => void): this; + once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + once(event: "timeout", listener: () => void): this; + once(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + prependListener(event: "sessionError", listener: (err: Error) => void): this; + prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependListener(event: "timeout", listener: () => void): this; + prependListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this; + prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this; + prependOnceListener(event: "sessionError", listener: (err: Error) => void): this; + prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + prependOnceListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + setTimeout(msec?: number, callback?: () => void): this; + } + + export class Http2ServerRequest extends stream.Readable { + constructor(stream: ServerHttp2Stream, headers: IncomingHttpHeaders, options: stream.ReadableOptions, rawHeaders: ReadonlyArray); + + readonly aborted: boolean; + readonly authority: string; + readonly connection: net.Socket | tls.TLSSocket; + readonly complete: boolean; + readonly headers: IncomingHttpHeaders; + readonly httpVersion: string; + readonly httpVersionMinor: number; + readonly httpVersionMajor: number; + readonly method: string; + readonly rawHeaders: string[]; + readonly rawTrailers: string[]; + readonly scheme: string; + readonly socket: net.Socket | tls.TLSSocket; + readonly stream: ServerHttp2Stream; + readonly trailers: IncomingHttpHeaders; + readonly url: string; + + setTimeout(msecs: number, callback?: () => void): void; + read(size?: number): Buffer | string | null; + + addListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: Buffer | string) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "aborted", hadError: boolean, code: number): boolean; + emit(event: "close"): boolean; + emit(event: "data", chunk: Buffer | string): boolean; + emit(event: "end"): boolean; + emit(event: "readable"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "aborted", listener: (hadError: boolean, code: number) => void): this; + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: Buffer | string) => void): this; + on(event: "end", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "aborted", listener: (hadError: boolean, code: number) => void): this; + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: Buffer | string) => void): this; + once(event: "end", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + export class Http2ServerResponse extends stream.Writable { + constructor(stream: ServerHttp2Stream); + + readonly connection: net.Socket | tls.TLSSocket; + readonly finished: boolean; + readonly headersSent: boolean; + readonly socket: net.Socket | tls.TLSSocket; + readonly stream: ServerHttp2Stream; + sendDate: boolean; + statusCode: number; + statusMessage: ''; + addTrailers(trailers: OutgoingHttpHeaders): void; + end(callback?: () => void): void; + end(data: string | Uint8Array, callback?: () => void): void; + end(data: string | Uint8Array, encoding: BufferEncoding, callback?: () => void): void; + getHeader(name: string): string; + getHeaderNames(): string[]; + getHeaders(): OutgoingHttpHeaders; + hasHeader(name: string): boolean; + removeHeader(name: string): void; + setHeader(name: string, value: number | string | ReadonlyArray): void; + setTimeout(msecs: number, callback?: () => void): void; + write(chunk: string | Uint8Array, callback?: (err: Error) => void): boolean; + write(chunk: string | Uint8Array, encoding: BufferEncoding, callback?: (err: Error) => void): boolean; + writeContinue(): void; + writeHead(statusCode: number, headers?: OutgoingHttpHeaders): this; + writeHead(statusCode: number, statusMessage: string, headers?: OutgoingHttpHeaders): this; + createPushResponse(headers: OutgoingHttpHeaders, callback: (err: Error | null, res: Http2ServerResponse) => void): void; + + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "pipe", listener: (src: stream.Readable) => void): this; + addListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "close"): boolean; + emit(event: "drain"): boolean; + emit(event: "error", error: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "pipe", src: stream.Readable): boolean; + emit(event: "unpipe", src: stream.Readable): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "pipe", listener: (src: stream.Readable) => void): this; + on(event: "unpipe", listener: (src: stream.Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "pipe", listener: (src: stream.Readable) => void): this; + once(event: "unpipe", listener: (src: stream.Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + // Public API + + export namespace constants { + const NGHTTP2_SESSION_SERVER: number; + const NGHTTP2_SESSION_CLIENT: number; + const NGHTTP2_STREAM_STATE_IDLE: number; + const NGHTTP2_STREAM_STATE_OPEN: number; + const NGHTTP2_STREAM_STATE_RESERVED_LOCAL: number; + const NGHTTP2_STREAM_STATE_RESERVED_REMOTE: number; + const NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: number; + const NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: number; + const NGHTTP2_STREAM_STATE_CLOSED: number; + const NGHTTP2_NO_ERROR: number; + const NGHTTP2_PROTOCOL_ERROR: number; + const NGHTTP2_INTERNAL_ERROR: number; + const NGHTTP2_FLOW_CONTROL_ERROR: number; + const NGHTTP2_SETTINGS_TIMEOUT: number; + const NGHTTP2_STREAM_CLOSED: number; + const NGHTTP2_FRAME_SIZE_ERROR: number; + const NGHTTP2_REFUSED_STREAM: number; + const NGHTTP2_CANCEL: number; + const NGHTTP2_COMPRESSION_ERROR: number; + const NGHTTP2_CONNECT_ERROR: number; + const NGHTTP2_ENHANCE_YOUR_CALM: number; + const NGHTTP2_INADEQUATE_SECURITY: number; + const NGHTTP2_HTTP_1_1_REQUIRED: number; + const NGHTTP2_ERR_FRAME_SIZE_ERROR: number; + const NGHTTP2_FLAG_NONE: number; + const NGHTTP2_FLAG_END_STREAM: number; + const NGHTTP2_FLAG_END_HEADERS: number; + const NGHTTP2_FLAG_ACK: number; + const NGHTTP2_FLAG_PADDED: number; + const NGHTTP2_FLAG_PRIORITY: number; + const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: number; + const DEFAULT_SETTINGS_ENABLE_PUSH: number; + const DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: number; + const DEFAULT_SETTINGS_MAX_FRAME_SIZE: number; + const MAX_MAX_FRAME_SIZE: number; + const MIN_MAX_FRAME_SIZE: number; + const MAX_INITIAL_WINDOW_SIZE: number; + const NGHTTP2_DEFAULT_WEIGHT: number; + const NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: number; + const NGHTTP2_SETTINGS_ENABLE_PUSH: number; + const NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: number; + const NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: number; + const NGHTTP2_SETTINGS_MAX_FRAME_SIZE: number; + const NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: number; + const PADDING_STRATEGY_NONE: number; + const PADDING_STRATEGY_MAX: number; + const PADDING_STRATEGY_CALLBACK: number; + const HTTP2_HEADER_STATUS: string; + const HTTP2_HEADER_METHOD: string; + const HTTP2_HEADER_AUTHORITY: string; + const HTTP2_HEADER_SCHEME: string; + const HTTP2_HEADER_PATH: string; + const HTTP2_HEADER_ACCEPT_CHARSET: string; + const HTTP2_HEADER_ACCEPT_ENCODING: string; + const HTTP2_HEADER_ACCEPT_LANGUAGE: string; + const HTTP2_HEADER_ACCEPT_RANGES: string; + const HTTP2_HEADER_ACCEPT: string; + const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: string; + const HTTP2_HEADER_AGE: string; + const HTTP2_HEADER_ALLOW: string; + const HTTP2_HEADER_AUTHORIZATION: string; + const HTTP2_HEADER_CACHE_CONTROL: string; + const HTTP2_HEADER_CONNECTION: string; + const HTTP2_HEADER_CONTENT_DISPOSITION: string; + const HTTP2_HEADER_CONTENT_ENCODING: string; + const HTTP2_HEADER_CONTENT_LANGUAGE: string; + const HTTP2_HEADER_CONTENT_LENGTH: string; + const HTTP2_HEADER_CONTENT_LOCATION: string; + const HTTP2_HEADER_CONTENT_MD5: string; + const HTTP2_HEADER_CONTENT_RANGE: string; + const HTTP2_HEADER_CONTENT_TYPE: string; + const HTTP2_HEADER_COOKIE: string; + const HTTP2_HEADER_DATE: string; + const HTTP2_HEADER_ETAG: string; + const HTTP2_HEADER_EXPECT: string; + const HTTP2_HEADER_EXPIRES: string; + const HTTP2_HEADER_FROM: string; + const HTTP2_HEADER_HOST: string; + const HTTP2_HEADER_IF_MATCH: string; + const HTTP2_HEADER_IF_MODIFIED_SINCE: string; + const HTTP2_HEADER_IF_NONE_MATCH: string; + const HTTP2_HEADER_IF_RANGE: string; + const HTTP2_HEADER_IF_UNMODIFIED_SINCE: string; + const HTTP2_HEADER_LAST_MODIFIED: string; + const HTTP2_HEADER_LINK: string; + const HTTP2_HEADER_LOCATION: string; + const HTTP2_HEADER_MAX_FORWARDS: string; + const HTTP2_HEADER_PREFER: string; + const HTTP2_HEADER_PROXY_AUTHENTICATE: string; + const HTTP2_HEADER_PROXY_AUTHORIZATION: string; + const HTTP2_HEADER_RANGE: string; + const HTTP2_HEADER_REFERER: string; + const HTTP2_HEADER_REFRESH: string; + const HTTP2_HEADER_RETRY_AFTER: string; + const HTTP2_HEADER_SERVER: string; + const HTTP2_HEADER_SET_COOKIE: string; + const HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: string; + const HTTP2_HEADER_TRANSFER_ENCODING: string; + const HTTP2_HEADER_TE: string; + const HTTP2_HEADER_UPGRADE: string; + const HTTP2_HEADER_USER_AGENT: string; + const HTTP2_HEADER_VARY: string; + const HTTP2_HEADER_VIA: string; + const HTTP2_HEADER_WWW_AUTHENTICATE: string; + const HTTP2_HEADER_HTTP2_SETTINGS: string; + const HTTP2_HEADER_KEEP_ALIVE: string; + const HTTP2_HEADER_PROXY_CONNECTION: string; + const HTTP2_METHOD_ACL: string; + const HTTP2_METHOD_BASELINE_CONTROL: string; + const HTTP2_METHOD_BIND: string; + const HTTP2_METHOD_CHECKIN: string; + const HTTP2_METHOD_CHECKOUT: string; + const HTTP2_METHOD_CONNECT: string; + const HTTP2_METHOD_COPY: string; + const HTTP2_METHOD_DELETE: string; + const HTTP2_METHOD_GET: string; + const HTTP2_METHOD_HEAD: string; + const HTTP2_METHOD_LABEL: string; + const HTTP2_METHOD_LINK: string; + const HTTP2_METHOD_LOCK: string; + const HTTP2_METHOD_MERGE: string; + const HTTP2_METHOD_MKACTIVITY: string; + const HTTP2_METHOD_MKCALENDAR: string; + const HTTP2_METHOD_MKCOL: string; + const HTTP2_METHOD_MKREDIRECTREF: string; + const HTTP2_METHOD_MKWORKSPACE: string; + const HTTP2_METHOD_MOVE: string; + const HTTP2_METHOD_OPTIONS: string; + const HTTP2_METHOD_ORDERPATCH: string; + const HTTP2_METHOD_PATCH: string; + const HTTP2_METHOD_POST: string; + const HTTP2_METHOD_PRI: string; + const HTTP2_METHOD_PROPFIND: string; + const HTTP2_METHOD_PROPPATCH: string; + const HTTP2_METHOD_PUT: string; + const HTTP2_METHOD_REBIND: string; + const HTTP2_METHOD_REPORT: string; + const HTTP2_METHOD_SEARCH: string; + const HTTP2_METHOD_TRACE: string; + const HTTP2_METHOD_UNBIND: string; + const HTTP2_METHOD_UNCHECKOUT: string; + const HTTP2_METHOD_UNLINK: string; + const HTTP2_METHOD_UNLOCK: string; + const HTTP2_METHOD_UPDATE: string; + const HTTP2_METHOD_UPDATEREDIRECTREF: string; + const HTTP2_METHOD_VERSION_CONTROL: string; + const HTTP_STATUS_CONTINUE: number; + const HTTP_STATUS_SWITCHING_PROTOCOLS: number; + const HTTP_STATUS_PROCESSING: number; + const HTTP_STATUS_OK: number; + const HTTP_STATUS_CREATED: number; + const HTTP_STATUS_ACCEPTED: number; + const HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: number; + const HTTP_STATUS_NO_CONTENT: number; + const HTTP_STATUS_RESET_CONTENT: number; + const HTTP_STATUS_PARTIAL_CONTENT: number; + const HTTP_STATUS_MULTI_STATUS: number; + const HTTP_STATUS_ALREADY_REPORTED: number; + const HTTP_STATUS_IM_USED: number; + const HTTP_STATUS_MULTIPLE_CHOICES: number; + const HTTP_STATUS_MOVED_PERMANENTLY: number; + const HTTP_STATUS_FOUND: number; + const HTTP_STATUS_SEE_OTHER: number; + const HTTP_STATUS_NOT_MODIFIED: number; + const HTTP_STATUS_USE_PROXY: number; + const HTTP_STATUS_TEMPORARY_REDIRECT: number; + const HTTP_STATUS_PERMANENT_REDIRECT: number; + const HTTP_STATUS_BAD_REQUEST: number; + const HTTP_STATUS_UNAUTHORIZED: number; + const HTTP_STATUS_PAYMENT_REQUIRED: number; + const HTTP_STATUS_FORBIDDEN: number; + const HTTP_STATUS_NOT_FOUND: number; + const HTTP_STATUS_METHOD_NOT_ALLOWED: number; + const HTTP_STATUS_NOT_ACCEPTABLE: number; + const HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: number; + const HTTP_STATUS_REQUEST_TIMEOUT: number; + const HTTP_STATUS_CONFLICT: number; + const HTTP_STATUS_GONE: number; + const HTTP_STATUS_LENGTH_REQUIRED: number; + const HTTP_STATUS_PRECONDITION_FAILED: number; + const HTTP_STATUS_PAYLOAD_TOO_LARGE: number; + const HTTP_STATUS_URI_TOO_LONG: number; + const HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: number; + const HTTP_STATUS_RANGE_NOT_SATISFIABLE: number; + const HTTP_STATUS_EXPECTATION_FAILED: number; + const HTTP_STATUS_TEAPOT: number; + const HTTP_STATUS_MISDIRECTED_REQUEST: number; + const HTTP_STATUS_UNPROCESSABLE_ENTITY: number; + const HTTP_STATUS_LOCKED: number; + const HTTP_STATUS_FAILED_DEPENDENCY: number; + const HTTP_STATUS_UNORDERED_COLLECTION: number; + const HTTP_STATUS_UPGRADE_REQUIRED: number; + const HTTP_STATUS_PRECONDITION_REQUIRED: number; + const HTTP_STATUS_TOO_MANY_REQUESTS: number; + const HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: number; + const HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: number; + const HTTP_STATUS_INTERNAL_SERVER_ERROR: number; + const HTTP_STATUS_NOT_IMPLEMENTED: number; + const HTTP_STATUS_BAD_GATEWAY: number; + const HTTP_STATUS_SERVICE_UNAVAILABLE: number; + const HTTP_STATUS_GATEWAY_TIMEOUT: number; + const HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: number; + const HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: number; + const HTTP_STATUS_INSUFFICIENT_STORAGE: number; + const HTTP_STATUS_LOOP_DETECTED: number; + const HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: number; + const HTTP_STATUS_NOT_EXTENDED: number; + const HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: number; + } + + /** + * This symbol can be set as a property on the HTTP/2 headers object with + * an array value in order to provide a list of headers considered sensitive. + */ + export const sensitiveHeaders: symbol; + + export function getDefaultSettings(): Settings; + export function getPackedSettings(settings: Settings): Buffer; + export function getUnpackedSettings(buf: Uint8Array): Settings; + + export function createServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server; + export function createServer(options: ServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server; + + export function createSecureServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer; + export function createSecureServer(options: SecureServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer; + + export function connect(authority: string | url.URL, listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): ClientHttp2Session; + export function connect( + authority: string | url.URL, + options?: ClientSessionOptions | SecureClientSessionOptions, + listener?: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void + ): ClientHttp2Session; +} diff --git a/node_modules/@types/node/https.d.ts b/node_modules/@types/node/https.d.ts new file mode 100755 index 0000000..87f352d --- /dev/null +++ b/node_modules/@types/node/https.d.ts @@ -0,0 +1,40 @@ +declare module 'node:https' { + export * from 'https'; +} + +declare module 'https' { + import * as tls from 'node:tls'; + import * as http from 'node:http'; + import { URL } from 'node:url'; + + type ServerOptions = tls.SecureContextOptions & tls.TlsOptions & http.ServerOptions; + + type RequestOptions = http.RequestOptions & tls.SecureContextOptions & { + rejectUnauthorized?: boolean; // Defaults to true + servername?: string; // SNI TLS Extension + }; + + interface AgentOptions extends http.AgentOptions, tls.ConnectionOptions { + rejectUnauthorized?: boolean; + maxCachedSessions?: number; + } + + class Agent extends http.Agent { + constructor(options?: AgentOptions); + options: AgentOptions; + } + + interface Server extends http.HttpBase {} + class Server extends tls.Server { + constructor(requestListener?: http.RequestListener); + constructor(options: ServerOptions, requestListener?: http.RequestListener); + } + + function createServer(requestListener?: http.RequestListener): Server; + function createServer(options: ServerOptions, requestListener?: http.RequestListener): Server; + function request(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + function request(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + function get(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + function get(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + let globalAgent: Agent; +} diff --git a/node_modules/@types/node/index.d.ts b/node_modules/@types/node/index.d.ts new file mode 100755 index 0000000..948c558 --- /dev/null +++ b/node_modules/@types/node/index.d.ts @@ -0,0 +1,58 @@ +// Type definitions for non-npm package Node.js 15.0 +// Project: http://nodejs.org/ +// Definitions by: Microsoft TypeScript +// DefinitelyTyped +// Alberto Schiabel +// Alvis HT Tang +// Andrew Makarov +// Benjamin Toueg +// Chigozirim C. +// David Junger +// Deividas Bakanas +// Eugene Y. Q. Shen +// Hannes Magnusson +// Hoàng Văn Khải +// Huw +// Kelvin Jin +// Klaus Meinhardt +// Lishude +// Mariusz Wiktorczyk +// Mohsen Azimi +// Nicolas Even +// Nikita Galkin +// Parambir Singh +// Sebastian Silbermann +// Simon Schick +// Thomas den Hollander +// Wilco Bakker +// wwwy3y3 +// Samuel Ainsworth +// Kyle Uehlein +// Thanik Bhongbhibhat +// Marcin Kopacz +// Trivikram Kamat +// Minh Son Nguyen +// Junxiao Shi +// Ilia Baryshnikov +// ExE Boss +// Surasak Chaisurin +// Piotr Błażejewicz +// Anna Henningsen +// Jason Kwok +// Victor Perin +// Yongsheng Zhang +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// NOTE: These definitions support NodeJS and TypeScript 3.7. +// Typically type modifications should be made in base.d.ts instead of here + +/// + +// NOTE: TypeScript version-specific augmentations can be found in the following paths: +// - ~/base.d.ts - Shared definitions common to all TypeScript versions +// - ~/index.d.ts - Definitions specific to TypeScript 2.8 +// - ~/ts3.5/index.d.ts - Definitions specific to TypeScript 3.5 + +// NOTE: Augmentations for TypeScript 3.5 and later should use individual files for overrides +// within the respective ~/ts3.5 (or later) folder. However, this is disallowed for versions +// prior to TypeScript 3.5, so the older definitions will be found here. diff --git a/node_modules/@types/node/inspector.d.ts b/node_modules/@types/node/inspector.d.ts new file mode 100755 index 0000000..ee0e2e7 --- /dev/null +++ b/node_modules/@types/node/inspector.d.ts @@ -0,0 +1,3048 @@ +// tslint:disable-next-line:dt-header +// Type definitions for inspector + +// These definitions are auto-generated. +// Please see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/19330 +// for more information. + +// tslint:disable:max-line-length + +/** + * The inspector module provides an API for interacting with the V8 inspector. + */ +declare module 'node:inspector' { + export * from 'inspector'; +} + +/** + * The inspector module provides an API for interacting with the V8 inspector. + */ +declare module 'inspector' { + import EventEmitter = require('node:events'); + + interface InspectorNotification { + method: string; + params: T; + } + + namespace Schema { + /** + * Description of the protocol domain. + */ + interface Domain { + /** + * Domain name. + */ + name: string; + /** + * Domain version. + */ + version: string; + } + + interface GetDomainsReturnType { + /** + * List of supported domains. + */ + domains: Domain[]; + } + } + + namespace Runtime { + /** + * Unique script identifier. + */ + type ScriptId = string; + + /** + * Unique object identifier. + */ + type RemoteObjectId = string; + + /** + * Primitive value which cannot be JSON-stringified. + */ + type UnserializableValue = string; + + /** + * Mirror object referencing original JavaScript object. + */ + interface RemoteObject { + /** + * Object type. + */ + type: string; + /** + * Object subtype hint. Specified for object type values only. + */ + subtype?: string; + /** + * Object class (constructor) name. Specified for object type values only. + */ + className?: string; + /** + * Remote object value in case of primitive values or JSON values (if it was requested). + */ + value?: any; + /** + * Primitive value which can not be JSON-stringified does not have value, but gets this property. + */ + unserializableValue?: UnserializableValue; + /** + * String representation of the object. + */ + description?: string; + /** + * Unique object identifier (for non-primitive values). + */ + objectId?: RemoteObjectId; + /** + * Preview containing abbreviated property values. Specified for object type values only. + * @experimental + */ + preview?: ObjectPreview; + /** + * @experimental + */ + customPreview?: CustomPreview; + } + + /** + * @experimental + */ + interface CustomPreview { + header: string; + hasBody: boolean; + formatterObjectId: RemoteObjectId; + bindRemoteObjectFunctionId: RemoteObjectId; + configObjectId?: RemoteObjectId; + } + + /** + * Object containing abbreviated remote object value. + * @experimental + */ + interface ObjectPreview { + /** + * Object type. + */ + type: string; + /** + * Object subtype hint. Specified for object type values only. + */ + subtype?: string; + /** + * String representation of the object. + */ + description?: string; + /** + * True iff some of the properties or entries of the original object did not fit. + */ + overflow: boolean; + /** + * List of the properties. + */ + properties: PropertyPreview[]; + /** + * List of the entries. Specified for map and set subtype values only. + */ + entries?: EntryPreview[]; + } + + /** + * @experimental + */ + interface PropertyPreview { + /** + * Property name. + */ + name: string; + /** + * Object type. Accessor means that the property itself is an accessor property. + */ + type: string; + /** + * User-friendly property value string. + */ + value?: string; + /** + * Nested value preview. + */ + valuePreview?: ObjectPreview; + /** + * Object subtype hint. Specified for object type values only. + */ + subtype?: string; + } + + /** + * @experimental + */ + interface EntryPreview { + /** + * Preview of the key. Specified for map-like collection entries. + */ + key?: ObjectPreview; + /** + * Preview of the value. + */ + value: ObjectPreview; + } + + /** + * Object property descriptor. + */ + interface PropertyDescriptor { + /** + * Property name or symbol description. + */ + name: string; + /** + * The value associated with the property. + */ + value?: RemoteObject; + /** + * True if the value associated with the property may be changed (data descriptors only). + */ + writable?: boolean; + /** + * A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only). + */ + get?: RemoteObject; + /** + * A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only). + */ + set?: RemoteObject; + /** + * True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. + */ + configurable: boolean; + /** + * True if this property shows up during enumeration of the properties on the corresponding object. + */ + enumerable: boolean; + /** + * True if the result was thrown during the evaluation. + */ + wasThrown?: boolean; + /** + * True if the property is owned for the object. + */ + isOwn?: boolean; + /** + * Property symbol object, if the property is of the symbol type. + */ + symbol?: RemoteObject; + } + + /** + * Object internal property descriptor. This property isn't normally visible in JavaScript code. + */ + interface InternalPropertyDescriptor { + /** + * Conventional property name. + */ + name: string; + /** + * The value associated with the property. + */ + value?: RemoteObject; + } + + /** + * Represents function call argument. Either remote object id objectId, primitive value, unserializable primitive value or neither of (for undefined) them should be specified. + */ + interface CallArgument { + /** + * Primitive value or serializable javascript object. + */ + value?: any; + /** + * Primitive value which can not be JSON-stringified. + */ + unserializableValue?: UnserializableValue; + /** + * Remote object handle. + */ + objectId?: RemoteObjectId; + } + + /** + * Id of an execution context. + */ + type ExecutionContextId = number; + + /** + * Description of an isolated world. + */ + interface ExecutionContextDescription { + /** + * Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed. + */ + id: ExecutionContextId; + /** + * Execution context origin. + */ + origin: string; + /** + * Human readable name describing given context. + */ + name: string; + /** + * Embedder-specific auxiliary data. + */ + auxData?: {}; + } + + /** + * Detailed information about exception (or error) that was thrown during script compilation or execution. + */ + interface ExceptionDetails { + /** + * Exception id. + */ + exceptionId: number; + /** + * Exception text, which should be used together with exception object when available. + */ + text: string; + /** + * Line number of the exception location (0-based). + */ + lineNumber: number; + /** + * Column number of the exception location (0-based). + */ + columnNumber: number; + /** + * Script ID of the exception location. + */ + scriptId?: ScriptId; + /** + * URL of the exception location, to be used when the script was not reported. + */ + url?: string; + /** + * JavaScript stack trace if available. + */ + stackTrace?: StackTrace; + /** + * Exception object if available. + */ + exception?: RemoteObject; + /** + * Identifier of the context where exception happened. + */ + executionContextId?: ExecutionContextId; + } + + /** + * Number of milliseconds since epoch. + */ + type Timestamp = number; + + /** + * Stack entry for runtime errors and assertions. + */ + interface CallFrame { + /** + * JavaScript function name. + */ + functionName: string; + /** + * JavaScript script id. + */ + scriptId: ScriptId; + /** + * JavaScript script name or url. + */ + url: string; + /** + * JavaScript script line number (0-based). + */ + lineNumber: number; + /** + * JavaScript script column number (0-based). + */ + columnNumber: number; + } + + /** + * Call frames for assertions or error messages. + */ + interface StackTrace { + /** + * String label of this stack trace. For async traces this may be a name of the function that initiated the async call. + */ + description?: string; + /** + * JavaScript function name. + */ + callFrames: CallFrame[]; + /** + * Asynchronous JavaScript stack trace that preceded this stack, if available. + */ + parent?: StackTrace; + /** + * Asynchronous JavaScript stack trace that preceded this stack, if available. + * @experimental + */ + parentId?: StackTraceId; + } + + /** + * Unique identifier of current debugger. + * @experimental + */ + type UniqueDebuggerId = string; + + /** + * If debuggerId is set stack trace comes from another debugger and can be resolved there. This allows to track cross-debugger calls. See Runtime.StackTrace and Debugger.paused for usages. + * @experimental + */ + interface StackTraceId { + id: string; + debuggerId?: UniqueDebuggerId; + } + + interface EvaluateParameterType { + /** + * Expression to evaluate. + */ + expression: string; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string; + /** + * Determines whether Command Line API should be available during the evaluation. + */ + includeCommandLineAPI?: boolean; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state. + */ + silent?: boolean; + /** + * Specifies in which execution context to perform evaluation. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + contextId?: ExecutionContextId; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean; + /** + * Whether execution should be treated as initiated by user in the UI. + */ + userGesture?: boolean; + /** + * Whether execution should await for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean; + } + + interface AwaitPromiseParameterType { + /** + * Identifier of the promise. + */ + promiseObjectId: RemoteObjectId; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean; + /** + * Whether preview should be generated for the result. + */ + generatePreview?: boolean; + } + + interface CallFunctionOnParameterType { + /** + * Declaration of the function to call. + */ + functionDeclaration: string; + /** + * Identifier of the object to call function on. Either objectId or executionContextId should be specified. + */ + objectId?: RemoteObjectId; + /** + * Call arguments. All call arguments must belong to the same JavaScript world as the target object. + */ + arguments?: CallArgument[]; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state. + */ + silent?: boolean; + /** + * Whether the result is expected to be a JSON object which should be sent by value. + */ + returnByValue?: boolean; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean; + /** + * Whether execution should be treated as initiated by user in the UI. + */ + userGesture?: boolean; + /** + * Whether execution should await for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean; + /** + * Specifies execution context which global object will be used to call function on. Either executionContextId or objectId should be specified. + */ + executionContextId?: ExecutionContextId; + /** + * Symbolic group name that can be used to release multiple objects. If objectGroup is not specified and objectId is, objectGroup will be inherited from object. + */ + objectGroup?: string; + } + + interface GetPropertiesParameterType { + /** + * Identifier of the object to return properties for. + */ + objectId: RemoteObjectId; + /** + * If true, returns properties belonging only to the element itself, not to its prototype chain. + */ + ownProperties?: boolean; + /** + * If true, returns accessor properties (with getter/setter) only; internal properties are not returned either. + * @experimental + */ + accessorPropertiesOnly?: boolean; + /** + * Whether preview should be generated for the results. + * @experimental + */ + generatePreview?: boolean; + } + + interface ReleaseObjectParameterType { + /** + * Identifier of the object to release. + */ + objectId: RemoteObjectId; + } + + interface ReleaseObjectGroupParameterType { + /** + * Symbolic object group name. + */ + objectGroup: string; + } + + interface SetCustomObjectFormatterEnabledParameterType { + enabled: boolean; + } + + interface CompileScriptParameterType { + /** + * Expression to compile. + */ + expression: string; + /** + * Source url to be set for the script. + */ + sourceURL: string; + /** + * Specifies whether the compiled script should be persisted. + */ + persistScript: boolean; + /** + * Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + executionContextId?: ExecutionContextId; + } + + interface RunScriptParameterType { + /** + * Id of the script to run. + */ + scriptId: ScriptId; + /** + * Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + executionContextId?: ExecutionContextId; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state. + */ + silent?: boolean; + /** + * Determines whether Command Line API should be available during the evaluation. + */ + includeCommandLineAPI?: boolean; + /** + * Whether the result is expected to be a JSON object which should be sent by value. + */ + returnByValue?: boolean; + /** + * Whether preview should be generated for the result. + */ + generatePreview?: boolean; + /** + * Whether execution should await for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean; + } + + interface QueryObjectsParameterType { + /** + * Identifier of the prototype to return objects for. + */ + prototypeObjectId: RemoteObjectId; + } + + interface GlobalLexicalScopeNamesParameterType { + /** + * Specifies in which execution context to lookup global scope variables. + */ + executionContextId?: ExecutionContextId; + } + + interface EvaluateReturnType { + /** + * Evaluation result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails; + } + + interface AwaitPromiseReturnType { + /** + * Promise result. Will contain rejected value if promise was rejected. + */ + result: RemoteObject; + /** + * Exception details if stack strace is available. + */ + exceptionDetails?: ExceptionDetails; + } + + interface CallFunctionOnReturnType { + /** + * Call result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails; + } + + interface GetPropertiesReturnType { + /** + * Object properties. + */ + result: PropertyDescriptor[]; + /** + * Internal object properties (only of the element itself). + */ + internalProperties?: InternalPropertyDescriptor[]; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails; + } + + interface CompileScriptReturnType { + /** + * Id of the script. + */ + scriptId?: ScriptId; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails; + } + + interface RunScriptReturnType { + /** + * Run result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails; + } + + interface QueryObjectsReturnType { + /** + * Array with objects. + */ + objects: RemoteObject; + } + + interface GlobalLexicalScopeNamesReturnType { + names: string[]; + } + + interface ExecutionContextCreatedEventDataType { + /** + * A newly created execution context. + */ + context: ExecutionContextDescription; + } + + interface ExecutionContextDestroyedEventDataType { + /** + * Id of the destroyed context + */ + executionContextId: ExecutionContextId; + } + + interface ExceptionThrownEventDataType { + /** + * Timestamp of the exception. + */ + timestamp: Timestamp; + exceptionDetails: ExceptionDetails; + } + + interface ExceptionRevokedEventDataType { + /** + * Reason describing why exception was revoked. + */ + reason: string; + /** + * The id of revoked exception, as reported in exceptionThrown. + */ + exceptionId: number; + } + + interface ConsoleAPICalledEventDataType { + /** + * Type of the call. + */ + type: string; + /** + * Call arguments. + */ + args: RemoteObject[]; + /** + * Identifier of the context where the call was made. + */ + executionContextId: ExecutionContextId; + /** + * Call timestamp. + */ + timestamp: Timestamp; + /** + * Stack trace captured when the call was made. + */ + stackTrace?: StackTrace; + /** + * Console context descriptor for calls on non-default console context (not console.*): 'anonymous#unique-logger-id' for call on unnamed context, 'name#unique-logger-id' for call on named context. + * @experimental + */ + context?: string; + } + + interface InspectRequestedEventDataType { + object: RemoteObject; + hints: {}; + } + } + + namespace Debugger { + /** + * Breakpoint identifier. + */ + type BreakpointId = string; + + /** + * Call frame identifier. + */ + type CallFrameId = string; + + /** + * Location in the source code. + */ + interface Location { + /** + * Script identifier as reported in the Debugger.scriptParsed. + */ + scriptId: Runtime.ScriptId; + /** + * Line number in the script (0-based). + */ + lineNumber: number; + /** + * Column number in the script (0-based). + */ + columnNumber?: number; + } + + /** + * Location in the source code. + * @experimental + */ + interface ScriptPosition { + lineNumber: number; + columnNumber: number; + } + + /** + * JavaScript call frame. Array of call frames form the call stack. + */ + interface CallFrame { + /** + * Call frame identifier. This identifier is only valid while the virtual machine is paused. + */ + callFrameId: CallFrameId; + /** + * Name of the JavaScript function called on this call frame. + */ + functionName: string; + /** + * Location in the source code. + */ + functionLocation?: Location; + /** + * Location in the source code. + */ + location: Location; + /** + * JavaScript script name or url. + */ + url: string; + /** + * Scope chain for this call frame. + */ + scopeChain: Scope[]; + /** + * this object for this call frame. + */ + this: Runtime.RemoteObject; + /** + * The value being returned, if the function is at return point. + */ + returnValue?: Runtime.RemoteObject; + } + + /** + * Scope description. + */ + interface Scope { + /** + * Scope type. + */ + type: string; + /** + * Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties. + */ + object: Runtime.RemoteObject; + name?: string; + /** + * Location in the source code where scope starts + */ + startLocation?: Location; + /** + * Location in the source code where scope ends + */ + endLocation?: Location; + } + + /** + * Search match for resource. + */ + interface SearchMatch { + /** + * Line number in resource content. + */ + lineNumber: number; + /** + * Line with match content. + */ + lineContent: string; + } + + interface BreakLocation { + /** + * Script identifier as reported in the Debugger.scriptParsed. + */ + scriptId: Runtime.ScriptId; + /** + * Line number in the script (0-based). + */ + lineNumber: number; + /** + * Column number in the script (0-based). + */ + columnNumber?: number; + type?: string; + } + + interface SetBreakpointsActiveParameterType { + /** + * New value for breakpoints active state. + */ + active: boolean; + } + + interface SetSkipAllPausesParameterType { + /** + * New value for skip pauses state. + */ + skip: boolean; + } + + interface SetBreakpointByUrlParameterType { + /** + * Line number to set breakpoint at. + */ + lineNumber: number; + /** + * URL of the resources to set breakpoint on. + */ + url?: string; + /** + * Regex pattern for the URLs of the resources to set breakpoints on. Either url or urlRegex must be specified. + */ + urlRegex?: string; + /** + * Script hash of the resources to set breakpoint on. + */ + scriptHash?: string; + /** + * Offset in the line to set breakpoint at. + */ + columnNumber?: number; + /** + * Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true. + */ + condition?: string; + } + + interface SetBreakpointParameterType { + /** + * Location to set breakpoint in. + */ + location: Location; + /** + * Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true. + */ + condition?: string; + } + + interface RemoveBreakpointParameterType { + breakpointId: BreakpointId; + } + + interface GetPossibleBreakpointsParameterType { + /** + * Start of range to search possible breakpoint locations in. + */ + start: Location; + /** + * End of range to search possible breakpoint locations in (excluding). When not specified, end of scripts is used as end of range. + */ + end?: Location; + /** + * Only consider locations which are in the same (non-nested) function as start. + */ + restrictToFunction?: boolean; + } + + interface ContinueToLocationParameterType { + /** + * Location to continue to. + */ + location: Location; + targetCallFrames?: string; + } + + interface PauseOnAsyncCallParameterType { + /** + * Debugger will pause when async call with given stack trace is started. + */ + parentStackTraceId: Runtime.StackTraceId; + } + + interface StepIntoParameterType { + /** + * Debugger will issue additional Debugger.paused notification if any async task is scheduled before next pause. + * @experimental + */ + breakOnAsyncCall?: boolean; + } + + interface GetStackTraceParameterType { + stackTraceId: Runtime.StackTraceId; + } + + interface SearchInContentParameterType { + /** + * Id of the script to search in. + */ + scriptId: Runtime.ScriptId; + /** + * String to search for. + */ + query: string; + /** + * If true, search is case sensitive. + */ + caseSensitive?: boolean; + /** + * If true, treats string parameter as regex. + */ + isRegex?: boolean; + } + + interface SetScriptSourceParameterType { + /** + * Id of the script to edit. + */ + scriptId: Runtime.ScriptId; + /** + * New content of the script. + */ + scriptSource: string; + /** + * If true the change will not actually be applied. Dry run may be used to get result description without actually modifying the code. + */ + dryRun?: boolean; + } + + interface RestartFrameParameterType { + /** + * Call frame identifier to evaluate on. + */ + callFrameId: CallFrameId; + } + + interface GetScriptSourceParameterType { + /** + * Id of the script to get source for. + */ + scriptId: Runtime.ScriptId; + } + + interface SetPauseOnExceptionsParameterType { + /** + * Pause on exceptions mode. + */ + state: string; + } + + interface EvaluateOnCallFrameParameterType { + /** + * Call frame identifier to evaluate on. + */ + callFrameId: CallFrameId; + /** + * Expression to evaluate. + */ + expression: string; + /** + * String object group name to put result into (allows rapid releasing resulting object handles using releaseObjectGroup). + */ + objectGroup?: string; + /** + * Specifies whether command line API should be available to the evaluated expression, defaults to false. + */ + includeCommandLineAPI?: boolean; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state. + */ + silent?: boolean; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean; + /** + * Whether to throw an exception if side effect cannot be ruled out during evaluation. + */ + throwOnSideEffect?: boolean; + } + + interface SetVariableValueParameterType { + /** + * 0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually. + */ + scopeNumber: number; + /** + * Variable name. + */ + variableName: string; + /** + * New variable value. + */ + newValue: Runtime.CallArgument; + /** + * Id of callframe that holds variable. + */ + callFrameId: CallFrameId; + } + + interface SetReturnValueParameterType { + /** + * New return value. + */ + newValue: Runtime.CallArgument; + } + + interface SetAsyncCallStackDepthParameterType { + /** + * Maximum depth of async call stacks. Setting to 0 will effectively disable collecting async call stacks (default). + */ + maxDepth: number; + } + + interface SetBlackboxPatternsParameterType { + /** + * Array of regexps that will be used to check script url for blackbox state. + */ + patterns: string[]; + } + + interface SetBlackboxedRangesParameterType { + /** + * Id of the script. + */ + scriptId: Runtime.ScriptId; + positions: ScriptPosition[]; + } + + interface EnableReturnType { + /** + * Unique identifier of the debugger. + * @experimental + */ + debuggerId: Runtime.UniqueDebuggerId; + } + + interface SetBreakpointByUrlReturnType { + /** + * Id of the created breakpoint for further reference. + */ + breakpointId: BreakpointId; + /** + * List of the locations this breakpoint resolved into upon addition. + */ + locations: Location[]; + } + + interface SetBreakpointReturnType { + /** + * Id of the created breakpoint for further reference. + */ + breakpointId: BreakpointId; + /** + * Location this breakpoint resolved into. + */ + actualLocation: Location; + } + + interface GetPossibleBreakpointsReturnType { + /** + * List of the possible breakpoint locations. + */ + locations: BreakLocation[]; + } + + interface GetStackTraceReturnType { + stackTrace: Runtime.StackTrace; + } + + interface SearchInContentReturnType { + /** + * List of search matches. + */ + result: SearchMatch[]; + } + + interface SetScriptSourceReturnType { + /** + * New stack trace in case editing has happened while VM was stopped. + */ + callFrames?: CallFrame[]; + /** + * Whether current call stack was modified after applying the changes. + */ + stackChanged?: boolean; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId; + /** + * Exception details if any. + */ + exceptionDetails?: Runtime.ExceptionDetails; + } + + interface RestartFrameReturnType { + /** + * New stack trace. + */ + callFrames: CallFrame[]; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId; + } + + interface GetScriptSourceReturnType { + /** + * Script source. + */ + scriptSource: string; + } + + interface EvaluateOnCallFrameReturnType { + /** + * Object wrapper for the evaluation result. + */ + result: Runtime.RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: Runtime.ExceptionDetails; + } + + interface ScriptParsedEventDataType { + /** + * Identifier of the script parsed. + */ + scriptId: Runtime.ScriptId; + /** + * URL or name of the script parsed (if any). + */ + url: string; + /** + * Line offset of the script within the resource with given URL (for script tags). + */ + startLine: number; + /** + * Column offset of the script within the resource with given URL. + */ + startColumn: number; + /** + * Last line of the script. + */ + endLine: number; + /** + * Length of the last line of the script. + */ + endColumn: number; + /** + * Specifies script creation context. + */ + executionContextId: Runtime.ExecutionContextId; + /** + * Content hash of the script. + */ + hash: string; + /** + * Embedder-specific auxiliary data. + */ + executionContextAuxData?: {}; + /** + * True, if this script is generated as a result of the live edit operation. + * @experimental + */ + isLiveEdit?: boolean; + /** + * URL of source map associated with script (if any). + */ + sourceMapURL?: string; + /** + * True, if this script has sourceURL. + */ + hasSourceURL?: boolean; + /** + * True, if this script is ES6 module. + */ + isModule?: boolean; + /** + * This script length. + */ + length?: number; + /** + * JavaScript top stack frame of where the script parsed event was triggered if available. + * @experimental + */ + stackTrace?: Runtime.StackTrace; + } + + interface ScriptFailedToParseEventDataType { + /** + * Identifier of the script parsed. + */ + scriptId: Runtime.ScriptId; + /** + * URL or name of the script parsed (if any). + */ + url: string; + /** + * Line offset of the script within the resource with given URL (for script tags). + */ + startLine: number; + /** + * Column offset of the script within the resource with given URL. + */ + startColumn: number; + /** + * Last line of the script. + */ + endLine: number; + /** + * Length of the last line of the script. + */ + endColumn: number; + /** + * Specifies script creation context. + */ + executionContextId: Runtime.ExecutionContextId; + /** + * Content hash of the script. + */ + hash: string; + /** + * Embedder-specific auxiliary data. + */ + executionContextAuxData?: {}; + /** + * URL of source map associated with script (if any). + */ + sourceMapURL?: string; + /** + * True, if this script has sourceURL. + */ + hasSourceURL?: boolean; + /** + * True, if this script is ES6 module. + */ + isModule?: boolean; + /** + * This script length. + */ + length?: number; + /** + * JavaScript top stack frame of where the script parsed event was triggered if available. + * @experimental + */ + stackTrace?: Runtime.StackTrace; + } + + interface BreakpointResolvedEventDataType { + /** + * Breakpoint unique identifier. + */ + breakpointId: BreakpointId; + /** + * Actual breakpoint location. + */ + location: Location; + } + + interface PausedEventDataType { + /** + * Call stack the virtual machine stopped on. + */ + callFrames: CallFrame[]; + /** + * Pause reason. + */ + reason: string; + /** + * Object containing break-specific auxiliary properties. + */ + data?: {}; + /** + * Hit breakpoints IDs + */ + hitBreakpoints?: string[]; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId; + /** + * Just scheduled async call will have this stack trace as parent stack during async execution. This field is available only after Debugger.stepInto call with breakOnAsynCall flag. + * @experimental + */ + asyncCallStackTraceId?: Runtime.StackTraceId; + } + } + + namespace Console { + /** + * Console message. + */ + interface ConsoleMessage { + /** + * Message source. + */ + source: string; + /** + * Message severity. + */ + level: string; + /** + * Message text. + */ + text: string; + /** + * URL of the message origin. + */ + url?: string; + /** + * Line number in the resource that generated this message (1-based). + */ + line?: number; + /** + * Column number in the resource that generated this message (1-based). + */ + column?: number; + } + + interface MessageAddedEventDataType { + /** + * Console message that has been added. + */ + message: ConsoleMessage; + } + } + + namespace Profiler { + /** + * Profile node. Holds callsite information, execution statistics and child nodes. + */ + interface ProfileNode { + /** + * Unique id of the node. + */ + id: number; + /** + * Function location. + */ + callFrame: Runtime.CallFrame; + /** + * Number of samples where this node was on top of the call stack. + */ + hitCount?: number; + /** + * Child node ids. + */ + children?: number[]; + /** + * The reason of being not optimized. The function may be deoptimized or marked as don't optimize. + */ + deoptReason?: string; + /** + * An array of source position ticks. + */ + positionTicks?: PositionTickInfo[]; + } + + /** + * Profile. + */ + interface Profile { + /** + * The list of profile nodes. First item is the root node. + */ + nodes: ProfileNode[]; + /** + * Profiling start timestamp in microseconds. + */ + startTime: number; + /** + * Profiling end timestamp in microseconds. + */ + endTime: number; + /** + * Ids of samples top nodes. + */ + samples?: number[]; + /** + * Time intervals between adjacent samples in microseconds. The first delta is relative to the profile startTime. + */ + timeDeltas?: number[]; + } + + /** + * Specifies a number of samples attributed to a certain source position. + */ + interface PositionTickInfo { + /** + * Source line number (1-based). + */ + line: number; + /** + * Number of samples attributed to the source line. + */ + ticks: number; + } + + /** + * Coverage data for a source range. + */ + interface CoverageRange { + /** + * JavaScript script source offset for the range start. + */ + startOffset: number; + /** + * JavaScript script source offset for the range end. + */ + endOffset: number; + /** + * Collected execution count of the source range. + */ + count: number; + } + + /** + * Coverage data for a JavaScript function. + */ + interface FunctionCoverage { + /** + * JavaScript function name. + */ + functionName: string; + /** + * Source ranges inside the function with coverage data. + */ + ranges: CoverageRange[]; + /** + * Whether coverage data for this function has block granularity. + */ + isBlockCoverage: boolean; + } + + /** + * Coverage data for a JavaScript script. + */ + interface ScriptCoverage { + /** + * JavaScript script id. + */ + scriptId: Runtime.ScriptId; + /** + * JavaScript script name or url. + */ + url: string; + /** + * Functions contained in the script that has coverage data. + */ + functions: FunctionCoverage[]; + } + + /** + * Describes a type collected during runtime. + * @experimental + */ + interface TypeObject { + /** + * Name of a type collected with type profiling. + */ + name: string; + } + + /** + * Source offset and types for a parameter or return value. + * @experimental + */ + interface TypeProfileEntry { + /** + * Source offset of the parameter or end of function for return values. + */ + offset: number; + /** + * The types for this parameter or return value. + */ + types: TypeObject[]; + } + + /** + * Type profile data collected during runtime for a JavaScript script. + * @experimental + */ + interface ScriptTypeProfile { + /** + * JavaScript script id. + */ + scriptId: Runtime.ScriptId; + /** + * JavaScript script name or url. + */ + url: string; + /** + * Type profile entries for parameters and return values of the functions in the script. + */ + entries: TypeProfileEntry[]; + } + + interface SetSamplingIntervalParameterType { + /** + * New sampling interval in microseconds. + */ + interval: number; + } + + interface StartPreciseCoverageParameterType { + /** + * Collect accurate call counts beyond simple 'covered' or 'not covered'. + */ + callCount?: boolean; + /** + * Collect block-based coverage. + */ + detailed?: boolean; + } + + interface StopReturnType { + /** + * Recorded profile. + */ + profile: Profile; + } + + interface TakePreciseCoverageReturnType { + /** + * Coverage data for the current isolate. + */ + result: ScriptCoverage[]; + } + + interface GetBestEffortCoverageReturnType { + /** + * Coverage data for the current isolate. + */ + result: ScriptCoverage[]; + } + + interface TakeTypeProfileReturnType { + /** + * Type profile for all scripts since startTypeProfile() was turned on. + */ + result: ScriptTypeProfile[]; + } + + interface ConsoleProfileStartedEventDataType { + id: string; + /** + * Location of console.profile(). + */ + location: Debugger.Location; + /** + * Profile title passed as an argument to console.profile(). + */ + title?: string; + } + + interface ConsoleProfileFinishedEventDataType { + id: string; + /** + * Location of console.profileEnd(). + */ + location: Debugger.Location; + profile: Profile; + /** + * Profile title passed as an argument to console.profile(). + */ + title?: string; + } + } + + namespace HeapProfiler { + /** + * Heap snapshot object id. + */ + type HeapSnapshotObjectId = string; + + /** + * Sampling Heap Profile node. Holds callsite information, allocation statistics and child nodes. + */ + interface SamplingHeapProfileNode { + /** + * Function location. + */ + callFrame: Runtime.CallFrame; + /** + * Allocations size in bytes for the node excluding children. + */ + selfSize: number; + /** + * Child nodes. + */ + children: SamplingHeapProfileNode[]; + } + + /** + * Profile. + */ + interface SamplingHeapProfile { + head: SamplingHeapProfileNode; + } + + interface StartTrackingHeapObjectsParameterType { + trackAllocations?: boolean; + } + + interface StopTrackingHeapObjectsParameterType { + /** + * If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken when the tracking is stopped. + */ + reportProgress?: boolean; + } + + interface TakeHeapSnapshotParameterType { + /** + * If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken. + */ + reportProgress?: boolean; + } + + interface GetObjectByHeapObjectIdParameterType { + objectId: HeapSnapshotObjectId; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string; + } + + interface AddInspectedHeapObjectParameterType { + /** + * Heap snapshot object id to be accessible by means of $x command line API. + */ + heapObjectId: HeapSnapshotObjectId; + } + + interface GetHeapObjectIdParameterType { + /** + * Identifier of the object to get heap object id for. + */ + objectId: Runtime.RemoteObjectId; + } + + interface StartSamplingParameterType { + /** + * Average sample interval in bytes. Poisson distribution is used for the intervals. The default value is 32768 bytes. + */ + samplingInterval?: number; + } + + interface GetObjectByHeapObjectIdReturnType { + /** + * Evaluation result. + */ + result: Runtime.RemoteObject; + } + + interface GetHeapObjectIdReturnType { + /** + * Id of the heap snapshot object corresponding to the passed remote object id. + */ + heapSnapshotObjectId: HeapSnapshotObjectId; + } + + interface StopSamplingReturnType { + /** + * Recorded sampling heap profile. + */ + profile: SamplingHeapProfile; + } + + interface GetSamplingProfileReturnType { + /** + * Return the sampling profile being collected. + */ + profile: SamplingHeapProfile; + } + + interface AddHeapSnapshotChunkEventDataType { + chunk: string; + } + + interface ReportHeapSnapshotProgressEventDataType { + done: number; + total: number; + finished?: boolean; + } + + interface LastSeenObjectIdEventDataType { + lastSeenObjectId: number; + timestamp: number; + } + + interface HeapStatsUpdateEventDataType { + /** + * An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment. + */ + statsUpdate: number[]; + } + } + + namespace NodeTracing { + interface TraceConfig { + /** + * Controls how the trace buffer stores data. + */ + recordMode?: string; + /** + * Included category filters. + */ + includedCategories: string[]; + } + + interface StartParameterType { + traceConfig: TraceConfig; + } + + interface GetCategoriesReturnType { + /** + * A list of supported tracing categories. + */ + categories: string[]; + } + + interface DataCollectedEventDataType { + value: Array<{}>; + } + } + + namespace NodeWorker { + type WorkerID = string; + + /** + * Unique identifier of attached debugging session. + */ + type SessionID = string; + + interface WorkerInfo { + workerId: WorkerID; + type: string; + title: string; + url: string; + } + + interface SendMessageToWorkerParameterType { + message: string; + /** + * Identifier of the session. + */ + sessionId: SessionID; + } + + interface EnableParameterType { + /** + * Whether to new workers should be paused until the frontend sends `Runtime.runIfWaitingForDebugger` + * message to run them. + */ + waitForDebuggerOnStart: boolean; + } + + interface DetachParameterType { + sessionId: SessionID; + } + + interface AttachedToWorkerEventDataType { + /** + * Identifier assigned to the session used to send/receive messages. + */ + sessionId: SessionID; + workerInfo: WorkerInfo; + waitingForDebugger: boolean; + } + + interface DetachedFromWorkerEventDataType { + /** + * Detached session identifier. + */ + sessionId: SessionID; + } + + interface ReceivedMessageFromWorkerEventDataType { + /** + * Identifier of a session which sends a message. + */ + sessionId: SessionID; + message: string; + } + } + + namespace NodeRuntime { + interface NotifyWhenWaitingForDisconnectParameterType { + enabled: boolean; + } + } + + /** + * The inspector.Session is used for dispatching messages to the V8 inspector back-end and receiving message responses and notifications. + */ + class Session extends EventEmitter { + /** + * Create a new instance of the inspector.Session class. + * The inspector session needs to be connected through session.connect() before the messages can be dispatched to the inspector backend. + */ + constructor(); + + /** + * Connects a session to the inspector back-end. + * An exception will be thrown if there is already a connected session established either + * through the API or by a front-end connected to the Inspector WebSocket port. + */ + connect(): void; + + /** + * Immediately close the session. All pending message callbacks will be called with an error. + * session.connect() will need to be called to be able to send messages again. + * Reconnected session will lose all inspector state, such as enabled agents or configured breakpoints. + */ + disconnect(): void; + + /** + * Posts a message to the inspector back-end. callback will be notified when a response is received. + * callback is a function that accepts two optional arguments - error and message-specific result. + */ + post(method: string, params?: {}, callback?: (err: Error | null, params?: {}) => void): void; + post(method: string, callback?: (err: Error | null, params?: {}) => void): void; + + /** + * Returns supported domains. + */ + post(method: "Schema.getDomains", callback?: (err: Error | null, params: Schema.GetDomainsReturnType) => void): void; + + /** + * Evaluates expression on global object. + */ + post(method: "Runtime.evaluate", params?: Runtime.EvaluateParameterType, callback?: (err: Error | null, params: Runtime.EvaluateReturnType) => void): void; + post(method: "Runtime.evaluate", callback?: (err: Error | null, params: Runtime.EvaluateReturnType) => void): void; + + /** + * Add handler to promise with given promise object id. + */ + post(method: "Runtime.awaitPromise", params?: Runtime.AwaitPromiseParameterType, callback?: (err: Error | null, params: Runtime.AwaitPromiseReturnType) => void): void; + post(method: "Runtime.awaitPromise", callback?: (err: Error | null, params: Runtime.AwaitPromiseReturnType) => void): void; + + /** + * Calls function with given declaration on the given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.callFunctionOn", params?: Runtime.CallFunctionOnParameterType, callback?: (err: Error | null, params: Runtime.CallFunctionOnReturnType) => void): void; + post(method: "Runtime.callFunctionOn", callback?: (err: Error | null, params: Runtime.CallFunctionOnReturnType) => void): void; + + /** + * Returns properties of a given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.getProperties", params?: Runtime.GetPropertiesParameterType, callback?: (err: Error | null, params: Runtime.GetPropertiesReturnType) => void): void; + post(method: "Runtime.getProperties", callback?: (err: Error | null, params: Runtime.GetPropertiesReturnType) => void): void; + + /** + * Releases remote object with given id. + */ + post(method: "Runtime.releaseObject", params?: Runtime.ReleaseObjectParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.releaseObject", callback?: (err: Error | null) => void): void; + + /** + * Releases all remote objects that belong to a given group. + */ + post(method: "Runtime.releaseObjectGroup", params?: Runtime.ReleaseObjectGroupParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.releaseObjectGroup", callback?: (err: Error | null) => void): void; + + /** + * Tells inspected instance to run if it was waiting for debugger to attach. + */ + post(method: "Runtime.runIfWaitingForDebugger", callback?: (err: Error | null) => void): void; + + /** + * Enables reporting of execution contexts creation by means of executionContextCreated event. When the reporting gets enabled the event will be sent immediately for each existing execution context. + */ + post(method: "Runtime.enable", callback?: (err: Error | null) => void): void; + + /** + * Disables reporting of execution contexts creation. + */ + post(method: "Runtime.disable", callback?: (err: Error | null) => void): void; + + /** + * Discards collected exceptions and console API calls. + */ + post(method: "Runtime.discardConsoleEntries", callback?: (err: Error | null) => void): void; + + /** + * @experimental + */ + post(method: "Runtime.setCustomObjectFormatterEnabled", params?: Runtime.SetCustomObjectFormatterEnabledParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.setCustomObjectFormatterEnabled", callback?: (err: Error | null) => void): void; + + /** + * Compiles expression. + */ + post(method: "Runtime.compileScript", params?: Runtime.CompileScriptParameterType, callback?: (err: Error | null, params: Runtime.CompileScriptReturnType) => void): void; + post(method: "Runtime.compileScript", callback?: (err: Error | null, params: Runtime.CompileScriptReturnType) => void): void; + + /** + * Runs script with given id in a given context. + */ + post(method: "Runtime.runScript", params?: Runtime.RunScriptParameterType, callback?: (err: Error | null, params: Runtime.RunScriptReturnType) => void): void; + post(method: "Runtime.runScript", callback?: (err: Error | null, params: Runtime.RunScriptReturnType) => void): void; + + post(method: "Runtime.queryObjects", params?: Runtime.QueryObjectsParameterType, callback?: (err: Error | null, params: Runtime.QueryObjectsReturnType) => void): void; + post(method: "Runtime.queryObjects", callback?: (err: Error | null, params: Runtime.QueryObjectsReturnType) => void): void; + + /** + * Returns all let, const and class variables from global scope. + */ + post( + method: "Runtime.globalLexicalScopeNames", + params?: Runtime.GlobalLexicalScopeNamesParameterType, + callback?: (err: Error | null, params: Runtime.GlobalLexicalScopeNamesReturnType) => void + ): void; + post(method: "Runtime.globalLexicalScopeNames", callback?: (err: Error | null, params: Runtime.GlobalLexicalScopeNamesReturnType) => void): void; + + /** + * Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received. + */ + post(method: "Debugger.enable", callback?: (err: Error | null, params: Debugger.EnableReturnType) => void): void; + + /** + * Disables debugger for given page. + */ + post(method: "Debugger.disable", callback?: (err: Error | null) => void): void; + + /** + * Activates / deactivates all breakpoints on the page. + */ + post(method: "Debugger.setBreakpointsActive", params?: Debugger.SetBreakpointsActiveParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBreakpointsActive", callback?: (err: Error | null) => void): void; + + /** + * Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc). + */ + post(method: "Debugger.setSkipAllPauses", params?: Debugger.SetSkipAllPausesParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setSkipAllPauses", callback?: (err: Error | null) => void): void; + + /** + * Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in locations property. Further matching script parsing will result in subsequent breakpointResolved events issued. This logical breakpoint will survive page reloads. + */ + post(method: "Debugger.setBreakpointByUrl", params?: Debugger.SetBreakpointByUrlParameterType, callback?: (err: Error | null, params: Debugger.SetBreakpointByUrlReturnType) => void): void; + post(method: "Debugger.setBreakpointByUrl", callback?: (err: Error | null, params: Debugger.SetBreakpointByUrlReturnType) => void): void; + + /** + * Sets JavaScript breakpoint at a given location. + */ + post(method: "Debugger.setBreakpoint", params?: Debugger.SetBreakpointParameterType, callback?: (err: Error | null, params: Debugger.SetBreakpointReturnType) => void): void; + post(method: "Debugger.setBreakpoint", callback?: (err: Error | null, params: Debugger.SetBreakpointReturnType) => void): void; + + /** + * Removes JavaScript breakpoint. + */ + post(method: "Debugger.removeBreakpoint", params?: Debugger.RemoveBreakpointParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.removeBreakpoint", callback?: (err: Error | null) => void): void; + + /** + * Returns possible locations for breakpoint. scriptId in start and end range locations should be the same. + */ + post( + method: "Debugger.getPossibleBreakpoints", + params?: Debugger.GetPossibleBreakpointsParameterType, + callback?: (err: Error | null, params: Debugger.GetPossibleBreakpointsReturnType) => void + ): void; + post(method: "Debugger.getPossibleBreakpoints", callback?: (err: Error | null, params: Debugger.GetPossibleBreakpointsReturnType) => void): void; + + /** + * Continues execution until specific location is reached. + */ + post(method: "Debugger.continueToLocation", params?: Debugger.ContinueToLocationParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.continueToLocation", callback?: (err: Error | null) => void): void; + + /** + * @experimental + */ + post(method: "Debugger.pauseOnAsyncCall", params?: Debugger.PauseOnAsyncCallParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.pauseOnAsyncCall", callback?: (err: Error | null) => void): void; + + /** + * Steps over the statement. + */ + post(method: "Debugger.stepOver", callback?: (err: Error | null) => void): void; + + /** + * Steps into the function call. + */ + post(method: "Debugger.stepInto", params?: Debugger.StepIntoParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.stepInto", callback?: (err: Error | null) => void): void; + + /** + * Steps out of the function call. + */ + post(method: "Debugger.stepOut", callback?: (err: Error | null) => void): void; + + /** + * Stops on the next JavaScript statement. + */ + post(method: "Debugger.pause", callback?: (err: Error | null) => void): void; + + /** + * This method is deprecated - use Debugger.stepInto with breakOnAsyncCall and Debugger.pauseOnAsyncTask instead. Steps into next scheduled async task if any is scheduled before next pause. Returns success when async task is actually scheduled, returns error if no task were scheduled or another scheduleStepIntoAsync was called. + * @experimental + */ + post(method: "Debugger.scheduleStepIntoAsync", callback?: (err: Error | null) => void): void; + + /** + * Resumes JavaScript execution. + */ + post(method: "Debugger.resume", callback?: (err: Error | null) => void): void; + + /** + * Returns stack trace with given stackTraceId. + * @experimental + */ + post(method: "Debugger.getStackTrace", params?: Debugger.GetStackTraceParameterType, callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void; + post(method: "Debugger.getStackTrace", callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void; + + /** + * Searches for given string in script content. + */ + post(method: "Debugger.searchInContent", params?: Debugger.SearchInContentParameterType, callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void; + post(method: "Debugger.searchInContent", callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void; + + /** + * Edits JavaScript source live. + */ + post(method: "Debugger.setScriptSource", params?: Debugger.SetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void; + post(method: "Debugger.setScriptSource", callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void; + + /** + * Restarts particular call frame from the beginning. + */ + post(method: "Debugger.restartFrame", params?: Debugger.RestartFrameParameterType, callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void; + post(method: "Debugger.restartFrame", callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void; + + /** + * Returns source for the script with given id. + */ + post(method: "Debugger.getScriptSource", params?: Debugger.GetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void; + post(method: "Debugger.getScriptSource", callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void; + + /** + * Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is none. + */ + post(method: "Debugger.setPauseOnExceptions", params?: Debugger.SetPauseOnExceptionsParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setPauseOnExceptions", callback?: (err: Error | null) => void): void; + + /** + * Evaluates expression on a given call frame. + */ + post(method: "Debugger.evaluateOnCallFrame", params?: Debugger.EvaluateOnCallFrameParameterType, callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void; + post(method: "Debugger.evaluateOnCallFrame", callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void; + + /** + * Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually. + */ + post(method: "Debugger.setVariableValue", params?: Debugger.SetVariableValueParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setVariableValue", callback?: (err: Error | null) => void): void; + + /** + * Changes return value in top frame. Available only at return break position. + * @experimental + */ + post(method: "Debugger.setReturnValue", params?: Debugger.SetReturnValueParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setReturnValue", callback?: (err: Error | null) => void): void; + + /** + * Enables or disables async call stacks tracking. + */ + post(method: "Debugger.setAsyncCallStackDepth", params?: Debugger.SetAsyncCallStackDepthParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setAsyncCallStackDepth", callback?: (err: Error | null) => void): void; + + /** + * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + * @experimental + */ + post(method: "Debugger.setBlackboxPatterns", params?: Debugger.SetBlackboxPatternsParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBlackboxPatterns", callback?: (err: Error | null) => void): void; + + /** + * Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted. + * @experimental + */ + post(method: "Debugger.setBlackboxedRanges", params?: Debugger.SetBlackboxedRangesParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBlackboxedRanges", callback?: (err: Error | null) => void): void; + + /** + * Enables console domain, sends the messages collected so far to the client by means of the messageAdded notification. + */ + post(method: "Console.enable", callback?: (err: Error | null) => void): void; + + /** + * Disables console domain, prevents further console messages from being reported to the client. + */ + post(method: "Console.disable", callback?: (err: Error | null) => void): void; + + /** + * Does nothing. + */ + post(method: "Console.clearMessages", callback?: (err: Error | null) => void): void; + + post(method: "Profiler.enable", callback?: (err: Error | null) => void): void; + + post(method: "Profiler.disable", callback?: (err: Error | null) => void): void; + + /** + * Changes CPU profiler sampling interval. Must be called before CPU profiles recording started. + */ + post(method: "Profiler.setSamplingInterval", params?: Profiler.SetSamplingIntervalParameterType, callback?: (err: Error | null) => void): void; + post(method: "Profiler.setSamplingInterval", callback?: (err: Error | null) => void): void; + + post(method: "Profiler.start", callback?: (err: Error | null) => void): void; + + post(method: "Profiler.stop", callback?: (err: Error | null, params: Profiler.StopReturnType) => void): void; + + /** + * Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters. + */ + post(method: "Profiler.startPreciseCoverage", params?: Profiler.StartPreciseCoverageParameterType, callback?: (err: Error | null) => void): void; + post(method: "Profiler.startPreciseCoverage", callback?: (err: Error | null) => void): void; + + /** + * Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code. + */ + post(method: "Profiler.stopPreciseCoverage", callback?: (err: Error | null) => void): void; + + /** + * Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started. + */ + post(method: "Profiler.takePreciseCoverage", callback?: (err: Error | null, params: Profiler.TakePreciseCoverageReturnType) => void): void; + + /** + * Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection. + */ + post(method: "Profiler.getBestEffortCoverage", callback?: (err: Error | null, params: Profiler.GetBestEffortCoverageReturnType) => void): void; + + /** + * Enable type profile. + * @experimental + */ + post(method: "Profiler.startTypeProfile", callback?: (err: Error | null) => void): void; + + /** + * Disable type profile. Disabling releases type profile data collected so far. + * @experimental + */ + post(method: "Profiler.stopTypeProfile", callback?: (err: Error | null) => void): void; + + /** + * Collect type profile. + * @experimental + */ + post(method: "Profiler.takeTypeProfile", callback?: (err: Error | null, params: Profiler.TakeTypeProfileReturnType) => void): void; + + post(method: "HeapProfiler.enable", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.disable", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.startTrackingHeapObjects", params?: HeapProfiler.StartTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.startTrackingHeapObjects", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.stopTrackingHeapObjects", params?: HeapProfiler.StopTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.stopTrackingHeapObjects", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.takeHeapSnapshot", params?: HeapProfiler.TakeHeapSnapshotParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.takeHeapSnapshot", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.collectGarbage", callback?: (err: Error | null) => void): void; + + post( + method: "HeapProfiler.getObjectByHeapObjectId", + params?: HeapProfiler.GetObjectByHeapObjectIdParameterType, + callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void + ): void; + post(method: "HeapProfiler.getObjectByHeapObjectId", callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void): void; + + /** + * Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions). + */ + post(method: "HeapProfiler.addInspectedHeapObject", params?: HeapProfiler.AddInspectedHeapObjectParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.addInspectedHeapObject", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.getHeapObjectId", params?: HeapProfiler.GetHeapObjectIdParameterType, callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void; + post(method: "HeapProfiler.getHeapObjectId", callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void; + + post(method: "HeapProfiler.startSampling", params?: HeapProfiler.StartSamplingParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.startSampling", callback?: (err: Error | null) => void): void; + + post(method: "HeapProfiler.stopSampling", callback?: (err: Error | null, params: HeapProfiler.StopSamplingReturnType) => void): void; + + post(method: "HeapProfiler.getSamplingProfile", callback?: (err: Error | null, params: HeapProfiler.GetSamplingProfileReturnType) => void): void; + + /** + * Gets supported tracing categories. + */ + post(method: "NodeTracing.getCategories", callback?: (err: Error | null, params: NodeTracing.GetCategoriesReturnType) => void): void; + + /** + * Start trace events collection. + */ + post(method: "NodeTracing.start", params?: NodeTracing.StartParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeTracing.start", callback?: (err: Error | null) => void): void; + + /** + * Stop trace events collection. Remaining collected events will be sent as a sequence of + * dataCollected events followed by tracingComplete event. + */ + post(method: "NodeTracing.stop", callback?: (err: Error | null) => void): void; + + /** + * Sends protocol message over session with given id. + */ + post(method: "NodeWorker.sendMessageToWorker", params?: NodeWorker.SendMessageToWorkerParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.sendMessageToWorker", callback?: (err: Error | null) => void): void; + + /** + * Instructs the inspector to attach to running workers. Will also attach to new workers + * as they start + */ + post(method: "NodeWorker.enable", params?: NodeWorker.EnableParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.enable", callback?: (err: Error | null) => void): void; + + /** + * Detaches from all running workers and disables attaching to new workers as they are started. + */ + post(method: "NodeWorker.disable", callback?: (err: Error | null) => void): void; + + /** + * Detached from the worker with given sessionId. + */ + post(method: "NodeWorker.detach", params?: NodeWorker.DetachParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.detach", callback?: (err: Error | null) => void): void; + + /** + * Enable the `NodeRuntime.waitingForDisconnect`. + */ + post(method: "NodeRuntime.notifyWhenWaitingForDisconnect", params?: NodeRuntime.NotifyWhenWaitingForDisconnectParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeRuntime.notifyWhenWaitingForDisconnect", callback?: (err: Error | null) => void): void; + + // Events + + addListener(event: string, listener: (...args: any[]) => void): this; + + /** + * Emitted when any notification from the V8 Inspector is received. + */ + addListener(event: "inspectorNotification", listener: (message: InspectorNotification<{}>) => void): this; + + /** + * Issued when new execution context is created. + */ + addListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when execution context is destroyed. + */ + addListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when all executionContexts were cleared in browser + */ + addListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + + /** + * Issued when exception was thrown and unhandled. + */ + addListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when unhandled exception was revoked. + */ + addListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when console API was called. + */ + addListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + addListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + addListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine fails to parse the script. + */ + addListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + addListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + addListener(event: "Debugger.paused", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine resumed execution. + */ + addListener(event: "Debugger.resumed", listener: () => void): this; + + /** + * Issued when new console message is added. + */ + addListener(event: "Console.messageAdded", listener: (message: InspectorNotification) => void): this; + + /** + * Sent when new profile recording is started using console.profile() call. + */ + addListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification) => void): this; + + addListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification) => void): this; + addListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification) => void): this; + addListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + addListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + addListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + addListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification) => void): this; + + /** + * Contains an bucket of collected trace events. + */ + addListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification) => void): this; + + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + addListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + + /** + * Issued when attached to a worker. + */ + addListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when detached from the worker. + */ + addListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + addListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + addListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "inspectorNotification", message: InspectorNotification<{}>): boolean; + emit(event: "Runtime.executionContextCreated", message: InspectorNotification): boolean; + emit(event: "Runtime.executionContextDestroyed", message: InspectorNotification): boolean; + emit(event: "Runtime.executionContextsCleared"): boolean; + emit(event: "Runtime.exceptionThrown", message: InspectorNotification): boolean; + emit(event: "Runtime.exceptionRevoked", message: InspectorNotification): boolean; + emit(event: "Runtime.consoleAPICalled", message: InspectorNotification): boolean; + emit(event: "Runtime.inspectRequested", message: InspectorNotification): boolean; + emit(event: "Debugger.scriptParsed", message: InspectorNotification): boolean; + emit(event: "Debugger.scriptFailedToParse", message: InspectorNotification): boolean; + emit(event: "Debugger.breakpointResolved", message: InspectorNotification): boolean; + emit(event: "Debugger.paused", message: InspectorNotification): boolean; + emit(event: "Debugger.resumed"): boolean; + emit(event: "Console.messageAdded", message: InspectorNotification): boolean; + emit(event: "Profiler.consoleProfileStarted", message: InspectorNotification): boolean; + emit(event: "Profiler.consoleProfileFinished", message: InspectorNotification): boolean; + emit(event: "HeapProfiler.addHeapSnapshotChunk", message: InspectorNotification): boolean; + emit(event: "HeapProfiler.resetProfiles"): boolean; + emit(event: "HeapProfiler.reportHeapSnapshotProgress", message: InspectorNotification): boolean; + emit(event: "HeapProfiler.lastSeenObjectId", message: InspectorNotification): boolean; + emit(event: "HeapProfiler.heapStatsUpdate", message: InspectorNotification): boolean; + emit(event: "NodeTracing.dataCollected", message: InspectorNotification): boolean; + emit(event: "NodeTracing.tracingComplete"): boolean; + emit(event: "NodeWorker.attachedToWorker", message: InspectorNotification): boolean; + emit(event: "NodeWorker.detachedFromWorker", message: InspectorNotification): boolean; + emit(event: "NodeWorker.receivedMessageFromWorker", message: InspectorNotification): boolean; + emit(event: "NodeRuntime.waitingForDisconnect"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + + /** + * Emitted when any notification from the V8 Inspector is received. + */ + on(event: "inspectorNotification", listener: (message: InspectorNotification<{}>) => void): this; + + /** + * Issued when new execution context is created. + */ + on(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when execution context is destroyed. + */ + on(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when all executionContexts were cleared in browser + */ + on(event: "Runtime.executionContextsCleared", listener: () => void): this; + + /** + * Issued when exception was thrown and unhandled. + */ + on(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when unhandled exception was revoked. + */ + on(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when console API was called. + */ + on(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + on(event: "Runtime.inspectRequested", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + on(event: "Debugger.scriptParsed", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine fails to parse the script. + */ + on(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + on(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + on(event: "Debugger.paused", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine resumed execution. + */ + on(event: "Debugger.resumed", listener: () => void): this; + + /** + * Issued when new console message is added. + */ + on(event: "Console.messageAdded", listener: (message: InspectorNotification) => void): this; + + /** + * Sent when new profile recording is started using console.profile() call. + */ + on(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification) => void): this; + + on(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification) => void): this; + on(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification) => void): this; + on(event: "HeapProfiler.resetProfiles", listener: () => void): this; + on(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + on(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + on(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification) => void): this; + + /** + * Contains an bucket of collected trace events. + */ + on(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification) => void): this; + + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + on(event: "NodeTracing.tracingComplete", listener: () => void): this; + + /** + * Issued when attached to a worker. + */ + on(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when detached from the worker. + */ + on(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + on(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + on(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + + /** + * Emitted when any notification from the V8 Inspector is received. + */ + once(event: "inspectorNotification", listener: (message: InspectorNotification<{}>) => void): this; + + /** + * Issued when new execution context is created. + */ + once(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when execution context is destroyed. + */ + once(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when all executionContexts were cleared in browser + */ + once(event: "Runtime.executionContextsCleared", listener: () => void): this; + + /** + * Issued when exception was thrown and unhandled. + */ + once(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when unhandled exception was revoked. + */ + once(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when console API was called. + */ + once(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + once(event: "Runtime.inspectRequested", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + once(event: "Debugger.scriptParsed", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine fails to parse the script. + */ + once(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + once(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + once(event: "Debugger.paused", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine resumed execution. + */ + once(event: "Debugger.resumed", listener: () => void): this; + + /** + * Issued when new console message is added. + */ + once(event: "Console.messageAdded", listener: (message: InspectorNotification) => void): this; + + /** + * Sent when new profile recording is started using console.profile() call. + */ + once(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification) => void): this; + + once(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification) => void): this; + once(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification) => void): this; + once(event: "HeapProfiler.resetProfiles", listener: () => void): this; + once(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + once(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + once(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification) => void): this; + + /** + * Contains an bucket of collected trace events. + */ + once(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification) => void): this; + + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + once(event: "NodeTracing.tracingComplete", listener: () => void): this; + + /** + * Issued when attached to a worker. + */ + once(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when detached from the worker. + */ + once(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + once(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + once(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependListener(event: "inspectorNotification", listener: (message: InspectorNotification<{}>) => void): this; + + /** + * Issued when new execution context is created. + */ + prependListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when execution context is destroyed. + */ + prependListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when all executionContexts were cleared in browser + */ + prependListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + + /** + * Issued when exception was thrown and unhandled. + */ + prependListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when unhandled exception was revoked. + */ + prependListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when console API was called. + */ + prependListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine fails to parse the script. + */ + prependListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependListener(event: "Debugger.paused", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine resumed execution. + */ + prependListener(event: "Debugger.resumed", listener: () => void): this; + + /** + * Issued when new console message is added. + */ + prependListener(event: "Console.messageAdded", listener: (message: InspectorNotification) => void): this; + + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification) => void): this; + + prependListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification) => void): this; + prependListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification) => void): this; + prependListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification) => void): this; + + /** + * Contains an bucket of collected trace events. + */ + prependListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification) => void): this; + + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + + /** + * Issued when attached to a worker. + */ + prependListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when detached from the worker. + */ + prependListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependOnceListener(event: "inspectorNotification", listener: (message: InspectorNotification<{}>) => void): this; + + /** + * Issued when new execution context is created. + */ + prependOnceListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when execution context is destroyed. + */ + prependOnceListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when all executionContexts were cleared in browser + */ + prependOnceListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + + /** + * Issued when exception was thrown and unhandled. + */ + prependOnceListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when unhandled exception was revoked. + */ + prependOnceListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when console API was called. + */ + prependOnceListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependOnceListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependOnceListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when virtual machine fails to parse the script. + */ + prependOnceListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependOnceListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependOnceListener(event: "Debugger.paused", listener: (message: InspectorNotification) => void): this; + + /** + * Fired when the virtual machine resumed execution. + */ + prependOnceListener(event: "Debugger.resumed", listener: () => void): this; + + /** + * Issued when new console message is added. + */ + prependOnceListener(event: "Console.messageAdded", listener: (message: InspectorNotification) => void): this; + + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependOnceListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification) => void): this; + + prependOnceListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification) => void): this; + prependOnceListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification) => void): this; + prependOnceListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependOnceListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependOnceListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification) => void): this; + + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependOnceListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification) => void): this; + + /** + * Contains an bucket of collected trace events. + */ + prependOnceListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification) => void): this; + + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependOnceListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + + /** + * Issued when attached to a worker. + */ + prependOnceListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Issued when detached from the worker. + */ + prependOnceListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependOnceListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification) => void): this; + + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependOnceListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + } + + // Top Level API + + /** + * Activate inspector on host and port. Equivalent to node --inspect=[[host:]port], but can be done programatically after node has started. + * If wait is true, will block until a client has connected to the inspect port and flow control has been passed to the debugger client. + * @param port Port to listen on for inspector connections. Optional, defaults to what was specified on the CLI. + * @param host Host to listen on for inspector connections. Optional, defaults to what was specified on the CLI. + * @param wait Block until a client has connected. Optional, defaults to false. + */ + function open(port?: number, host?: string, wait?: boolean): void; + + /** + * Deactivate the inspector. Blocks until there are no active connections. + */ + function close(): void; + + /** + * Return the URL of the active inspector, or `undefined` if there is none. + */ + function url(): string | undefined; + + /** + * Blocks until a client (existing or connected later) has sent + * `Runtime.runIfWaitingForDebugger` command. + * An exception will be thrown if there is no active inspector. + */ + function waitForDebugger(): void; +} diff --git a/node_modules/@types/node/module.d.ts b/node_modules/@types/node/module.d.ts new file mode 100755 index 0000000..0778bcd --- /dev/null +++ b/node_modules/@types/node/module.d.ts @@ -0,0 +1,57 @@ +declare module 'node:module' { + import Module = require('module'); + export = Module; +} + +declare module 'module' { + import { URL } from 'node:url'; + namespace Module { + /** + * Updates all the live bindings for builtin ES Modules to match the properties of the CommonJS exports. + * It does not add or remove exported names from the ES Modules. + */ + function syncBuiltinESMExports(): void; + + function findSourceMap(path: string, error?: Error): SourceMap; + interface SourceMapPayload { + file: string; + version: number; + sources: string[]; + sourcesContent: string[]; + names: string[]; + mappings: string; + sourceRoot: string; + } + + interface SourceMapping { + generatedLine: number; + generatedColumn: number; + originalSource: string; + originalLine: number; + originalColumn: number; + } + + class SourceMap { + readonly payload: SourceMapPayload; + constructor(payload: SourceMapPayload); + findEntry(line: number, column: number): SourceMapping; + } + } + interface Module extends NodeModule {} + class Module { + static runMain(): void; + static wrap(code: string): string; + + /** + * @deprecated Deprecated since: v12.2.0. Please use createRequire() instead. + */ + static createRequireFromPath(path: string): NodeRequire; + static createRequire(path: string | URL): NodeRequire; + static builtinModules: string[]; + + static Module: typeof Module; + + constructor(id: string, parent?: Module); + } + export = Module; +} diff --git a/node_modules/@types/node/net.d.ts b/node_modules/@types/node/net.d.ts new file mode 100755 index 0000000..7ef882a --- /dev/null +++ b/node_modules/@types/node/net.d.ts @@ -0,0 +1,328 @@ +declare module 'node:net' { + export * from 'net'; +} + +declare module 'net' { + import * as stream from 'node:stream'; + import EventEmitter = require('node:events'); + import * as dns from 'node:dns'; + + type LookupFunction = ( + hostname: string, + options: dns.LookupOneOptions, + callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, + ) => void; + + interface AddressInfo { + address: string; + family: string; + port: number; + } + + interface SocketConstructorOpts { + fd?: number; + allowHalfOpen?: boolean; + readable?: boolean; + writable?: boolean; + } + + interface OnReadOpts { + buffer: Uint8Array | (() => Uint8Array); + /** + * This function is called for every chunk of incoming data. + * Two arguments are passed to it: the number of bytes written to buffer and a reference to buffer. + * Return false from this function to implicitly pause() the socket. + */ + callback(bytesWritten: number, buf: Uint8Array): boolean; + } + + interface ConnectOpts { + /** + * If specified, incoming data is stored in a single buffer and passed to the supplied callback when data arrives on the socket. + * Note: this will cause the streaming functionality to not provide any data, however events like 'error', 'end', and 'close' will + * still be emitted as normal and methods like pause() and resume() will also behave as expected. + */ + onread?: OnReadOpts; + } + + interface TcpSocketConnectOpts extends ConnectOpts { + port: number; + host?: string; + localAddress?: string; + localPort?: number; + hints?: number; + family?: number; + lookup?: LookupFunction; + } + + interface IpcSocketConnectOpts extends ConnectOpts { + path: string; + } + + type SocketConnectOpts = TcpSocketConnectOpts | IpcSocketConnectOpts; + + class Socket extends stream.Duplex { + constructor(options?: SocketConstructorOpts); + + // Extended base methods + write(buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean; + write(str: Uint8Array | string, encoding?: BufferEncoding, cb?: (err?: Error) => void): boolean; + + connect(options: SocketConnectOpts, connectionListener?: () => void): this; + connect(port: number, host: string, connectionListener?: () => void): this; + connect(port: number, connectionListener?: () => void): this; + connect(path: string, connectionListener?: () => void): this; + + setEncoding(encoding?: BufferEncoding): this; + pause(): this; + resume(): this; + setTimeout(timeout: number, callback?: () => void): this; + setNoDelay(noDelay?: boolean): this; + setKeepAlive(enable?: boolean, initialDelay?: number): this; + address(): AddressInfo | {}; + unref(): this; + ref(): this; + + /** @deprecated since v14.6.0 - Use `writableLength` instead. */ + readonly bufferSize: number; + readonly bytesRead: number; + readonly bytesWritten: number; + readonly connecting: boolean; + readonly destroyed: boolean; + readonly localAddress: string; + readonly localPort: number; + readonly remoteAddress?: string; + readonly remoteFamily?: string; + readonly remotePort?: number; + + // Extended base methods + end(cb?: () => void): void; + end(buffer: Uint8Array | string, cb?: () => void): void; + end(str: Uint8Array | string, encoding?: BufferEncoding, cb?: () => void): void; + + /** + * events.EventEmitter + * 1. close + * 2. connect + * 3. data + * 4. drain + * 5. end + * 6. error + * 7. lookup + * 8. timeout + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: (had_error: boolean) => void): this; + addListener(event: "connect", listener: () => void): this; + addListener(event: "data", listener: (data: Buffer) => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + addListener(event: "timeout", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close", had_error: boolean): boolean; + emit(event: "connect"): boolean; + emit(event: "data", data: Buffer): boolean; + emit(event: "drain"): boolean; + emit(event: "end"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "lookup", err: Error, address: string, family: string | number, host: string): boolean; + emit(event: "timeout"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: (had_error: boolean) => void): this; + on(event: "connect", listener: () => void): this; + on(event: "data", listener: (data: Buffer) => void): this; + on(event: "drain", listener: () => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + on(event: "timeout", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: (had_error: boolean) => void): this; + once(event: "connect", listener: () => void): this; + once(event: "data", listener: (data: Buffer) => void): this; + once(event: "drain", listener: () => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + once(event: "timeout", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: (had_error: boolean) => void): this; + prependListener(event: "connect", listener: () => void): this; + prependListener(event: "data", listener: (data: Buffer) => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + prependListener(event: "timeout", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: (had_error: boolean) => void): this; + prependOnceListener(event: "connect", listener: () => void): this; + prependOnceListener(event: "data", listener: (data: Buffer) => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + } + + interface ListenOptions { + port?: number; + host?: string; + backlog?: number; + path?: string; + exclusive?: boolean; + readableAll?: boolean; + writableAll?: boolean; + /** + * @default false + */ + ipv6Only?: boolean; + } + + interface ServerOpts { + /** + * Indicates whether half-opened TCP connections are allowed. __Default:__ `false`. + */ + allowHalfOpen?: boolean; + + /** + * Indicates whether the socket should be paused on incoming connections. __Default:__ `false`. + */ + pauseOnConnect?: boolean; + } + + // https://github.com/nodejs/node/blob/master/lib/net.js + class Server extends EventEmitter { + constructor(connectionListener?: (socket: Socket) => void); + constructor(options?: ServerOpts, connectionListener?: (socket: Socket) => void); + + listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this; + listen(port?: number, hostname?: string, listeningListener?: () => void): this; + listen(port?: number, backlog?: number, listeningListener?: () => void): this; + listen(port?: number, listeningListener?: () => void): this; + listen(path: string, backlog?: number, listeningListener?: () => void): this; + listen(path: string, listeningListener?: () => void): this; + listen(options: ListenOptions, listeningListener?: () => void): this; + listen(handle: any, backlog?: number, listeningListener?: () => void): this; + listen(handle: any, listeningListener?: () => void): this; + close(callback?: (err?: Error) => void): this; + address(): AddressInfo | string | null; + getConnections(cb: (error: Error | null, count: number) => void): void; + ref(): this; + unref(): this; + maxConnections: number; + connections: number; + listening: boolean; + + /** + * events.EventEmitter + * 1. close + * 2. connection + * 3. error + * 4. listening + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "connection", listener: (socket: Socket) => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "listening", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "connection", socket: Socket): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "listening"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "connection", listener: (socket: Socket) => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "listening", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "connection", listener: (socket: Socket) => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "listening", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "connection", listener: (socket: Socket) => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "listening", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "connection", listener: (socket: Socket) => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "listening", listener: () => void): this; + } + + type IPVersion = 'ipv4' | 'ipv6'; + + class BlockList { + /** + * Adds a rule to block the given IP address. + * + * @param address An IPv4 or IPv6 address. + * @param type Either 'ipv4' or 'ipv6'. Default: 'ipv4'. + */ + addAddress(address: string, type?: IPVersion): void; + + /** + * Adds a rule to block a range of IP addresses from start (inclusive) to end (inclusive). + * + * @param start The starting IPv4 or IPv6 address in the range. + * @param end The ending IPv4 or IPv6 address in the range. + * @param type Either 'ipv4' or 'ipv6'. Default: 'ipv4'. + */ + addRange(start: string, end: string, type?: IPVersion): void; + + /** + * Adds a rule to block a range of IP addresses specified as a subnet mask. + * + * @param net The network IPv4 or IPv6 address. + * @param prefix The number of CIDR prefix bits. + * For IPv4, this must be a value between 0 and 32. For IPv6, this must be between 0 and 128. + * @param type Either 'ipv4' or 'ipv6'. Default: 'ipv4'. + */ + addSubnet(net: string, prefix: number, type?: IPVersion): void; + + /** + * Returns `true` if the given IP address matches any of the rules added to the `BlockList`. + * + * @param address The IP address to check + * @param type Either 'ipv4' or 'ipv6'. Default: 'ipv4'. + */ + check(address: string, type?: IPVersion): boolean; + } + + interface TcpNetConnectOpts extends TcpSocketConnectOpts, SocketConstructorOpts { + timeout?: number; + } + + interface IpcNetConnectOpts extends IpcSocketConnectOpts, SocketConstructorOpts { + timeout?: number; + } + + type NetConnectOpts = TcpNetConnectOpts | IpcNetConnectOpts; + + function createServer(connectionListener?: (socket: Socket) => void): Server; + function createServer(options?: ServerOpts, connectionListener?: (socket: Socket) => void): Server; + function connect(options: NetConnectOpts, connectionListener?: () => void): Socket; + function connect(port: number, host?: string, connectionListener?: () => void): Socket; + function connect(path: string, connectionListener?: () => void): Socket; + function createConnection(options: NetConnectOpts, connectionListener?: () => void): Socket; + function createConnection(port: number, host?: string, connectionListener?: () => void): Socket; + function createConnection(path: string, connectionListener?: () => void): Socket; + function isIP(input: string): number; + function isIPv4(input: string): boolean; + function isIPv6(input: string): boolean; +} diff --git a/node_modules/@types/node/os.d.ts b/node_modules/@types/node/os.d.ts new file mode 100755 index 0000000..f152ade --- /dev/null +++ b/node_modules/@types/node/os.d.ts @@ -0,0 +1,243 @@ +declare module 'node:os' { + export * from 'os'; +} + +declare module 'os' { + interface CpuInfo { + model: string; + speed: number; + times: { + user: number; + nice: number; + sys: number; + idle: number; + irq: number; + }; + } + + interface NetworkInterfaceBase { + address: string; + netmask: string; + mac: string; + internal: boolean; + cidr: string | null; + } + + interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase { + family: "IPv4"; + } + + interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase { + family: "IPv6"; + scopeid: number; + } + + interface UserInfo { + username: T; + uid: number; + gid: number; + shell: T; + homedir: T; + } + + type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6; + + function hostname(): string; + function loadavg(): number[]; + function uptime(): number; + function freemem(): number; + function totalmem(): number; + function cpus(): CpuInfo[]; + function type(): string; + function release(): string; + function networkInterfaces(): NodeJS.Dict; + function homedir(): string; + function userInfo(options: { encoding: 'buffer' }): UserInfo; + function userInfo(options?: { encoding: BufferEncoding }): UserInfo; + + type SignalConstants = { + [key in NodeJS.Signals]: number; + }; + + namespace constants { + const UV_UDP_REUSEADDR: number; + namespace signals {} + const signals: SignalConstants; + namespace errno { + const E2BIG: number; + const EACCES: number; + const EADDRINUSE: number; + const EADDRNOTAVAIL: number; + const EAFNOSUPPORT: number; + const EAGAIN: number; + const EALREADY: number; + const EBADF: number; + const EBADMSG: number; + const EBUSY: number; + const ECANCELED: number; + const ECHILD: number; + const ECONNABORTED: number; + const ECONNREFUSED: number; + const ECONNRESET: number; + const EDEADLK: number; + const EDESTADDRREQ: number; + const EDOM: number; + const EDQUOT: number; + const EEXIST: number; + const EFAULT: number; + const EFBIG: number; + const EHOSTUNREACH: number; + const EIDRM: number; + const EILSEQ: number; + const EINPROGRESS: number; + const EINTR: number; + const EINVAL: number; + const EIO: number; + const EISCONN: number; + const EISDIR: number; + const ELOOP: number; + const EMFILE: number; + const EMLINK: number; + const EMSGSIZE: number; + const EMULTIHOP: number; + const ENAMETOOLONG: number; + const ENETDOWN: number; + const ENETRESET: number; + const ENETUNREACH: number; + const ENFILE: number; + const ENOBUFS: number; + const ENODATA: number; + const ENODEV: number; + const ENOENT: number; + const ENOEXEC: number; + const ENOLCK: number; + const ENOLINK: number; + const ENOMEM: number; + const ENOMSG: number; + const ENOPROTOOPT: number; + const ENOSPC: number; + const ENOSR: number; + const ENOSTR: number; + const ENOSYS: number; + const ENOTCONN: number; + const ENOTDIR: number; + const ENOTEMPTY: number; + const ENOTSOCK: number; + const ENOTSUP: number; + const ENOTTY: number; + const ENXIO: number; + const EOPNOTSUPP: number; + const EOVERFLOW: number; + const EPERM: number; + const EPIPE: number; + const EPROTO: number; + const EPROTONOSUPPORT: number; + const EPROTOTYPE: number; + const ERANGE: number; + const EROFS: number; + const ESPIPE: number; + const ESRCH: number; + const ESTALE: number; + const ETIME: number; + const ETIMEDOUT: number; + const ETXTBSY: number; + const EWOULDBLOCK: number; + const EXDEV: number; + const WSAEINTR: number; + const WSAEBADF: number; + const WSAEACCES: number; + const WSAEFAULT: number; + const WSAEINVAL: number; + const WSAEMFILE: number; + const WSAEWOULDBLOCK: number; + const WSAEINPROGRESS: number; + const WSAEALREADY: number; + const WSAENOTSOCK: number; + const WSAEDESTADDRREQ: number; + const WSAEMSGSIZE: number; + const WSAEPROTOTYPE: number; + const WSAENOPROTOOPT: number; + const WSAEPROTONOSUPPORT: number; + const WSAESOCKTNOSUPPORT: number; + const WSAEOPNOTSUPP: number; + const WSAEPFNOSUPPORT: number; + const WSAEAFNOSUPPORT: number; + const WSAEADDRINUSE: number; + const WSAEADDRNOTAVAIL: number; + const WSAENETDOWN: number; + const WSAENETUNREACH: number; + const WSAENETRESET: number; + const WSAECONNABORTED: number; + const WSAECONNRESET: number; + const WSAENOBUFS: number; + const WSAEISCONN: number; + const WSAENOTCONN: number; + const WSAESHUTDOWN: number; + const WSAETOOMANYREFS: number; + const WSAETIMEDOUT: number; + const WSAECONNREFUSED: number; + const WSAELOOP: number; + const WSAENAMETOOLONG: number; + const WSAEHOSTDOWN: number; + const WSAEHOSTUNREACH: number; + const WSAENOTEMPTY: number; + const WSAEPROCLIM: number; + const WSAEUSERS: number; + const WSAEDQUOT: number; + const WSAESTALE: number; + const WSAEREMOTE: number; + const WSASYSNOTREADY: number; + const WSAVERNOTSUPPORTED: number; + const WSANOTINITIALISED: number; + const WSAEDISCON: number; + const WSAENOMORE: number; + const WSAECANCELLED: number; + const WSAEINVALIDPROCTABLE: number; + const WSAEINVALIDPROVIDER: number; + const WSAEPROVIDERFAILEDINIT: number; + const WSASYSCALLFAILURE: number; + const WSASERVICE_NOT_FOUND: number; + const WSATYPE_NOT_FOUND: number; + const WSA_E_NO_MORE: number; + const WSA_E_CANCELLED: number; + const WSAEREFUSED: number; + } + namespace priority { + const PRIORITY_LOW: number; + const PRIORITY_BELOW_NORMAL: number; + const PRIORITY_NORMAL: number; + const PRIORITY_ABOVE_NORMAL: number; + const PRIORITY_HIGH: number; + const PRIORITY_HIGHEST: number; + } + } + + function arch(): string; + /** + * Returns a string identifying the kernel version. + * On POSIX systems, the operating system release is determined by calling + * [uname(3)][]. On Windows, `pRtlGetVersion` is used, and if it is not available, + * `GetVersionExW()` will be used. See + * https://en.wikipedia.org/wiki/Uname#Examples for more information. + */ + function version(): string; + function platform(): NodeJS.Platform; + function tmpdir(): string; + const EOL: string; + function endianness(): "BE" | "LE"; + /** + * Gets the priority of a process. + * Defaults to current process. + */ + function getPriority(pid?: number): number; + /** + * Sets the priority of the current process. + * @param priority Must be in range of -20 to 19 + */ + function setPriority(priority: number): void; + /** + * Sets the priority of the process specified process. + * @param priority Must be in range of -20 to 19 + */ + function setPriority(pid: number, priority: number): void; +} diff --git a/node_modules/@types/node/package.json b/node_modules/@types/node/package.json new file mode 100755 index 0000000..0f23712 --- /dev/null +++ b/node_modules/@types/node/package.json @@ -0,0 +1,231 @@ +{ + "name": "@types/node", + "version": "15.0.1", + "description": "TypeScript definitions for Node.js", + "license": "MIT", + "contributors": [ + { + "name": "Microsoft TypeScript", + "url": "https://github.com/Microsoft", + "githubUsername": "Microsoft" + }, + { + "name": "DefinitelyTyped", + "url": "https://github.com/DefinitelyTyped", + "githubUsername": "DefinitelyTyped" + }, + { + "name": "Alberto Schiabel", + "url": "https://github.com/jkomyno", + "githubUsername": "jkomyno" + }, + { + "name": "Alvis HT Tang", + "url": "https://github.com/alvis", + "githubUsername": "alvis" + }, + { + "name": "Andrew Makarov", + "url": "https://github.com/r3nya", + "githubUsername": "r3nya" + }, + { + "name": "Benjamin Toueg", + "url": "https://github.com/btoueg", + "githubUsername": "btoueg" + }, + { + "name": "Chigozirim C.", + "url": "https://github.com/smac89", + "githubUsername": "smac89" + }, + { + "name": "David Junger", + "url": "https://github.com/touffy", + "githubUsername": "touffy" + }, + { + "name": "Deividas Bakanas", + "url": "https://github.com/DeividasBakanas", + "githubUsername": "DeividasBakanas" + }, + { + "name": "Eugene Y. Q. Shen", + "url": "https://github.com/eyqs", + "githubUsername": "eyqs" + }, + { + "name": "Hannes Magnusson", + "url": "https://github.com/Hannes-Magnusson-CK", + "githubUsername": "Hannes-Magnusson-CK" + }, + { + "name": "Hoàng Văn Khải", + "url": "https://github.com/KSXGitHub", + "githubUsername": "KSXGitHub" + }, + { + "name": "Huw", + "url": "https://github.com/hoo29", + "githubUsername": "hoo29" + }, + { + "name": "Kelvin Jin", + "url": "https://github.com/kjin", + "githubUsername": "kjin" + }, + { + "name": "Klaus Meinhardt", + "url": "https://github.com/ajafff", + "githubUsername": "ajafff" + }, + { + "name": "Lishude", + "url": "https://github.com/islishude", + "githubUsername": "islishude" + }, + { + "name": "Mariusz Wiktorczyk", + "url": "https://github.com/mwiktorczyk", + "githubUsername": "mwiktorczyk" + }, + { + "name": "Mohsen Azimi", + "url": "https://github.com/mohsen1", + "githubUsername": "mohsen1" + }, + { + "name": "Nicolas Even", + "url": "https://github.com/n-e", + "githubUsername": "n-e" + }, + { + "name": "Nikita Galkin", + "url": "https://github.com/galkin", + "githubUsername": "galkin" + }, + { + "name": "Parambir Singh", + "url": "https://github.com/parambirs", + "githubUsername": "parambirs" + }, + { + "name": "Sebastian Silbermann", + "url": "https://github.com/eps1lon", + "githubUsername": "eps1lon" + }, + { + "name": "Simon Schick", + "url": "https://github.com/SimonSchick", + "githubUsername": "SimonSchick" + }, + { + "name": "Thomas den Hollander", + "url": "https://github.com/ThomasdenH", + "githubUsername": "ThomasdenH" + }, + { + "name": "Wilco Bakker", + "url": "https://github.com/WilcoBakker", + "githubUsername": "WilcoBakker" + }, + { + "name": "wwwy3y3", + "url": "https://github.com/wwwy3y3", + "githubUsername": "wwwy3y3" + }, + { + "name": "Samuel Ainsworth", + "url": "https://github.com/samuela", + "githubUsername": "samuela" + }, + { + "name": "Kyle Uehlein", + "url": "https://github.com/kuehlein", + "githubUsername": "kuehlein" + }, + { + "name": "Thanik Bhongbhibhat", + "url": "https://github.com/bhongy", + "githubUsername": "bhongy" + }, + { + "name": "Marcin Kopacz", + "url": "https://github.com/chyzwar", + "githubUsername": "chyzwar" + }, + { + "name": "Trivikram Kamat", + "url": "https://github.com/trivikr", + "githubUsername": "trivikr" + }, + { + "name": "Minh Son Nguyen", + "url": "https://github.com/nguymin4", + "githubUsername": "nguymin4" + }, + { + "name": "Junxiao Shi", + "url": "https://github.com/yoursunny", + "githubUsername": "yoursunny" + }, + { + "name": "Ilia Baryshnikov", + "url": "https://github.com/qwelias", + "githubUsername": "qwelias" + }, + { + "name": "ExE Boss", + "url": "https://github.com/ExE-Boss", + "githubUsername": "ExE-Boss" + }, + { + "name": "Surasak Chaisurin", + "url": "https://github.com/Ryan-Willpower", + "githubUsername": "Ryan-Willpower" + }, + { + "name": "Piotr Błażejewicz", + "url": "https://github.com/peterblazejewicz", + "githubUsername": "peterblazejewicz" + }, + { + "name": "Anna Henningsen", + "url": "https://github.com/addaleax", + "githubUsername": "addaleax" + }, + { + "name": "Jason Kwok", + "url": "https://github.com/JasonHK", + "githubUsername": "JasonHK" + }, + { + "name": "Victor Perin", + "url": "https://github.com/victorperin", + "githubUsername": "victorperin" + }, + { + "name": "Yongsheng Zhang", + "url": "https://github.com/ZYSzys", + "githubUsername": "ZYSzys" + } + ], + "main": "", + "types": "index.d.ts", + "typesVersions": { + "<=3.6": { + "*": [ + "ts3.6/*" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/node" + }, + "scripts": {}, + "dependencies": {}, + "typesPublisherContentHash": "1f56531114fdab066269305f7c1d7188e8e2ca2aa02bbefafb728e755115b0f2", + "typeScriptVersion": "3.5" +} \ No newline at end of file diff --git a/node_modules/@types/node/path.d.ts b/node_modules/@types/node/path.d.ts new file mode 100755 index 0000000..39adcaf --- /dev/null +++ b/node_modules/@types/node/path.d.ts @@ -0,0 +1,158 @@ +declare module 'node:path' { + import path = require('path'); + export = path; +} + +declare module 'path' { + namespace path { + /** + * A parsed path object generated by path.parse() or consumed by path.format(). + */ + interface ParsedPath { + /** + * The root of the path such as '/' or 'c:\' + */ + root: string; + /** + * The full directory path such as '/home/user/dir' or 'c:\path\dir' + */ + dir: string; + /** + * The file name including extension (if any) such as 'index.html' + */ + base: string; + /** + * The file extension (if any) such as '.html' + */ + ext: string; + /** + * The file name without extension (if any) such as 'index' + */ + name: string; + } + + interface FormatInputPathObject { + /** + * The root of the path such as '/' or 'c:\' + */ + root?: string; + /** + * The full directory path such as '/home/user/dir' or 'c:\path\dir' + */ + dir?: string; + /** + * The file name including extension (if any) such as 'index.html' + */ + base?: string; + /** + * The file extension (if any) such as '.html' + */ + ext?: string; + /** + * The file name without extension (if any) such as 'index' + */ + name?: string; + } + + interface PlatformPath { + /** + * Normalize a string path, reducing '..' and '.' parts. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * + * @param p string path to normalize. + */ + normalize(p: string): string; + /** + * Join all arguments together and normalize the resulting path. + * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. + * + * @param paths paths to join. + */ + join(...paths: string[]): string; + /** + * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. + * + * Starting from leftmost {from} parameter, resolves {to} to an absolute path. + * + * If {to} isn't already absolute, {from} arguments are prepended in right to left order, + * until an absolute path is found. If after using all {from} paths still no absolute path is found, + * the current working directory is used as well. The resulting path is normalized, + * and trailing slashes are removed unless the path gets resolved to the root directory. + * + * @param pathSegments string paths to join. Non-string arguments are ignored. + */ + resolve(...pathSegments: string[]): string; + /** + * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. + * + * @param path path to test. + */ + isAbsolute(p: string): boolean; + /** + * Solve the relative path from {from} to {to}. + * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. + */ + relative(from: string, to: string): string; + /** + * Return the directory name of a path. Similar to the Unix dirname command. + * + * @param p the path to evaluate. + */ + dirname(p: string): string; + /** + * Return the last portion of a path. Similar to the Unix basename command. + * Often used to extract the file name from a fully qualified path. + * + * @param p the path to evaluate. + * @param ext optionally, an extension to remove from the result. + */ + basename(p: string, ext?: string): string; + /** + * Return the extension of the path, from the last '.' to end of string in the last portion of the path. + * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string + * + * @param p the path to evaluate. + */ + extname(p: string): string; + /** + * The platform-specific file separator. '\\' or '/'. + */ + readonly sep: string; + /** + * The platform-specific file delimiter. ';' or ':'. + */ + readonly delimiter: string; + /** + * Returns an object from a path string - the opposite of format(). + * + * @param pathString path to evaluate. + */ + parse(p: string): ParsedPath; + /** + * Returns a path string from an object - the opposite of parse(). + * + * @param pathString path to evaluate. + */ + format(pP: FormatInputPathObject): string; + /** + * On Windows systems only, returns an equivalent namespace-prefixed path for the given path. + * If path is not a string, path will be returned without modifications. + * This method is meaningful only on Windows system. + * On POSIX systems, the method is non-operational and always returns path without modifications. + */ + toNamespacedPath(path: string): string; + /** + * Posix specific pathing. + * Same as parent object on posix. + */ + readonly posix: PlatformPath; + /** + * Windows specific pathing. + * Same as parent object on windows + */ + readonly win32: PlatformPath; + } + } + const path: path.PlatformPath; + export = path; +} diff --git a/node_modules/@types/node/perf_hooks.d.ts b/node_modules/@types/node/perf_hooks.d.ts new file mode 100755 index 0000000..6c858ef --- /dev/null +++ b/node_modules/@types/node/perf_hooks.d.ts @@ -0,0 +1,275 @@ +declare module 'node:perf_hooks' { + export * from 'perf_hooks'; +} + +declare module 'perf_hooks' { + import { AsyncResource } from 'node:async_hooks'; + + type EntryType = 'node' | 'mark' | 'measure' | 'gc' | 'function' | 'http2' | 'http'; + + interface PerformanceEntry { + /** + * The total number of milliseconds elapsed for this entry. + * This value will not be meaningful for all Performance Entry types. + */ + readonly duration: number; + + /** + * The name of the performance entry. + */ + readonly name: string; + + /** + * The high resolution millisecond timestamp marking the starting time of the Performance Entry. + */ + readonly startTime: number; + + /** + * The type of the performance entry. + * Currently it may be one of: 'node', 'mark', 'measure', 'gc', or 'function'. + */ + readonly entryType: EntryType; + + /** + * When `performanceEntry.entryType` is equal to 'gc', `the performance.kind` property identifies + * the type of garbage collection operation that occurred. + * See perf_hooks.constants for valid values. + */ + readonly kind?: number; + + /** + * When `performanceEntry.entryType` is equal to 'gc', the `performance.flags` + * property contains additional information about garbage collection operation. + * See perf_hooks.constants for valid values. + */ + readonly flags?: number; + } + + interface PerformanceNodeTiming extends PerformanceEntry { + /** + * The high resolution millisecond timestamp at which the Node.js process completed bootstrap. + */ + readonly bootstrapComplete: number; + + /** + * The high resolution millisecond timestamp at which the Node.js process completed bootstrapping. + * If bootstrapping has not yet finished, the property has the value of -1. + */ + readonly environment: number; + + /** + * The high resolution millisecond timestamp at which the Node.js environment was initialized. + */ + readonly idleTime: number; + + /** + * The high resolution millisecond timestamp of the amount of time the event loop has been idle + * within the event loop's event provider (e.g. `epoll_wait`). This does not take CPU usage + * into consideration. If the event loop has not yet started (e.g., in the first tick of the main script), + * the property has the value of 0. + */ + readonly loopExit: number; + + /** + * The high resolution millisecond timestamp at which the Node.js event loop started. + * If the event loop has not yet started (e.g., in the first tick of the main script), the property has the value of -1. + */ + readonly loopStart: number; + + /** + * The high resolution millisecond timestamp at which the V8 platform was initialized. + */ + readonly v8Start: number; + } + + interface EventLoopUtilization { + idle: number; + active: number; + utilization: number; + } + + interface Performance { + /** + * If name is not provided, removes all PerformanceMark objects from the Performance Timeline. + * If name is provided, removes only the named mark. + * @param name + */ + clearMarks(name?: string): void; + + /** + * Creates a new PerformanceMark entry in the Performance Timeline. + * A PerformanceMark is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'mark', + * and whose performanceEntry.duration is always 0. + * Performance marks are used to mark specific significant moments in the Performance Timeline. + * @param name + */ + mark(name?: string): void; + + /** + * Creates a new PerformanceMeasure entry in the Performance Timeline. + * A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure', + * and whose performanceEntry.duration measures the number of milliseconds elapsed since startMark and endMark. + * + * The startMark argument may identify any existing PerformanceMark in the the Performance Timeline, or may identify + * any of the timestamp properties provided by the PerformanceNodeTiming class. If the named startMark does not exist, + * then startMark is set to timeOrigin by default. + * + * The endMark argument must identify any existing PerformanceMark in the the Performance Timeline or any of the timestamp + * properties provided by the PerformanceNodeTiming class. If the named endMark does not exist, an error will be thrown. + * @param name + * @param startMark + * @param endMark + */ + measure(name: string, startMark: string, endMark: string): void; + + /** + * An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones. + */ + readonly nodeTiming: PerformanceNodeTiming; + + /** + * @return the current high resolution millisecond timestamp + */ + now(): number; + + /** + * The timeOrigin specifies the high resolution millisecond timestamp from which all performance metric durations are measured. + */ + readonly timeOrigin: number; + + /** + * Wraps a function within a new function that measures the running time of the wrapped function. + * A PerformanceObserver must be subscribed to the 'function' event type in order for the timing details to be accessed. + * @param fn + */ + timerify any>(fn: T): T; + + /** + * eventLoopUtilization is similar to CPU utilization except that it is calculated using high precision wall-clock time. + * It represents the percentage of time the event loop has spent outside the event loop's event provider (e.g. epoll_wait). + * No other CPU idle time is taken into consideration. + * + * @param util1 The result of a previous call to eventLoopUtilization() + * @param util2 The result of a previous call to eventLoopUtilization() prior to util1 + */ + eventLoopUtilization(util1?: EventLoopUtilization, util2?: EventLoopUtilization): EventLoopUtilization; + } + + interface PerformanceObserverEntryList { + /** + * @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime. + */ + getEntries(): PerformanceEntry[]; + + /** + * @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime + * whose performanceEntry.name is equal to name, and optionally, whose performanceEntry.entryType is equal to type. + */ + getEntriesByName(name: string, type?: EntryType): PerformanceEntry[]; + + /** + * @return Returns a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime + * whose performanceEntry.entryType is equal to type. + */ + getEntriesByType(type: EntryType): PerformanceEntry[]; + } + + type PerformanceObserverCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void; + + class PerformanceObserver extends AsyncResource { + constructor(callback: PerformanceObserverCallback); + + /** + * Disconnects the PerformanceObserver instance from all notifications. + */ + disconnect(): void; + + /** + * Subscribes the PerformanceObserver instance to notifications of new PerformanceEntry instances identified by options.entryTypes. + * When options.buffered is false, the callback will be invoked once for every PerformanceEntry instance. + * Property buffered defaults to false. + * @param options + */ + observe(options: { entryTypes: ReadonlyArray; buffered?: boolean }): void; + } + + namespace constants { + const NODE_PERFORMANCE_GC_MAJOR: number; + const NODE_PERFORMANCE_GC_MINOR: number; + const NODE_PERFORMANCE_GC_INCREMENTAL: number; + const NODE_PERFORMANCE_GC_WEAKCB: number; + + const NODE_PERFORMANCE_GC_FLAGS_NO: number; + const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number; + const NODE_PERFORMANCE_GC_FLAGS_FORCED: number; + const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number; + const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number; + const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number; + const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number; + } + + const performance: Performance; + + interface EventLoopMonitorOptions { + /** + * The sampling rate in milliseconds. + * Must be greater than zero. + * @default 10 + */ + resolution?: number; + } + + interface EventLoopDelayMonitor { + /** + * Enables the event loop delay sample timer. Returns `true` if the timer was started, `false` if it was already started. + */ + enable(): boolean; + /** + * Disables the event loop delay sample timer. Returns `true` if the timer was stopped, `false` if it was already stopped. + */ + disable(): boolean; + + /** + * Resets the collected histogram data. + */ + reset(): void; + + /** + * Returns the value at the given percentile. + * @param percentile A percentile value between 1 and 100. + */ + percentile(percentile: number): number; + + /** + * A `Map` object detailing the accumulated percentile distribution. + */ + readonly percentiles: Map; + + /** + * The number of times the event loop delay exceeded the maximum 1 hour eventloop delay threshold. + */ + readonly exceeds: number; + + /** + * The minimum recorded event loop delay. + */ + readonly min: number; + + /** + * The maximum recorded event loop delay. + */ + readonly max: number; + + /** + * The mean of the recorded event loop delays. + */ + readonly mean: number; + + /** + * The standard deviation of the recorded event loop delays. + */ + readonly stddev: number; + } + + function monitorEventLoopDelay(options?: EventLoopMonitorOptions): EventLoopDelayMonitor; +} diff --git a/node_modules/@types/node/process.d.ts b/node_modules/@types/node/process.d.ts new file mode 100755 index 0000000..2babb16 --- /dev/null +++ b/node_modules/@types/node/process.d.ts @@ -0,0 +1,453 @@ +declare module 'node:process' { + export = process; +} + +declare module 'process' { + import * as tty from 'node:tty'; + + global { + var process: NodeJS.Process; + + namespace NodeJS { + // this namespace merge is here because these are specifically used + // as the type for process.stdin, process.stdout, and process.stderr. + // they can't live in tty.d.ts because we need to disambiguate the imported name. + interface ReadStream extends tty.ReadStream {} + interface WriteStream extends tty.WriteStream {} + + interface MemoryUsage { + rss: number; + heapTotal: number; + heapUsed: number; + external: number; + arrayBuffers: number; + } + + interface CpuUsage { + user: number; + system: number; + } + + interface ProcessRelease { + name: string; + sourceUrl?: string; + headersUrl?: string; + libUrl?: string; + lts?: string; + } + + interface ProcessVersions extends Dict { + http_parser: string; + node: string; + v8: string; + ares: string; + uv: string; + zlib: string; + modules: string; + openssl: string; + } + + type Platform = 'aix' + | 'android' + | 'darwin' + | 'freebsd' + | 'linux' + | 'openbsd' + | 'sunos' + | 'win32' + | 'cygwin' + | 'netbsd'; + + type Signals = + "SIGABRT" | "SIGALRM" | "SIGBUS" | "SIGCHLD" | "SIGCONT" | "SIGFPE" | "SIGHUP" | "SIGILL" | "SIGINT" | "SIGIO" | + "SIGIOT" | "SIGKILL" | "SIGPIPE" | "SIGPOLL" | "SIGPROF" | "SIGPWR" | "SIGQUIT" | "SIGSEGV" | "SIGSTKFLT" | + "SIGSTOP" | "SIGSYS" | "SIGTERM" | "SIGTRAP" | "SIGTSTP" | "SIGTTIN" | "SIGTTOU" | "SIGUNUSED" | "SIGURG" | + "SIGUSR1" | "SIGUSR2" | "SIGVTALRM" | "SIGWINCH" | "SIGXCPU" | "SIGXFSZ" | "SIGBREAK" | "SIGLOST" | "SIGINFO"; + + type MultipleResolveType = 'resolve' | 'reject'; + + type BeforeExitListener = (code: number) => void; + type DisconnectListener = () => void; + type ExitListener = (code: number) => void; + type RejectionHandledListener = (promise: Promise) => void; + type UncaughtExceptionListener = (error: Error) => void; + type UnhandledRejectionListener = (reason: {} | null | undefined, promise: Promise) => void; + type WarningListener = (warning: Error) => void; + type MessageListener = (message: any, sendHandle: any) => void; + type SignalsListener = (signal: Signals) => void; + type NewListenerListener = (type: string | symbol, listener: (...args: any[]) => void) => void; + type RemoveListenerListener = (type: string | symbol, listener: (...args: any[]) => void) => void; + type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: any) => void; + + interface Socket extends ReadWriteStream { + isTTY?: true; + } + + // Alias for compatibility + interface ProcessEnv extends Dict {} + + interface HRTime { + (time?: [number, number]): [number, number]; + bigint(): bigint; + } + + interface ProcessReport { + /** + * Directory where the report is written. + * working directory of the Node.js process. + * @default '' indicating that reports are written to the current + */ + directory: string; + + /** + * Filename where the report is written. + * The default value is the empty string. + * @default '' the output filename will be comprised of a timestamp, + * PID, and sequence number. + */ + filename: string; + + /** + * Returns a JSON-formatted diagnostic report for the running process. + * The report's JavaScript stack trace is taken from err, if present. + */ + getReport(err?: Error): string; + + /** + * If true, a diagnostic report is generated on fatal errors, + * such as out of memory errors or failed C++ assertions. + * @default false + */ + reportOnFatalError: boolean; + + /** + * If true, a diagnostic report is generated when the process + * receives the signal specified by process.report.signal. + * @defaul false + */ + reportOnSignal: boolean; + + /** + * If true, a diagnostic report is generated on uncaught exception. + * @default false + */ + reportOnUncaughtException: boolean; + + /** + * The signal used to trigger the creation of a diagnostic report. + * @default 'SIGUSR2' + */ + signal: Signals; + + /** + * Writes a diagnostic report to a file. If filename is not provided, the default filename + * includes the date, time, PID, and a sequence number. + * The report's JavaScript stack trace is taken from err, if present. + * + * @param fileName Name of the file where the report is written. + * This should be a relative path, that will be appended to the directory specified in + * `process.report.directory`, or the current working directory of the Node.js process, + * if unspecified. + * @param error A custom error used for reporting the JavaScript stack. + * @return Filename of the generated report. + */ + writeReport(fileName?: string): string; + writeReport(error?: Error): string; + writeReport(fileName?: string, err?: Error): string; + } + + interface ResourceUsage { + fsRead: number; + fsWrite: number; + involuntaryContextSwitches: number; + ipcReceived: number; + ipcSent: number; + majorPageFault: number; + maxRSS: number; + minorPageFault: number; + sharedMemorySize: number; + signalsCount: number; + swappedOut: number; + systemCPUTime: number; + unsharedDataSize: number; + unsharedStackSize: number; + userCPUTime: number; + voluntaryContextSwitches: number; + } + + interface EmitWarningOptions { + /** + * When `warning` is a `string`, `type` is the name to use for the _type_ of warning being emitted. + * + * @default 'Warning' + */ + type?: string; + + /** + * A unique identifier for the warning instance being emitted. + */ + code?: string; + + /** + * When `warning` is a `string`, `ctor` is an optional function used to limit the generated stack trace. + * + * @default process.emitWarning + */ + ctor?: Function; + + /** + * Additional text to include with the error. + */ + detail?: string; + } + + interface Process extends EventEmitter { + /** + * Can also be a tty.WriteStream, not typed due to limitations. + */ + stdout: WriteStream & { + fd: 1; + }; + /** + * Can also be a tty.WriteStream, not typed due to limitations. + */ + stderr: WriteStream & { + fd: 2; + }; + stdin: ReadStream & { + fd: 0; + }; + openStdin(): Socket; + argv: string[]; + argv0: string; + execArgv: string[]; + execPath: string; + abort(): never; + chdir(directory: string): void; + cwd(): string; + debugPort: number; + + /** + * The `process.emitWarning()` method can be used to emit custom or application specific process warnings. + * + * These can be listened for by adding a handler to the `'warning'` event. + * + * @param warning The warning to emit. + * @param type When `warning` is a `string`, `type` is the name to use for the _type_ of warning being emitted. Default: `'Warning'`. + * @param code A unique identifier for the warning instance being emitted. + * @param ctor When `warning` is a `string`, `ctor` is an optional function used to limit the generated stack trace. Default: `process.emitWarning`. + */ + emitWarning(warning: string | Error, ctor?: Function): void; + emitWarning(warning: string | Error, type?: string, ctor?: Function): void; + emitWarning(warning: string | Error, type?: string, code?: string, ctor?: Function): void; + emitWarning(warning: string | Error, options?: EmitWarningOptions): void; + + env: ProcessEnv; + exit(code?: number): never; + exitCode?: number; + getgid(): number; + setgid(id: number | string): void; + getuid(): number; + setuid(id: number | string): void; + geteuid(): number; + seteuid(id: number | string): void; + getegid(): number; + setegid(id: number | string): void; + getgroups(): number[]; + setgroups(groups: ReadonlyArray): void; + setUncaughtExceptionCaptureCallback(cb: ((err: Error) => void) | null): void; + hasUncaughtExceptionCaptureCallback(): boolean; + version: string; + versions: ProcessVersions; + config: { + target_defaults: { + cflags: any[]; + default_configuration: string; + defines: string[]; + include_dirs: string[]; + libraries: string[]; + }; + variables: { + clang: number; + host_arch: string; + node_install_npm: boolean; + node_install_waf: boolean; + node_prefix: string; + node_shared_openssl: boolean; + node_shared_v8: boolean; + node_shared_zlib: boolean; + node_use_dtrace: boolean; + node_use_etw: boolean; + node_use_openssl: boolean; + target_arch: string; + v8_no_strict_aliasing: number; + v8_use_snapshot: boolean; + visibility: string; + }; + }; + kill(pid: number, signal?: string | number): true; + pid: number; + ppid: number; + title: string; + arch: string; + platform: Platform; + /** @deprecated since v14.0.0 - use `require.main` instead. */ + mainModule?: Module; + memoryUsage(): MemoryUsage; + cpuUsage(previousValue?: CpuUsage): CpuUsage; + nextTick(callback: Function, ...args: any[]): void; + release: ProcessRelease; + features: { + inspector: boolean; + debug: boolean; + uv: boolean; + ipv6: boolean; + tls_alpn: boolean; + tls_sni: boolean; + tls_ocsp: boolean; + tls: boolean; + }; + /** + * @deprecated since v14.0.0 - Calling process.umask() with no argument causes + * the process-wide umask to be written twice. This introduces a race condition between threads, + * and is a potential security vulnerability. There is no safe, cross-platform alternative API. + */ + umask(): number; + /** + * Can only be set if not in worker thread. + */ + umask(mask: string | number): number; + uptime(): number; + hrtime: HRTime; + domain: Domain; + + // Worker + send?(message: any, sendHandle?: any, options?: { swallowErrors?: boolean}, callback?: (error: Error | null) => void): boolean; + disconnect(): void; + connected: boolean; + + /** + * The `process.allowedNodeEnvironmentFlags` property is a special, + * read-only `Set` of flags allowable within the [`NODE_OPTIONS`][] + * environment variable. + */ + allowedNodeEnvironmentFlags: ReadonlySet; + + /** + * Only available with `--experimental-report` + */ + report?: ProcessReport; + + resourceUsage(): ResourceUsage; + + traceDeprecation: boolean; + + /* EventEmitter */ + addListener(event: "beforeExit", listener: BeforeExitListener): this; + addListener(event: "disconnect", listener: DisconnectListener): this; + addListener(event: "exit", listener: ExitListener): this; + addListener(event: "rejectionHandled", listener: RejectionHandledListener): this; + addListener(event: "uncaughtException", listener: UncaughtExceptionListener): this; + addListener(event: "uncaughtExceptionMonitor", listener: UncaughtExceptionListener): this; + addListener(event: "unhandledRejection", listener: UnhandledRejectionListener): this; + addListener(event: "warning", listener: WarningListener): this; + addListener(event: "message", listener: MessageListener): this; + addListener(event: Signals, listener: SignalsListener): this; + addListener(event: "newListener", listener: NewListenerListener): this; + addListener(event: "removeListener", listener: RemoveListenerListener): this; + addListener(event: "multipleResolves", listener: MultipleResolveListener): this; + + emit(event: "beforeExit", code: number): boolean; + emit(event: "disconnect"): boolean; + emit(event: "exit", code: number): boolean; + emit(event: "rejectionHandled", promise: Promise): boolean; + emit(event: "uncaughtException", error: Error): boolean; + emit(event: "uncaughtExceptionMonitor", error: Error): boolean; + emit(event: "unhandledRejection", reason: any, promise: Promise): boolean; + emit(event: "warning", warning: Error): boolean; + emit(event: "message", message: any, sendHandle: any): this; + emit(event: Signals, signal: Signals): boolean; + emit(event: "newListener", eventName: string | symbol, listener: (...args: any[]) => void): this; + emit(event: "removeListener", eventName: string, listener: (...args: any[]) => void): this; + emit(event: "multipleResolves", listener: MultipleResolveListener): this; + + on(event: "beforeExit", listener: BeforeExitListener): this; + on(event: "disconnect", listener: DisconnectListener): this; + on(event: "exit", listener: ExitListener): this; + on(event: "rejectionHandled", listener: RejectionHandledListener): this; + on(event: "uncaughtException", listener: UncaughtExceptionListener): this; + on(event: "uncaughtExceptionMonitor", listener: UncaughtExceptionListener): this; + on(event: "unhandledRejection", listener: UnhandledRejectionListener): this; + on(event: "warning", listener: WarningListener): this; + on(event: "message", listener: MessageListener): this; + on(event: Signals, listener: SignalsListener): this; + on(event: "newListener", listener: NewListenerListener): this; + on(event: "removeListener", listener: RemoveListenerListener): this; + on(event: "multipleResolves", listener: MultipleResolveListener): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "beforeExit", listener: BeforeExitListener): this; + once(event: "disconnect", listener: DisconnectListener): this; + once(event: "exit", listener: ExitListener): this; + once(event: "rejectionHandled", listener: RejectionHandledListener): this; + once(event: "uncaughtException", listener: UncaughtExceptionListener): this; + once(event: "uncaughtExceptionMonitor", listener: UncaughtExceptionListener): this; + once(event: "unhandledRejection", listener: UnhandledRejectionListener): this; + once(event: "warning", listener: WarningListener): this; + once(event: "message", listener: MessageListener): this; + once(event: Signals, listener: SignalsListener): this; + once(event: "newListener", listener: NewListenerListener): this; + once(event: "removeListener", listener: RemoveListenerListener): this; + once(event: "multipleResolves", listener: MultipleResolveListener): this; + + prependListener(event: "beforeExit", listener: BeforeExitListener): this; + prependListener(event: "disconnect", listener: DisconnectListener): this; + prependListener(event: "exit", listener: ExitListener): this; + prependListener(event: "rejectionHandled", listener: RejectionHandledListener): this; + prependListener(event: "uncaughtException", listener: UncaughtExceptionListener): this; + prependListener(event: "uncaughtExceptionMonitor", listener: UncaughtExceptionListener): this; + prependListener(event: "unhandledRejection", listener: UnhandledRejectionListener): this; + prependListener(event: "warning", listener: WarningListener): this; + prependListener(event: "message", listener: MessageListener): this; + prependListener(event: Signals, listener: SignalsListener): this; + prependListener(event: "newListener", listener: NewListenerListener): this; + prependListener(event: "removeListener", listener: RemoveListenerListener): this; + prependListener(event: "multipleResolves", listener: MultipleResolveListener): this; + + prependOnceListener(event: "beforeExit", listener: BeforeExitListener): this; + prependOnceListener(event: "disconnect", listener: DisconnectListener): this; + prependOnceListener(event: "exit", listener: ExitListener): this; + prependOnceListener(event: "rejectionHandled", listener: RejectionHandledListener): this; + prependOnceListener(event: "uncaughtException", listener: UncaughtExceptionListener): this; + prependOnceListener(event: "uncaughtExceptionMonitor", listener: UncaughtExceptionListener): this; + prependOnceListener(event: "unhandledRejection", listener: UnhandledRejectionListener): this; + prependOnceListener(event: "warning", listener: WarningListener): this; + prependOnceListener(event: "message", listener: MessageListener): this; + prependOnceListener(event: Signals, listener: SignalsListener): this; + prependOnceListener(event: "newListener", listener: NewListenerListener): this; + prependOnceListener(event: "removeListener", listener: RemoveListenerListener): this; + prependOnceListener(event: "multipleResolves", listener: MultipleResolveListener): this; + + listeners(event: "beforeExit"): BeforeExitListener[]; + listeners(event: "disconnect"): DisconnectListener[]; + listeners(event: "exit"): ExitListener[]; + listeners(event: "rejectionHandled"): RejectionHandledListener[]; + listeners(event: "uncaughtException"): UncaughtExceptionListener[]; + listeners(event: "uncaughtExceptionMonitor"): UncaughtExceptionListener[]; + listeners(event: "unhandledRejection"): UnhandledRejectionListener[]; + listeners(event: "warning"): WarningListener[]; + listeners(event: "message"): MessageListener[]; + listeners(event: Signals): SignalsListener[]; + listeners(event: "newListener"): NewListenerListener[]; + listeners(event: "removeListener"): RemoveListenerListener[]; + listeners(event: "multipleResolves"): MultipleResolveListener[]; + } + + interface Global { + process: Process; + } + } + } + + export = process; +} diff --git a/node_modules/@types/node/punycode.d.ts b/node_modules/@types/node/punycode.d.ts new file mode 100755 index 0000000..593e9cb --- /dev/null +++ b/node_modules/@types/node/punycode.d.ts @@ -0,0 +1,86 @@ +/** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ +declare module 'node:punycode' { + export * from 'punycode'; +} + +/** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ +declare module 'punycode' { + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + function decode(string: string): string; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + function encode(string: string): string; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + function toUnicode(domain: string): string; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + function toASCII(domain: string): string; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + const ucs2: ucs2; + interface ucs2 { + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + decode(string: string): number[]; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + encode(codePoints: ReadonlyArray): string; + } + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + const version: string; +} diff --git a/node_modules/@types/node/querystring.d.ts b/node_modules/@types/node/querystring.d.ts new file mode 100755 index 0000000..e37234c --- /dev/null +++ b/node_modules/@types/node/querystring.d.ts @@ -0,0 +1,32 @@ +declare module 'node:querystring' { + export * from 'querystring'; +} + +declare module 'querystring' { + interface StringifyOptions { + encodeURIComponent?: (str: string) => string; + } + + interface ParseOptions { + maxKeys?: number; + decodeURIComponent?: (str: string) => string; + } + + interface ParsedUrlQuery extends NodeJS.Dict { } + + interface ParsedUrlQueryInput extends NodeJS.Dict | ReadonlyArray | ReadonlyArray | null> { + } + + function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string; + function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery; + /** + * The querystring.encode() function is an alias for querystring.stringify(). + */ + const encode: typeof stringify; + /** + * The querystring.decode() function is an alias for querystring.parse(). + */ + const decode: typeof parse; + function escape(str: string): string; + function unescape(str: string): string; +} diff --git a/node_modules/@types/node/readline.d.ts b/node_modules/@types/node/readline.d.ts new file mode 100755 index 0000000..2449d89 --- /dev/null +++ b/node_modules/@types/node/readline.d.ts @@ -0,0 +1,174 @@ +declare module 'node:readline' { + export * from 'readline'; +} + +declare module 'readline' { + import EventEmitter = require('node:events'); + + interface Key { + sequence?: string; + name?: string; + ctrl?: boolean; + meta?: boolean; + shift?: boolean; + } + + class Interface extends EventEmitter { + readonly terminal: boolean; + + // Need direct access to line/cursor data, for use in external processes + // see: https://github.com/nodejs/node/issues/30347 + /** The current input data */ + readonly line: string; + /** The current cursor position in the input line */ + readonly cursor: number; + + /** + * NOTE: According to the documentation: + * + * > Instances of the `readline.Interface` class are constructed using the + * > `readline.createInterface()` method. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface + */ + protected constructor(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean); + /** + * NOTE: According to the documentation: + * + * > Instances of the `readline.Interface` class are constructed using the + * > `readline.createInterface()` method. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface + */ + protected constructor(options: ReadLineOptions); + + setPrompt(prompt: string): void; + prompt(preserveCursor?: boolean): void; + question(query: string, callback: (answer: string) => void): void; + pause(): this; + resume(): this; + close(): void; + write(data: string | Buffer, key?: Key): void; + + /** + * Returns the real position of the cursor in relation to the input + * prompt + string. Long input (wrapping) strings, as well as multiple + * line prompts are included in the calculations. + */ + getCursorPos(): CursorPos; + + /** + * events.EventEmitter + * 1. close + * 2. line + * 3. pause + * 4. resume + * 5. SIGCONT + * 6. SIGINT + * 7. SIGTSTP + */ + + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "line", listener: (input: string) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: "SIGCONT", listener: () => void): this; + addListener(event: "SIGINT", listener: () => void): this; + addListener(event: "SIGTSTP", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "line", input: string): boolean; + emit(event: "pause"): boolean; + emit(event: "resume"): boolean; + emit(event: "SIGCONT"): boolean; + emit(event: "SIGINT"): boolean; + emit(event: "SIGTSTP"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "line", listener: (input: string) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: "SIGCONT", listener: () => void): this; + on(event: "SIGINT", listener: () => void): this; + on(event: "SIGTSTP", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "line", listener: (input: string) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: "SIGCONT", listener: () => void): this; + once(event: "SIGINT", listener: () => void): this; + once(event: "SIGTSTP", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "line", listener: (input: string) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: "SIGCONT", listener: () => void): this; + prependListener(event: "SIGINT", listener: () => void): this; + prependListener(event: "SIGTSTP", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "line", listener: (input: string) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: "SIGCONT", listener: () => void): this; + prependOnceListener(event: "SIGINT", listener: () => void): this; + prependOnceListener(event: "SIGTSTP", listener: () => void): this; + [Symbol.asyncIterator](): AsyncIterableIterator; + } + + type ReadLine = Interface; // type forwarded for backwards compatibility + + type Completer = (line: string) => CompleterResult; + type AsyncCompleter = (line: string, callback: (err?: null | Error, result?: CompleterResult) => void) => any; + + type CompleterResult = [string[], string]; + + interface ReadLineOptions { + input: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + completer?: Completer | AsyncCompleter; + terminal?: boolean; + historySize?: number; + prompt?: string; + crlfDelay?: number; + removeHistoryDuplicates?: boolean; + escapeCodeTimeout?: number; + tabSize?: number; + } + + function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface; + function createInterface(options: ReadLineOptions): Interface; + function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void; + + type Direction = -1 | 0 | 1; + + interface CursorPos { + rows: number; + cols: number; + } + + /** + * Clears the current line of this WriteStream in a direction identified by `dir`. + */ + function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean; + /** + * Clears this `WriteStream` from the current cursor down. + */ + function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean; + /** + * Moves this WriteStream's cursor to the specified position. + */ + function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean; + /** + * Moves this WriteStream's cursor relative to its current position. + */ + function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean; +} diff --git a/node_modules/@types/node/repl.d.ts b/node_modules/@types/node/repl.d.ts new file mode 100755 index 0000000..8fae7f9 --- /dev/null +++ b/node_modules/@types/node/repl.d.ts @@ -0,0 +1,399 @@ +declare module 'node:repl' { + export * from 'repl'; +} + +declare module 'repl' { + import { Interface, Completer, AsyncCompleter } from 'node:readline'; + import { Context } from 'node:vm'; + import { InspectOptions } from 'node:util'; + + interface ReplOptions { + /** + * The input prompt to display. + * Default: `"> "` + */ + prompt?: string; + /** + * The `Readable` stream from which REPL input will be read. + * Default: `process.stdin` + */ + input?: NodeJS.ReadableStream; + /** + * The `Writable` stream to which REPL output will be written. + * Default: `process.stdout` + */ + output?: NodeJS.WritableStream; + /** + * If `true`, specifies that the output should be treated as a TTY terminal, and have + * ANSI/VT100 escape codes written to it. + * Default: checking the value of the `isTTY` property on the output stream upon + * instantiation. + */ + terminal?: boolean; + /** + * The function to be used when evaluating each given line of input. + * Default: an async wrapper for the JavaScript `eval()` function. An `eval` function can + * error with `repl.Recoverable` to indicate the input was incomplete and prompt for + * additional lines. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_default_evaluation + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_custom_evaluation_functions + */ + eval?: REPLEval; + /** + * Defines if the repl prints output previews or not. + * @default `true` Always `false` in case `terminal` is falsy. + */ + preview?: boolean; + /** + * If `true`, specifies that the default `writer` function should include ANSI color + * styling to REPL output. If a custom `writer` function is provided then this has no + * effect. + * Default: the REPL instance's `terminal` value. + */ + useColors?: boolean; + /** + * If `true`, specifies that the default evaluation function will use the JavaScript + * `global` as the context as opposed to creating a new separate context for the REPL + * instance. The node CLI REPL sets this value to `true`. + * Default: `false`. + */ + useGlobal?: boolean; + /** + * If `true`, specifies that the default writer will not output the return value of a + * command if it evaluates to `undefined`. + * Default: `false`. + */ + ignoreUndefined?: boolean; + /** + * The function to invoke to format the output of each command before writing to `output`. + * Default: a wrapper for `util.inspect`. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_customizing_repl_output + */ + writer?: REPLWriter; + /** + * An optional function used for custom Tab auto completion. + * + * @see https://nodejs.org/dist/latest-v11.x/docs/api/readline.html#readline_use_of_the_completer_function + */ + completer?: Completer | AsyncCompleter; + /** + * A flag that specifies whether the default evaluator executes all JavaScript commands in + * strict mode or default (sloppy) mode. + * Accepted values are: + * - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode. + * - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to + * prefacing every repl statement with `'use strict'`. + */ + replMode?: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT; + /** + * Stop evaluating the current piece of code when `SIGINT` is received, i.e. `Ctrl+C` is + * pressed. This cannot be used together with a custom `eval` function. + * Default: `false`. + */ + breakEvalOnSigint?: boolean; + } + + type REPLEval = (this: REPLServer, evalCmd: string, context: Context, file: string, cb: (err: Error | null, result: any) => void) => void; + type REPLWriter = (this: REPLServer, obj: any) => string; + + /** + * This is the default "writer" value, if none is passed in the REPL options, + * and it can be overridden by custom print functions. + */ + const writer: REPLWriter & { options: InspectOptions }; + + type REPLCommandAction = (this: REPLServer, text: string) => void; + + interface REPLCommand { + /** + * Help text to be displayed when `.help` is entered. + */ + help?: string; + /** + * The function to execute, optionally accepting a single string argument. + */ + action: REPLCommandAction; + } + + /** + * Provides a customizable Read-Eval-Print-Loop (REPL). + * + * Instances of `repl.REPLServer` will accept individual lines of user input, evaluate those + * according to a user-defined evaluation function, then output the result. Input and output + * may be from `stdin` and `stdout`, respectively, or may be connected to any Node.js `stream`. + * + * Instances of `repl.REPLServer` support automatic completion of inputs, simplistic Emacs-style + * line editing, multi-line inputs, ANSI-styled output, saving and restoring current REPL session + * state, error recovery, and customizable evaluation functions. + * + * Instances of `repl.REPLServer` are created using the `repl.start()` method and _should not_ + * be created directly using the JavaScript `new` keyword. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_repl + */ + class REPLServer extends Interface { + /** + * The `vm.Context` provided to the `eval` function to be used for JavaScript + * evaluation. + */ + readonly context: Context; + /** + * @deprecated since v14.3.0 - Use `input` instead. + */ + readonly inputStream: NodeJS.ReadableStream; + /** + * @deprecated since v14.3.0 - Use `output` instead. + */ + readonly outputStream: NodeJS.WritableStream; + /** + * The `Readable` stream from which REPL input will be read. + */ + readonly input: NodeJS.ReadableStream; + /** + * The `Writable` stream to which REPL output will be written. + */ + readonly output: NodeJS.WritableStream; + /** + * The commands registered via `replServer.defineCommand()`. + */ + readonly commands: NodeJS.ReadOnlyDict; + /** + * A value indicating whether the REPL is currently in "editor mode". + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_commands_and_special_keys + */ + readonly editorMode: boolean; + /** + * A value indicating whether the `_` variable has been assigned. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly underscoreAssigned: boolean; + /** + * The last evaluation result from the REPL (assigned to the `_` variable inside of the REPL). + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly last: any; + /** + * A value indicating whether the `_error` variable has been assigned. + * + * @since v9.8.0 + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly underscoreErrAssigned: boolean; + /** + * The last error raised inside the REPL (assigned to the `_error` variable inside of the REPL). + * + * @since v9.8.0 + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly lastError: any; + /** + * Specified in the REPL options, this is the function to be used when evaluating each + * given line of input. If not specified in the REPL options, this is an async wrapper + * for the JavaScript `eval()` function. + */ + readonly eval: REPLEval; + /** + * Specified in the REPL options, this is a value indicating whether the default + * `writer` function should include ANSI color styling to REPL output. + */ + readonly useColors: boolean; + /** + * Specified in the REPL options, this is a value indicating whether the default `eval` + * function will use the JavaScript `global` as the context as opposed to creating a new + * separate context for the REPL instance. + */ + readonly useGlobal: boolean; + /** + * Specified in the REPL options, this is a value indicating whether the default `writer` + * function should output the result of a command if it evaluates to `undefined`. + */ + readonly ignoreUndefined: boolean; + /** + * Specified in the REPL options, this is the function to invoke to format the output of + * each command before writing to `outputStream`. If not specified in the REPL options, + * this will be a wrapper for `util.inspect`. + */ + readonly writer: REPLWriter; + /** + * Specified in the REPL options, this is the function to use for custom Tab auto-completion. + */ + readonly completer: Completer | AsyncCompleter; + /** + * Specified in the REPL options, this is a flag that specifies whether the default `eval` + * function should execute all JavaScript commands in strict mode or default (sloppy) mode. + * Possible values are: + * - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode. + * - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to + * prefacing every repl statement with `'use strict'`. + */ + readonly replMode: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT; + + /** + * NOTE: According to the documentation: + * + * > Instances of `repl.REPLServer` are created using the `repl.start()` method and + * > _should not_ be created directly using the JavaScript `new` keyword. + * + * `REPLServer` cannot be subclassed due to implementation specifics in NodeJS. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_class_replserver + */ + private constructor(); + + /** + * Used to add new `.`-prefixed commands to the REPL instance. Such commands are invoked + * by typing a `.` followed by the `keyword`. + * + * @param keyword The command keyword (_without_ a leading `.` character). + * @param cmd The function to invoke when the command is processed. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_replserver_definecommand_keyword_cmd + */ + defineCommand(keyword: string, cmd: REPLCommandAction | REPLCommand): void; + /** + * Readies the REPL instance for input from the user, printing the configured `prompt` to a + * new line in the `output` and resuming the `input` to accept new input. + * + * When multi-line input is being entered, an ellipsis is printed rather than the 'prompt'. + * + * This method is primarily intended to be called from within the action function for + * commands registered using the `replServer.defineCommand()` method. + * + * @param preserveCursor When `true`, the cursor placement will not be reset to `0`. + */ + displayPrompt(preserveCursor?: boolean): void; + /** + * Clears any command that has been buffered but not yet executed. + * + * This method is primarily intended to be called from within the action function for + * commands registered using the `replServer.defineCommand()` method. + * + * @since v9.0.0 + */ + clearBufferedCommand(): void; + + /** + * Initializes a history log file for the REPL instance. When executing the + * Node.js binary and using the command line REPL, a history file is initialized + * by default. However, this is not the case when creating a REPL + * programmatically. Use this method to initialize a history log file when working + * with REPL instances programmatically. + * @param path The path to the history file + */ + setupHistory(path: string, cb: (err: Error | null, repl: this) => void): void; + + /** + * events.EventEmitter + * 1. close - inherited from `readline.Interface` + * 2. line - inherited from `readline.Interface` + * 3. pause - inherited from `readline.Interface` + * 4. resume - inherited from `readline.Interface` + * 5. SIGCONT - inherited from `readline.Interface` + * 6. SIGINT - inherited from `readline.Interface` + * 7. SIGTSTP - inherited from `readline.Interface` + * 8. exit + * 9. reset + */ + + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "line", listener: (input: string) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: "SIGCONT", listener: () => void): this; + addListener(event: "SIGINT", listener: () => void): this; + addListener(event: "SIGTSTP", listener: () => void): this; + addListener(event: "exit", listener: () => void): this; + addListener(event: "reset", listener: (context: Context) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "line", input: string): boolean; + emit(event: "pause"): boolean; + emit(event: "resume"): boolean; + emit(event: "SIGCONT"): boolean; + emit(event: "SIGINT"): boolean; + emit(event: "SIGTSTP"): boolean; + emit(event: "exit"): boolean; + emit(event: "reset", context: Context): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "line", listener: (input: string) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: "SIGCONT", listener: () => void): this; + on(event: "SIGINT", listener: () => void): this; + on(event: "SIGTSTP", listener: () => void): this; + on(event: "exit", listener: () => void): this; + on(event: "reset", listener: (context: Context) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "line", listener: (input: string) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: "SIGCONT", listener: () => void): this; + once(event: "SIGINT", listener: () => void): this; + once(event: "SIGTSTP", listener: () => void): this; + once(event: "exit", listener: () => void): this; + once(event: "reset", listener: (context: Context) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "line", listener: (input: string) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: "SIGCONT", listener: () => void): this; + prependListener(event: "SIGINT", listener: () => void): this; + prependListener(event: "SIGTSTP", listener: () => void): this; + prependListener(event: "exit", listener: () => void): this; + prependListener(event: "reset", listener: (context: Context) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "line", listener: (input: string) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: "SIGCONT", listener: () => void): this; + prependOnceListener(event: "SIGINT", listener: () => void): this; + prependOnceListener(event: "SIGTSTP", listener: () => void): this; + prependOnceListener(event: "exit", listener: () => void): this; + prependOnceListener(event: "reset", listener: (context: Context) => void): this; + } + + /** + * A flag passed in the REPL options. Evaluates expressions in sloppy mode. + */ + const REPL_MODE_SLOPPY: unique symbol; + + /** + * A flag passed in the REPL options. Evaluates expressions in strict mode. + * This is equivalent to prefacing every repl statement with `'use strict'`. + */ + const REPL_MODE_STRICT: unique symbol; + + /** + * Creates and starts a `repl.REPLServer` instance. + * + * @param options The options for the `REPLServer`. If `options` is a string, then it specifies + * the input prompt. + */ + function start(options?: string | ReplOptions): REPLServer; + + /** + * Indicates a recoverable error that a `REPLServer` can use to support multi-line input. + * + * @see https://nodejs.org/dist/latest-v10.x/docs/api/repl.html#repl_recoverable_errors + */ + class Recoverable extends SyntaxError { + err: Error; + + constructor(err: Error); + } +} diff --git a/node_modules/@types/node/stream.d.ts b/node_modules/@types/node/stream.d.ts new file mode 100755 index 0000000..a9210d8 --- /dev/null +++ b/node_modules/@types/node/stream.d.ts @@ -0,0 +1,468 @@ +declare module 'node:stream' { + import Stream = require('stream'); + export = Stream; +} + +declare module 'stream' { + import EventEmitter = require('node:events'); + import * as streamPromises from "node:stream/promises"; + + class internal extends EventEmitter { + pipe(destination: T, options?: { end?: boolean; }): T; + } + + namespace internal { + class Stream extends internal { + constructor(opts?: ReadableOptions); + } + + interface ReadableOptions { + highWaterMark?: number; + encoding?: BufferEncoding; + objectMode?: boolean; + read?(this: Readable, size: number): void; + construct?(this: Readable, callback: (error?: Error | null) => void): void; + destroy?(this: Readable, error: Error | null, callback: (error: Error | null) => void): void; + autoDestroy?: boolean; + } + + class Readable extends Stream implements NodeJS.ReadableStream { + /** + * A utility method for creating Readable Streams out of iterators. + */ + static from(iterable: Iterable | AsyncIterable, options?: ReadableOptions): Readable; + + readable: boolean; + readonly readableEncoding: BufferEncoding | null; + readonly readableEnded: boolean; + readonly readableFlowing: boolean | null; + readonly readableHighWaterMark: number; + readonly readableLength: number; + readonly readableObjectMode: boolean; + destroyed: boolean; + constructor(opts?: ReadableOptions); + _construct?(callback: (error?: Error | null) => void): void; + _read(size: number): void; + read(size?: number): any; + setEncoding(encoding: BufferEncoding): this; + pause(): this; + resume(): this; + isPaused(): boolean; + unpipe(destination?: NodeJS.WritableStream): this; + unshift(chunk: any, encoding?: BufferEncoding): void; + wrap(oldStream: NodeJS.ReadableStream): this; + push(chunk: any, encoding?: BufferEncoding): boolean; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + destroy(error?: Error): void; + + /** + * Event emitter + * The defined events on documents including: + * 1. close + * 2. data + * 3. end + * 4. error + * 5. pause + * 6. readable + * 7. resume + */ + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: any) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "close"): boolean; + emit(event: "data", chunk: any): boolean; + emit(event: "end"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "pause"): boolean; + emit(event: "readable"): boolean; + emit(event: "resume"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: any) => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: any) => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: any) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: any) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + removeListener(event: "close", listener: () => void): this; + removeListener(event: "data", listener: (chunk: any) => void): this; + removeListener(event: "end", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "pause", listener: () => void): this; + removeListener(event: "readable", listener: () => void): this; + removeListener(event: "resume", listener: () => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + + [Symbol.asyncIterator](): AsyncIterableIterator; + } + + interface WritableOptions { + highWaterMark?: number; + decodeStrings?: boolean; + defaultEncoding?: BufferEncoding; + objectMode?: boolean; + emitClose?: boolean; + construct?(this: Writable, callback: (error?: Error | null) => void): void; + write?(this: Writable, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Writable, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + destroy?(this: Writable, error: Error | null, callback: (error: Error | null) => void): void; + final?(this: Writable, callback: (error?: Error | null) => void): void; + autoDestroy?: boolean; + } + + class Writable extends Stream implements NodeJS.WritableStream { + readonly writable: boolean; + readonly writableEnded: boolean; + readonly writableFinished: boolean; + readonly writableHighWaterMark: number; + readonly writableLength: number; + readonly writableObjectMode: boolean; + readonly writableCorked: number; + destroyed: boolean; + constructor(opts?: WritableOptions); + _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + _writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + _construct?(callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; + write(chunk: any, encoding: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean; + setDefaultEncoding(encoding: BufferEncoding): this; + end(cb?: () => void): void; + end(chunk: any, cb?: () => void): void; + end(chunk: any, encoding: BufferEncoding, cb?: () => void): void; + cork(): void; + uncork(): void; + destroy(error?: Error): void; + + /** + * Event emitter + * The defined events on documents including: + * 1. close + * 2. drain + * 3. error + * 4. finish + * 5. pipe + * 6. unpipe + */ + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "pipe", listener: (src: Readable) => void): this; + addListener(event: "unpipe", listener: (src: Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "close"): boolean; + emit(event: "drain"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "pipe", src: Readable): boolean; + emit(event: "unpipe", src: Readable): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "pipe", listener: (src: Readable) => void): this; + on(event: "unpipe", listener: (src: Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "pipe", listener: (src: Readable) => void): this; + once(event: "unpipe", listener: (src: Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "pipe", listener: (src: Readable) => void): this; + prependListener(event: "unpipe", listener: (src: Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + removeListener(event: "close", listener: () => void): this; + removeListener(event: "drain", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "finish", listener: () => void): this; + removeListener(event: "pipe", listener: (src: Readable) => void): this; + removeListener(event: "unpipe", listener: (src: Readable) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + } + + interface DuplexOptions extends ReadableOptions, WritableOptions { + allowHalfOpen?: boolean; + readableObjectMode?: boolean; + writableObjectMode?: boolean; + readableHighWaterMark?: number; + writableHighWaterMark?: number; + writableCorked?: number; + construct?(this: Duplex, callback: (error?: Error | null) => void): void; + read?(this: Duplex, size: number): void; + write?(this: Duplex, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Duplex, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + final?(this: Duplex, callback: (error?: Error | null) => void): void; + destroy?(this: Duplex, error: Error | null, callback: (error: Error | null) => void): void; + } + + // Note: Duplex extends both Readable and Writable. + class Duplex extends Readable implements Writable { + readonly writable: boolean; + readonly writableEnded: boolean; + readonly writableFinished: boolean; + readonly writableHighWaterMark: number; + readonly writableLength: number; + readonly writableObjectMode: boolean; + readonly writableCorked: number; + constructor(opts?: DuplexOptions); + _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + _writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + write(chunk: any, encoding?: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean; + write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; + setDefaultEncoding(encoding: BufferEncoding): this; + end(cb?: () => void): void; + end(chunk: any, cb?: () => void): void; + end(chunk: any, encoding?: BufferEncoding, cb?: () => void): void; + cork(): void; + uncork(): void; + } + + type TransformCallback = (error?: Error | null, data?: any) => void; + + interface TransformOptions extends DuplexOptions { + construct?(this: Transform, callback: (error?: Error | null) => void): void; + read?(this: Transform, size: number): void; + write?(this: Transform, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Transform, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + final?(this: Transform, callback: (error?: Error | null) => void): void; + destroy?(this: Transform, error: Error | null, callback: (error: Error | null) => void): void; + transform?(this: Transform, chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; + flush?(this: Transform, callback: TransformCallback): void; + } + + class Transform extends Duplex { + constructor(opts?: TransformOptions); + _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; + _flush(callback: TransformCallback): void; + } + + class PassThrough extends Transform { } + + interface FinishedOptions { + error?: boolean; + readable?: boolean; + writable?: boolean; + } + function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options: FinishedOptions, callback: (err?: NodeJS.ErrnoException | null) => void): () => void; + function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, callback: (err?: NodeJS.ErrnoException | null) => void): () => void; + namespace finished { + function __promisify__(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options?: FinishedOptions): Promise; + } + + type PipelineSourceFunction = () => Iterable | AsyncIterable; + type PipelineSource = Iterable | AsyncIterable | NodeJS.ReadableStream | PipelineSourceFunction; + type PipelineTransform, U> = + NodeJS.ReadWriteStream | + ((source: S extends (...args: any[]) => Iterable | AsyncIterable ? + AsyncIterable : S) => AsyncIterable); + type PipelineTransformSource = PipelineSource | PipelineTransform; + + type PipelineDestinationIterableFunction = (source: AsyncIterable) => AsyncIterable; + type PipelineDestinationPromiseFunction = (source: AsyncIterable) => Promise

; + + type PipelineDestination, P> = + S extends PipelineTransformSource ? + (NodeJS.WritableStream | PipelineDestinationIterableFunction | PipelineDestinationPromiseFunction) : never; + type PipelineCallback> = + S extends PipelineDestinationPromiseFunction ? (err: NodeJS.ErrnoException | null, value: P) => void : + (err: NodeJS.ErrnoException | null) => void; + type PipelinePromise> = + S extends PipelineDestinationPromiseFunction ? Promise

: Promise; + interface PipelineOptions { + signal: AbortSignal; + } + + function pipeline, + B extends PipelineDestination>( + source: A, + destination: B, + callback?: PipelineCallback + ): B extends NodeJS.WritableStream ? B : NodeJS.WritableStream; + function pipeline, + T1 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + destination: B, + callback?: PipelineCallback + ): B extends NodeJS.WritableStream ? B : NodeJS.WritableStream; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + destination: B, + callback?: PipelineCallback + ): B extends NodeJS.WritableStream ? B : NodeJS.WritableStream; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + destination: B, + callback?: PipelineCallback + ): B extends NodeJS.WritableStream ? B : NodeJS.WritableStream; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + T4 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + transform4: T4, + destination: B, + callback?: PipelineCallback + ): B extends NodeJS.WritableStream ? B : NodeJS.WritableStream; + function pipeline( + streams: ReadonlyArray, + callback?: (err: NodeJS.ErrnoException | null) => void, + ): NodeJS.WritableStream; + function pipeline( + stream1: NodeJS.ReadableStream, + stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream, + ...streams: Array void)>, + ): NodeJS.WritableStream; + namespace pipeline { + function __promisify__, + B extends PipelineDestination>( + source: A, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function __promisify__, + T1 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + destination: B, + options?: PipelineOptions, + ): PipelinePromise; + function __promisify__, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function __promisify__, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function __promisify__, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + T4 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + transform4: T4, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + + function __promisify__( + streams: ReadonlyArray, + options?: PipelineOptions + ): Promise; + function __promisify__( + stream1: NodeJS.ReadableStream, + stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream, + ...streams: Array, + ): Promise; + } + + interface Pipe { + close(): void; + hasRef(): boolean; + ref(): void; + unref(): void; + } + + const promises: typeof streamPromises; + } + + export = internal; +} diff --git a/node_modules/@types/node/stream/promises.d.ts b/node_modules/@types/node/stream/promises.d.ts new file mode 100755 index 0000000..e582794 --- /dev/null +++ b/node_modules/@types/node/stream/promises.d.ts @@ -0,0 +1,71 @@ +declare module "node:stream/promises" { + export * from "stream/promises"; +} + +declare module "stream/promises" { + import { FinishedOptions, PipelineSource, PipelineTransform, + PipelineDestination, PipelinePromise, PipelineOptions } from "stream"; + + function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options?: FinishedOptions): Promise; + + function pipeline, + B extends PipelineDestination>( + source: A, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function pipeline, + T1 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + function pipeline, + T1 extends PipelineTransform, + T2 extends PipelineTransform, + T3 extends PipelineTransform, + T4 extends PipelineTransform, + B extends PipelineDestination>( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + transform4: T4, + destination: B, + options?: PipelineOptions + ): PipelinePromise; + + function pipeline( + streams: ReadonlyArray, + options?: PipelineOptions + ): Promise; + function pipeline( + stream1: NodeJS.ReadableStream, + stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream, + ...streams: Array, + ): Promise; +} diff --git a/node_modules/@types/node/string_decoder.d.ts b/node_modules/@types/node/string_decoder.d.ts new file mode 100755 index 0000000..6b688d3 --- /dev/null +++ b/node_modules/@types/node/string_decoder.d.ts @@ -0,0 +1,11 @@ +declare module 'node:string_decoder' { + export * from 'string_decoder'; +} + +declare module 'string_decoder' { + class StringDecoder { + constructor(encoding?: BufferEncoding); + write(buffer: Buffer): string; + end(buffer?: Buffer): string; + } +} diff --git a/node_modules/@types/node/timers.d.ts b/node_modules/@types/node/timers.d.ts new file mode 100755 index 0000000..c97e34a --- /dev/null +++ b/node_modules/@types/node/timers.d.ts @@ -0,0 +1,34 @@ +declare module 'node:timers' { + export * from 'timers'; +} + +declare module 'timers' { + interface TimerOptions { + /** + * Set to `false` to indicate that the scheduled `Timeout` + * should not require the Node.js event loop to remain active. + * @default true + */ + ref?: boolean; + + /** + * An optional `AbortSignal` that can be used to cancel the scheduled `Timeout`. + */ + signal?: AbortSignal; + } + + function setTimeout(callback: (...args: any[]) => void, ms?: number, ...args: any[]): NodeJS.Timeout; + namespace setTimeout { + function __promisify__(ms: number): Promise; + function __promisify__(ms: number, value: T, options?: TimerOptions): Promise; + } + function clearTimeout(timeoutId: NodeJS.Timeout): void; + function setInterval(callback: (...args: any[]) => void, ms?: number, ...args: any[]): NodeJS.Timeout; + function clearInterval(intervalId: NodeJS.Timeout): void; + function setImmediate(callback: (...args: any[]) => void, ...args: any[]): NodeJS.Immediate; + namespace setImmediate { + function __promisify__(): Promise; + function __promisify__(value: T, options?: TimerOptions): Promise; + } + function clearImmediate(immediateId: NodeJS.Immediate): void; +} diff --git a/node_modules/@types/node/timers/promises.d.ts b/node_modules/@types/node/timers/promises.d.ts new file mode 100755 index 0000000..87c1f10 --- /dev/null +++ b/node_modules/@types/node/timers/promises.d.ts @@ -0,0 +1,17 @@ +declare module 'node:timers/promises' { + export * from 'timers/promises'; +} + +declare module 'timers/promises' { + import { TimerOptions } from 'node:timers'; + + /** + * Returns a promise that resolves after the specified delay in milliseconds. + */ + function setTimeout(delay: number, value?: T, options?: TimerOptions): Promise; + + /** + * Returns a promise that resolves in the next tick. + */ + function setImmediate(value: T, options?: TimerOptions): Promise; +} diff --git a/node_modules/@types/node/tls.d.ts b/node_modules/@types/node/tls.d.ts new file mode 100755 index 0000000..e65a196 --- /dev/null +++ b/node_modules/@types/node/tls.d.ts @@ -0,0 +1,783 @@ +declare module 'node:tls' { + export * from 'tls'; +} + +declare module 'tls' { + import * as net from 'node:net'; + + const CLIENT_RENEG_LIMIT: number; + const CLIENT_RENEG_WINDOW: number; + + interface Certificate { + /** + * Country code. + */ + C: string; + /** + * Street. + */ + ST: string; + /** + * Locality. + */ + L: string; + /** + * Organization. + */ + O: string; + /** + * Organizational unit. + */ + OU: string; + /** + * Common name. + */ + CN: string; + } + + interface PeerCertificate { + subject: Certificate; + issuer: Certificate; + subjectaltname: string; + infoAccess: NodeJS.Dict; + modulus: string; + exponent: string; + valid_from: string; + valid_to: string; + fingerprint: string; + fingerprint256: string; + ext_key_usage: string[]; + serialNumber: string; + raw: Buffer; + } + + interface DetailedPeerCertificate extends PeerCertificate { + issuerCertificate: DetailedPeerCertificate; + } + + interface CipherNameAndProtocol { + /** + * The cipher name. + */ + name: string; + /** + * SSL/TLS protocol version. + */ + version: string; + + /** + * IETF name for the cipher suite. + */ + standardName: string; + } + + interface EphemeralKeyInfo { + /** + * The supported types are 'DH' and 'ECDH'. + */ + type: string; + /** + * The name property is available only when type is 'ECDH'. + */ + name?: string; + /** + * The size of parameter of an ephemeral key exchange. + */ + size: number; + } + + interface KeyObject { + /** + * Private keys in PEM format. + */ + pem: string | Buffer; + /** + * Optional passphrase. + */ + passphrase?: string; + } + + interface PxfObject { + /** + * PFX or PKCS12 encoded private key and certificate chain. + */ + buf: string | Buffer; + /** + * Optional passphrase. + */ + passphrase?: string; + } + + interface TLSSocketOptions extends SecureContextOptions, CommonConnectionOptions { + /** + * If true the TLS socket will be instantiated in server-mode. + * Defaults to false. + */ + isServer?: boolean; + /** + * An optional net.Server instance. + */ + server?: net.Server; + + /** + * An optional Buffer instance containing a TLS session. + */ + session?: Buffer; + /** + * If true, specifies that the OCSP status request extension will be + * added to the client hello and an 'OCSPResponse' event will be + * emitted on the socket before establishing a secure communication + */ + requestOCSP?: boolean; + } + + class TLSSocket extends net.Socket { + /** + * Construct a new tls.TLSSocket object from an existing TCP socket. + */ + constructor(socket: net.Socket, options?: TLSSocketOptions); + + /** + * A boolean that is true if the peer certificate was signed by one of the specified CAs, otherwise false. + */ + authorized: boolean; + /** + * The reason why the peer's certificate has not been verified. + * This property becomes available only when tlsSocket.authorized === false. + */ + authorizationError: Error; + /** + * Static boolean value, always true. + * May be used to distinguish TLS sockets from regular ones. + */ + encrypted: boolean; + + /** + * String containing the selected ALPN protocol. + * When ALPN has no selected protocol, tlsSocket.alpnProtocol equals false. + */ + alpnProtocol?: string; + + /** + * Returns an object representing the local certificate. The returned + * object has some properties corresponding to the fields of the + * certificate. + * + * See tls.TLSSocket.getPeerCertificate() for an example of the + * certificate structure. + * + * If there is no local certificate, an empty object will be returned. + * If the socket has been destroyed, null will be returned. + */ + getCertificate(): PeerCertificate | object | null; + /** + * Returns an object representing the cipher name and the SSL/TLS protocol version of the current connection. + * @returns Returns an object representing the cipher name + * and the SSL/TLS protocol version of the current connection. + */ + getCipher(): CipherNameAndProtocol; + /** + * Returns an object representing the type, name, and size of parameter + * of an ephemeral key exchange in Perfect Forward Secrecy on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; null is + * returned if called on a server socket. The supported types are 'DH' + * and 'ECDH'. The name property is available only when type is 'ECDH'. + * + * For example: { type: 'ECDH', name: 'prime256v1', size: 256 }. + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + /** + * Returns the latest Finished message that has + * been sent to the socket as part of a SSL/TLS handshake, or undefined + * if no Finished message has been sent yet. + * + * As the Finished messages are message digests of the complete + * handshake (with a total of 192 bits for TLS 1.0 and more for SSL + * 3.0), they can be used for external authentication procedures when + * the authentication provided by SSL/TLS is not desired or is not + * enough. + * + * Corresponds to the SSL_get_finished routine in OpenSSL and may be + * used to implement the tls-unique channel binding from RFC 5929. + */ + getFinished(): Buffer | undefined; + /** + * Returns an object representing the peer's certificate. + * The returned object has some properties corresponding to the field of the certificate. + * If detailed argument is true the full chain with issuer property will be returned, + * if false only the top certificate without issuer property. + * If the peer does not provide a certificate, it returns null or an empty object. + * @param detailed - If true; the full chain with issuer property will be returned. + * @returns An object representing the peer's certificate. + */ + getPeerCertificate(detailed: true): DetailedPeerCertificate; + getPeerCertificate(detailed?: false): PeerCertificate; + getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate; + /** + * Returns the latest Finished message that is expected or has actually + * been received from the socket as part of a SSL/TLS handshake, or + * undefined if there is no Finished message so far. + * + * As the Finished messages are message digests of the complete + * handshake (with a total of 192 bits for TLS 1.0 and more for SSL + * 3.0), they can be used for external authentication procedures when + * the authentication provided by SSL/TLS is not desired or is not + * enough. + * + * Corresponds to the SSL_get_peer_finished routine in OpenSSL and may + * be used to implement the tls-unique channel binding from RFC 5929. + */ + getPeerFinished(): Buffer | undefined; + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the current connection. + * The value `'unknown'` will be returned for connected sockets that have not completed the handshaking process. + * The value `null` will be returned for server sockets or disconnected client sockets. + * See https://www.openssl.org/docs/man1.0.2/ssl/SSL_get_version.html for more information. + * @returns negotiated SSL/TLS protocol version of the current connection + */ + getProtocol(): string | null; + /** + * Could be used to speed up handshake establishment when reconnecting to the server. + * @returns ASN.1 encoded TLS session or undefined if none was negotiated. + */ + getSession(): Buffer | undefined; + /** + * Returns a list of signature algorithms shared between the server and + * the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + /** + * NOTE: Works only with client TLS sockets. + * Useful only for debugging, for session reuse provide session option to tls.connect(). + * @returns TLS session ticket or undefined if none was negotiated. + */ + getTLSTicket(): Buffer | undefined; + /** + * Returns true if the session was reused, false otherwise. + */ + isSessionReused(): boolean; + /** + * Initiate TLS renegotiation process. + * + * NOTE: Can be used to request peer's certificate after the secure connection has been established. + * ANOTHER NOTE: When running as the server, socket will be destroyed with an error after handshakeTimeout timeout. + * @param options - The options may contain the following fields: rejectUnauthorized, + * requestCert (See tls.createServer() for details). + * @param callback - callback(err) will be executed with null as err, once the renegotiation + * is successfully completed. + * @return `undefined` when socket is destroy, `false` if negotiaion can't be initiated. + */ + renegotiate(options: { rejectUnauthorized?: boolean, requestCert?: boolean }, callback: (err: Error | null) => void): undefined | boolean; + /** + * Set maximum TLS fragment size (default and maximum value is: 16384, minimum is: 512). + * Smaller fragment size decreases buffering latency on the client: large fragments are buffered by + * the TLS layer until the entire fragment is received and its integrity is verified; + * large fragments can span multiple roundtrips, and their processing can be delayed due to packet + * loss or reordering. However, smaller fragments add extra TLS framing bytes and CPU overhead, + * which may decrease overall server throughput. + * @param size - TLS fragment size (default and maximum value is: 16384, minimum is: 512). + * @returns Returns true on success, false otherwise. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Disables TLS renegotiation for this TLSSocket instance. Once called, + * attempts to renegotiate will trigger an 'error' event on the + * TLSSocket. + */ + disableRenegotiation(): void; + + /** + * When enabled, TLS packet trace information is written to `stderr`. This can be + * used to debug TLS connection problems. + * + * Note: The format of the output is identical to the output of `openssl s_client + * -trace` or `openssl s_server -trace`. While it is produced by OpenSSL's + * `SSL_trace()` function, the format is undocumented, can change without notice, + * and should not be relied on. + */ + enableTrace(): void; + + /** + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the + * [IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context optionally provide a context. + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; + + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + addListener(event: "secureConnect", listener: () => void): this; + addListener(event: "session", listener: (session: Buffer) => void): this; + addListener(event: "keylog", listener: (line: Buffer) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "OCSPResponse", response: Buffer): boolean; + emit(event: "secureConnect"): boolean; + emit(event: "session", session: Buffer): boolean; + emit(event: "keylog", line: Buffer): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "OCSPResponse", listener: (response: Buffer) => void): this; + on(event: "secureConnect", listener: () => void): this; + on(event: "session", listener: (session: Buffer) => void): this; + on(event: "keylog", listener: (line: Buffer) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "OCSPResponse", listener: (response: Buffer) => void): this; + once(event: "secureConnect", listener: () => void): this; + once(event: "session", listener: (session: Buffer) => void): this; + once(event: "keylog", listener: (line: Buffer) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + prependListener(event: "secureConnect", listener: () => void): this; + prependListener(event: "session", listener: (session: Buffer) => void): this; + prependListener(event: "keylog", listener: (line: Buffer) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + prependOnceListener(event: "secureConnect", listener: () => void): this; + prependOnceListener(event: "session", listener: (session: Buffer) => void): this; + prependOnceListener(event: "keylog", listener: (line: Buffer) => void): this; + } + + interface CommonConnectionOptions { + /** + * An optional TLS context object from tls.createSecureContext() + */ + secureContext?: SecureContext; + + /** + * When enabled, TLS packet trace information is written to `stderr`. This can be + * used to debug TLS connection problems. + * @default false + */ + enableTrace?: boolean; + /** + * If true the server will request a certificate from clients that + * connect and attempt to verify that certificate. Defaults to + * false. + */ + requestCert?: boolean; + /** + * An array of strings or a Buffer naming possible ALPN protocols. + * (Protocols should be ordered by their priority.) + */ + ALPNProtocols?: string[] | Uint8Array[] | Uint8Array; + /** + * SNICallback(servername, cb) A function that will be + * called if the client supports SNI TLS extension. Two arguments + * will be passed when called: servername and cb. SNICallback should + * invoke cb(null, ctx), where ctx is a SecureContext instance. + * (tls.createSecureContext(...) can be used to get a proper + * SecureContext.) If SNICallback wasn't provided the default callback + * with high-level API will be used (see below). + */ + SNICallback?: (servername: string, cb: (err: Error | null, ctx: SecureContext) => void) => void; + /** + * If true the server will reject any connection which is not + * authorized with the list of supplied CAs. This option only has an + * effect if requestCert is true. + * @default true + */ + rejectUnauthorized?: boolean; + } + + interface TlsOptions extends SecureContextOptions, CommonConnectionOptions, net.ServerOpts { + /** + * Abort the connection if the SSL/TLS handshake does not finish in the + * specified number of milliseconds. A 'tlsClientError' is emitted on + * the tls.Server object whenever a handshake times out. Default: + * 120000 (120 seconds). + */ + handshakeTimeout?: number; + /** + * The number of seconds after which a TLS session created by the + * server will no longer be resumable. See Session Resumption for more + * information. Default: 300. + */ + sessionTimeout?: number; + /** + * 48-bytes of cryptographically strong pseudo-random data. + */ + ticketKeys?: Buffer; + + /** + * + * @param socket + * @param identity identity parameter sent from the client. + * @return pre-shared key that must either be + * a buffer or `null` to stop the negotiation process. Returned PSK must be + * compatible with the selected cipher's digest. + * + * When negotiating TLS-PSK (pre-shared keys), this function is called + * with the identity provided by the client. + * If the return value is `null` the negotiation process will stop and an + * "unknown_psk_identity" alert message will be sent to the other party. + * If the server wishes to hide the fact that the PSK identity was not known, + * the callback must provide some random data as `psk` to make the connection + * fail with "decrypt_error" before negotiation is finished. + * PSK ciphers are disabled by default, and using TLS-PSK thus + * requires explicitly specifying a cipher suite with the `ciphers` option. + * More information can be found in the RFC 4279. + */ + + pskCallback?(socket: TLSSocket, identity: string): DataView | NodeJS.TypedArray | null; + /** + * hint to send to a client to help + * with selecting the identity during TLS-PSK negotiation. Will be ignored + * in TLS 1.3. Upon failing to set pskIdentityHint `tlsClientError` will be + * emitted with `ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED` code. + */ + pskIdentityHint?: string; + } + + interface PSKCallbackNegotation { + psk: DataView | NodeJS.TypedArray; + identity: string; + } + + interface ConnectionOptions extends SecureContextOptions, CommonConnectionOptions { + host?: string; + port?: number; + path?: string; // Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. + socket?: net.Socket; // Establish secure connection on a given socket rather than creating a new socket + checkServerIdentity?: typeof checkServerIdentity; + servername?: string; // SNI TLS Extension + session?: Buffer; + minDHSize?: number; + lookup?: net.LookupFunction; + timeout?: number; + /** + * When negotiating TLS-PSK (pre-shared keys), this function is called + * with optional identity `hint` provided by the server or `null` + * in case of TLS 1.3 where `hint` was removed. + * It will be necessary to provide a custom `tls.checkServerIdentity()` + * for the connection as the default one will try to check hostname/IP + * of the server against the certificate but that's not applicable for PSK + * because there won't be a certificate present. + * More information can be found in the RFC 4279. + * + * @param hint message sent from the server to help client + * decide which identity to use during negotiation. + * Always `null` if TLS 1.3 is used. + * @returns Return `null` to stop the negotiation process. `psk` must be + * compatible with the selected cipher's digest. + * `identity` must use UTF-8 encoding. + */ + pskCallback?(hint: string | null): PSKCallbackNegotation | null; + } + + class Server extends net.Server { + constructor(secureConnectionListener?: (socket: TLSSocket) => void); + constructor(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void); + + /** + * The server.addContext() method adds a secure context that will be + * used if the client request's SNI name matches the supplied hostname + * (or wildcard). + */ + addContext(hostName: string, credentials: SecureContextOptions): void; + /** + * Returns the session ticket keys. + */ + getTicketKeys(): Buffer; + /** + * + * The server.setSecureContext() method replaces the + * secure context of an existing server. Existing connections to the + * server are not interrupted. + */ + setSecureContext(details: SecureContextOptions): void; + /** + * The server.setSecureContext() method replaces the secure context of + * an existing server. Existing connections to the server are not + * interrupted. + */ + setTicketKeys(keys: Buffer): void; + + /** + * events.EventEmitter + * 1. tlsClientError + * 2. newSession + * 3. OCSPRequest + * 4. resumeSession + * 5. secureConnection + * 6. keylog + */ + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + addListener(event: "newSession", listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this; + addListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this; + addListener(event: "resumeSession", listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this; + addListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + addListener(event: "keylog", listener: (line: Buffer, tlsSocket: TLSSocket) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "tlsClientError", err: Error, tlsSocket: TLSSocket): boolean; + emit(event: "newSession", sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void): boolean; + emit(event: "OCSPRequest", certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void): boolean; + emit(event: "resumeSession", sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void): boolean; + emit(event: "secureConnection", tlsSocket: TLSSocket): boolean; + emit(event: "keylog", line: Buffer, tlsSocket: TLSSocket): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + on(event: "newSession", listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this; + on(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this; + on(event: "resumeSession", listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this; + on(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + on(event: "keylog", listener: (line: Buffer, tlsSocket: TLSSocket) => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + once(event: "newSession", listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this; + once(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this; + once(event: "resumeSession", listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this; + once(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + once(event: "keylog", listener: (line: Buffer, tlsSocket: TLSSocket) => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + prependListener(event: "newSession", listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this; + prependListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this; + prependListener(event: "resumeSession", listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this; + prependListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + prependListener(event: "keylog", listener: (line: Buffer, tlsSocket: TLSSocket) => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + prependOnceListener(event: "newSession", listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this; + prependOnceListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this; + prependOnceListener(event: "resumeSession", listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this; + prependOnceListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + prependOnceListener(event: "keylog", listener: (line: Buffer, tlsSocket: TLSSocket) => void): this; + } + + interface SecurePair { + encrypted: TLSSocket; + cleartext: TLSSocket; + } + + type SecureVersion = 'TLSv1.3' | 'TLSv1.2' | 'TLSv1.1' | 'TLSv1'; + + interface SecureContextOptions { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | Array; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: string | Buffer | Array; + /** + * Colon-separated list of supported signature algorithms. The list + * can contain digest algorithms (SHA256, MD5 etc.), public key + * algorithms (RSA-PSS, ECDSA etc.), combination of both (e.g + * 'RSA+SHA384') or TLS v1.3 scheme names (e.g. rsa_pss_pss_sha512). + */ + sigalgs?: string; + /** + * Cipher suite specification, replacing the default. For more + * information, see modifying the default cipher suite. Permitted + * ciphers can be obtained via tls.getCiphers(). Cipher names must be + * uppercased in order for OpenSSL to accept them. + */ + ciphers?: string; + /** + * Name of an OpenSSL engine which can provide the client certificate. + */ + clientCertEngine?: string; + /** + * PEM formatted CRLs (Certificate Revocation Lists). + */ + crl?: string | Buffer | Array; + /** + * Diffie Hellman parameters, required for Perfect Forward Secrecy. Use + * openssl dhparam to create the parameters. The key length must be + * greater than or equal to 1024 bits or else an error will be thrown. + * Although 1024 bits is permissible, use 2048 bits or larger for + * stronger security. If omitted or invalid, the parameters are + * silently discarded and DHE ciphers will not be available. + */ + dhparam?: string | Buffer; + /** + * A string describing a named curve or a colon separated list of curve + * NIDs or names, for example P-521:P-384:P-256, to use for ECDH key + * agreement. Set to auto to select the curve automatically. Use + * crypto.getCurves() to obtain a list of available curve names. On + * recent releases, openssl ecparam -list_curves will also display the + * name and description of each available elliptic curve. Default: + * tls.DEFAULT_ECDH_CURVE. + */ + ecdhCurve?: string; + /** + * Attempt to use the server's cipher suite preferences instead of the + * client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be + * set in secureOptions + */ + honorCipherOrder?: boolean; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: string | Buffer | Array; + /** + * Name of an OpenSSL engine to get private key from. Should be used + * together with privateKeyIdentifier. + */ + privateKeyEngine?: string; + /** + * Identifier of a private key managed by an OpenSSL engine. Should be + * used together with privateKeyEngine. Should not be set together with + * key, because both options define a private key in different ways. + */ + privateKeyIdentifier?: string; + /** + * Optionally set the maximum TLS version to allow. One + * of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the + * `secureProtocol` option, use one or the other. + * **Default:** `'TLSv1.3'`, unless changed using CLI options. Using + * `--tls-max-v1.2` sets the default to `'TLSv1.2'`. Using `--tls-max-v1.3` sets the default to + * `'TLSv1.3'`. If multiple of the options are provided, the highest maximum is used. + */ + maxVersion?: SecureVersion; + /** + * Optionally set the minimum TLS version to allow. One + * of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the + * `secureProtocol` option, use one or the other. It is not recommended to use + * less than TLSv1.2, but it may be required for interoperability. + * **Default:** `'TLSv1.2'`, unless changed using CLI options. Using + * `--tls-v1.0` sets the default to `'TLSv1'`. Using `--tls-v1.1` sets the default to + * `'TLSv1.1'`. Using `--tls-min-v1.3` sets the default to + * 'TLSv1.3'. If multiple of the options are provided, the lowest minimum is used. + */ + minVersion?: SecureVersion; + /** + * Shared passphrase used for a single private key and/or a PFX. + */ + passphrase?: string; + /** + * PFX or PKCS12 encoded private key and certificate chain. pfx is an + * alternative to providing key and cert individually. PFX is usually + * encrypted, if it is, passphrase will be used to decrypt it. Multiple + * PFX can be provided either as an array of unencrypted PFX buffers, + * or an array of objects in the form {buf: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted PFX will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + pfx?: string | Buffer | Array; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number; // Value is a numeric bitmask of the `SSL_OP_*` options + /** + * Legacy mechanism to select the TLS protocol version to use, it does + * not support independent control of the minimum and maximum version, + * and does not support limiting the protocol to TLSv1.3. Use + * minVersion and maxVersion instead. The possible values are listed as + * SSL_METHODS, use the function names as strings. For example, use + * 'TLSv1_1_method' to force TLS version 1.1, or 'TLS_method' to allow + * any TLS protocol version up to TLSv1.3. It is not recommended to use + * TLS versions less than 1.2, but it may be required for + * interoperability. Default: none, see minVersion. + */ + secureProtocol?: string; + /** + * Opaque identifier used by servers to ensure session state is not + * shared between applications. Unused by clients. + */ + sessionIdContext?: string; + /** + * 48-bytes of cryptographically strong pseudo-random data. + * See Session Resumption for more information. + */ + ticketKeys?: Buffer; + /** + * The number of seconds after which a TLS session created by the + * server will no longer be resumable. See Session Resumption for more + * information. Default: 300. + */ + sessionTimeout?: number; + } + + interface SecureContext { + context: any; + } + + /* + * Verifies the certificate `cert` is issued to host `host`. + * @host The hostname to verify the certificate against + * @cert PeerCertificate representing the peer's certificate + * + * Returns Error object, populating it with the reason, host and cert on failure. On success, returns undefined. + */ + function checkServerIdentity(host: string, cert: PeerCertificate): Error | undefined; + function createServer(secureConnectionListener?: (socket: TLSSocket) => void): Server; + function createServer(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void): Server; + function connect(options: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + /** + * @deprecated since v0.11.3 Use `tls.TLSSocket` instead. + */ + function createSecurePair(credentials?: SecureContext, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; + function createSecureContext(options?: SecureContextOptions): SecureContext; + function getCiphers(): string[]; + + /** + * The default curve name to use for ECDH key agreement in a tls server. + * The default value is 'auto'. See tls.createSecureContext() for further + * information. + */ + let DEFAULT_ECDH_CURVE: string; + /** + * The default value of the maxVersion option of + * tls.createSecureContext(). It can be assigned any of the supported TLS + * protocol versions, 'TLSv1.3', 'TLSv1.2', 'TLSv1.1', or 'TLSv1'. Default: + * 'TLSv1.3', unless changed using CLI options. Using --tls-max-v1.2 sets + * the default to 'TLSv1.2'. Using --tls-max-v1.3 sets the default to + * 'TLSv1.3'. If multiple of the options are provided, the highest maximum + * is used. + */ + let DEFAULT_MAX_VERSION: SecureVersion; + /** + * The default value of the minVersion option of tls.createSecureContext(). + * It can be assigned any of the supported TLS protocol versions, + * 'TLSv1.3', 'TLSv1.2', 'TLSv1.1', or 'TLSv1'. Default: 'TLSv1.2', unless + * changed using CLI options. Using --tls-min-v1.0 sets the default to + * 'TLSv1'. Using --tls-min-v1.1 sets the default to 'TLSv1.1'. Using + * --tls-min-v1.3 sets the default to 'TLSv1.3'. If multiple of the options + * are provided, the lowest minimum is used. + */ + let DEFAULT_MIN_VERSION: SecureVersion; + + /** + * An immutable array of strings representing the root certificates (in PEM + * format) used for verifying peer certificates. This is the default value + * of the ca option to tls.createSecureContext(). + */ + const rootCertificates: ReadonlyArray; +} diff --git a/node_modules/@types/node/trace_events.d.ts b/node_modules/@types/node/trace_events.d.ts new file mode 100755 index 0000000..812b2b5 --- /dev/null +++ b/node_modules/@types/node/trace_events.d.ts @@ -0,0 +1,65 @@ +declare module 'node:trace_events' { + export * from 'trace_events'; +} + +declare module 'trace_events' { + /** + * The `Tracing` object is used to enable or disable tracing for sets of + * categories. Instances are created using the + * `trace_events.createTracing()` method. + * + * When created, the `Tracing` object is disabled. Calling the + * `tracing.enable()` method adds the categories to the set of enabled trace + * event categories. Calling `tracing.disable()` will remove the categories + * from the set of enabled trace event categories. + */ + interface Tracing { + /** + * A comma-separated list of the trace event categories covered by this + * `Tracing` object. + */ + readonly categories: string; + + /** + * Disables this `Tracing` object. + * + * Only trace event categories _not_ covered by other enabled `Tracing` + * objects and _not_ specified by the `--trace-event-categories` flag + * will be disabled. + */ + disable(): void; + + /** + * Enables this `Tracing` object for the set of categories covered by + * the `Tracing` object. + */ + enable(): void; + + /** + * `true` only if the `Tracing` object has been enabled. + */ + readonly enabled: boolean; + } + + interface CreateTracingOptions { + /** + * An array of trace category names. Values included in the array are + * coerced to a string when possible. An error will be thrown if the + * value cannot be coerced. + */ + categories: string[]; + } + + /** + * Creates and returns a Tracing object for the given set of categories. + */ + function createTracing(options: CreateTracingOptions): Tracing; + + /** + * Returns a comma-separated list of all currently-enabled trace event + * categories. The current set of enabled trace event categories is + * determined by the union of all currently-enabled `Tracing` objects and + * any categories enabled using the `--trace-event-categories` flag. + */ + function getEnabledCategories(): string | undefined; +} diff --git a/node_modules/@types/node/ts3.6/assert.d.ts b/node_modules/@types/node/ts3.6/assert.d.ts new file mode 100755 index 0000000..6f3a33e --- /dev/null +++ b/node_modules/@types/node/ts3.6/assert.d.ts @@ -0,0 +1,103 @@ +declare module 'node:assert' { + import assert = require('assert'); + export = assert; +} + +declare module 'assert' { + /** An alias of `assert.ok()`. */ + function assert(value: any, message?: string | Error): void; + namespace assert { + class AssertionError extends Error { + actual: any; + expected: any; + operator: string; + generatedMessage: boolean; + code: 'ERR_ASSERTION'; + + constructor(options?: { + /** If provided, the error message is set to this value. */ + message?: string; + /** The `actual` property on the error instance. */ + actual?: any; + /** The `expected` property on the error instance. */ + expected?: any; + /** The `operator` property on the error instance. */ + operator?: string; + /** If provided, the generated stack trace omits frames before this function. */ + // tslint:disable-next-line:ban-types + stackStartFn?: Function; + }); + } + + class CallTracker { + calls(exact?: number): () => void; + calls any>(fn?: Func, exact?: number): Func; + report(): CallTrackerReportInformation[]; + verify(): void; + } + interface CallTrackerReportInformation { + message: string; + /** The actual number of times the function was called. */ + actual: number; + /** The number of times the function was expected to be called. */ + expected: number; + /** The name of the function that is wrapped. */ + operator: string; + /** A stack trace of the function. */ + stack: object; + } + + type AssertPredicate = RegExp | (new () => object) | ((thrown: any) => boolean) | object | Error; + + function fail(message?: string | Error): never; + /** @deprecated since v10.0.0 - use fail([message]) or other assert functions instead. */ + function fail( + actual: any, + expected: any, + message?: string | Error, + operator?: string, + // tslint:disable-next-line:ban-types + stackStartFn?: Function, + ): never; + function ok(value: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use strictEqual() instead. */ + function equal(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use notStrictEqual() instead. */ + function notEqual(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use deepStrictEqual() instead. */ + function deepEqual(actual: any, expected: any, message?: string | Error): void; + /** @deprecated since v9.9.0 - use notDeepStrictEqual() instead. */ + function notDeepEqual(actual: any, expected: any, message?: string | Error): void; + function strictEqual(actual: any, expected: any, message?: string | Error): void; + function notStrictEqual(actual: any, expected: any, message?: string | Error): void; + function deepStrictEqual(actual: any, expected: any, message?: string | Error): void; + function notDeepStrictEqual(actual: any, expected: any, message?: string | Error): void; + + function throws(block: () => any, message?: string | Error): void; + function throws(block: () => any, error: AssertPredicate, message?: string | Error): void; + function doesNotThrow(block: () => any, message?: string | Error): void; + function doesNotThrow(block: () => any, error: AssertPredicate, message?: string | Error): void; + + function ifError(value: any): void; + + function rejects(block: (() => Promise) | Promise, message?: string | Error): Promise; + function rejects( + block: (() => Promise) | Promise, + error: AssertPredicate, + message?: string | Error, + ): Promise; + function doesNotReject(block: (() => Promise) | Promise, message?: string | Error): Promise; + function doesNotReject( + block: (() => Promise) | Promise, + error: AssertPredicate, + message?: string | Error, + ): Promise; + + function match(value: string, regExp: RegExp, message?: string | Error): void; + function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void; + + const strict: typeof assert; + } + + export = assert; +} diff --git a/node_modules/@types/node/ts3.6/base.d.ts b/node_modules/@types/node/ts3.6/base.d.ts new file mode 100755 index 0000000..8f41e14 --- /dev/null +++ b/node_modules/@types/node/ts3.6/base.d.ts @@ -0,0 +1,66 @@ +// NOTE: These definitions support NodeJS and TypeScript 3.6 and earlier. + +// NOTE: TypeScript version-specific augmentations can be found in the following paths: +// - ~/base.d.ts - Shared definitions common to all TypeScript versions +// - ~/index.d.ts - Definitions specific to TypeScript 3.7 and above +// - ~/ts3.5/base.d.ts - Definitions specific to TypeScript 3.6 and earlier +// - ~/ts3.5/index.d.ts - Definitions specific to TypeScript 3.6 and earlier with assert pulled in + +// Reference required types from the default lib: +/// +/// +/// +/// + +// Base definitions for all NodeJS modules that are not specific to any version of TypeScript: +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +// TypeScript 3.5-specific augmentations: +/// + +// TypeScript 3.5-specific augmentations: +/// diff --git a/node_modules/@types/node/ts3.6/index.d.ts b/node_modules/@types/node/ts3.6/index.d.ts new file mode 100755 index 0000000..e34d7e5 --- /dev/null +++ b/node_modules/@types/node/ts3.6/index.d.ts @@ -0,0 +1,7 @@ +// NOTE: These definitions support NodeJS and TypeScript 3.5 - 3.6. +// This is required to enable typing assert in ts3.7 without causing errors +// Typically type modifications should be made in base.d.ts instead of here + +/// + +/// diff --git a/node_modules/@types/node/tty.d.ts b/node_modules/@types/node/tty.d.ts new file mode 100755 index 0000000..64b51b4 --- /dev/null +++ b/node_modules/@types/node/tty.d.ts @@ -0,0 +1,70 @@ +declare module 'node:tty' { + export * from 'tty'; +} + +declare module 'tty' { + import * as net from 'node:net'; + + function isatty(fd: number): boolean; + class ReadStream extends net.Socket { + constructor(fd: number, options?: net.SocketConstructorOpts); + isRaw: boolean; + setRawMode(mode: boolean): this; + isTTY: boolean; + } + /** + * -1 - to the left from cursor + * 0 - the entire line + * 1 - to the right from cursor + */ + type Direction = -1 | 0 | 1; + class WriteStream extends net.Socket { + constructor(fd: number); + addListener(event: string, listener: (...args: any[]) => void): this; + addListener(event: "resize", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "resize"): boolean; + + on(event: string, listener: (...args: any[]) => void): this; + on(event: "resize", listener: () => void): this; + + once(event: string, listener: (...args: any[]) => void): this; + once(event: "resize", listener: () => void): this; + + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "resize", listener: () => void): this; + + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "resize", listener: () => void): this; + + /** + * Clears the current line of this WriteStream in a direction identified by `dir`. + */ + clearLine(dir: Direction, callback?: () => void): boolean; + /** + * Clears this `WriteStream` from the current cursor down. + */ + clearScreenDown(callback?: () => void): boolean; + /** + * Moves this WriteStream's cursor to the specified position. + */ + cursorTo(x: number, y?: number, callback?: () => void): boolean; + cursorTo(x: number, callback: () => void): boolean; + /** + * Moves this WriteStream's cursor relative to its current position. + */ + moveCursor(dx: number, dy: number, callback?: () => void): boolean; + /** + * @default `process.env` + */ + getColorDepth(env?: {}): number; + hasColors(depth?: number): boolean; + hasColors(env?: {}): boolean; + hasColors(depth: number, env?: {}): boolean; + getWindowSize(): [number, number]; + columns: number; + rows: number; + isTTY: boolean; + } +} diff --git a/node_modules/@types/node/url.d.ts b/node_modules/@types/node/url.d.ts new file mode 100755 index 0000000..7186b94 --- /dev/null +++ b/node_modules/@types/node/url.d.ts @@ -0,0 +1,120 @@ +declare module 'node:url' { + export * from 'url'; +} + +declare module 'url' { + import { ParsedUrlQuery, ParsedUrlQueryInput } from 'node:querystring'; + + // Input to `url.format` + interface UrlObject { + auth?: string | null; + hash?: string | null; + host?: string | null; + hostname?: string | null; + href?: string | null; + pathname?: string | null; + protocol?: string | null; + search?: string | null; + slashes?: boolean | null; + port?: string | number | null; + query?: string | null | ParsedUrlQueryInput; + } + + // Output of `url.parse` + interface Url { + auth: string | null; + hash: string | null; + host: string | null; + hostname: string | null; + href: string; + path: string | null; + pathname: string | null; + protocol: string | null; + search: string | null; + slashes: boolean | null; + port: string | null; + query: string | null | ParsedUrlQuery; + } + + interface UrlWithParsedQuery extends Url { + query: ParsedUrlQuery; + } + + interface UrlWithStringQuery extends Url { + query: string | null; + } + + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function parse(urlStr: string): UrlWithStringQuery; + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function parse(urlStr: string, parseQueryString: false | undefined, slashesDenoteHost?: boolean): UrlWithStringQuery; + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function parse(urlStr: string, parseQueryString: true, slashesDenoteHost?: boolean): UrlWithParsedQuery; + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function parse(urlStr: string, parseQueryString: boolean, slashesDenoteHost?: boolean): Url; + + function format(URL: URL, options?: URLFormatOptions): string; + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function format(urlObject: UrlObject | string): string; + /** @deprecated since v11.0.0 - Use the WHATWG URL API. */ + function resolve(from: string, to: string): string; + + function domainToASCII(domain: string): string; + function domainToUnicode(domain: string): string; + + /** + * This function ensures the correct decodings of percent-encoded characters as + * well as ensuring a cross-platform valid absolute path string. + * @param url The file URL string or URL object to convert to a path. + */ + function fileURLToPath(url: string | URL): string; + + /** + * This function ensures that path is resolved absolutely, and that the URL + * control characters are correctly encoded when converting into a File URL. + * @param url The path to convert to a File URL. + */ + function pathToFileURL(url: string): URL; + + interface URLFormatOptions { + auth?: boolean; + fragment?: boolean; + search?: boolean; + unicode?: boolean; + } + + class URL { + constructor(input: string, base?: string | URL); + hash: string; + host: string; + hostname: string; + href: string; + readonly origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + readonly searchParams: URLSearchParams; + username: string; + toString(): string; + toJSON(): string; + } + + class URLSearchParams implements Iterable<[string, string]> { + constructor(init?: URLSearchParams | string | NodeJS.Dict> | Iterable<[string, string]> | ReadonlyArray<[string, string]>); + append(name: string, value: string): void; + delete(name: string): void; + entries(): IterableIterator<[string, string]>; + forEach(callback: (value: string, name: string, searchParams: this) => void): void; + get(name: string): string | null; + getAll(name: string): string[]; + has(name: string): boolean; + keys(): IterableIterator; + set(name: string, value: string): void; + sort(): void; + toString(): string; + values(): IterableIterator; + [Symbol.iterator](): IterableIterator<[string, string]>; + } +} diff --git a/node_modules/@types/node/util.d.ts b/node_modules/@types/node/util.d.ts new file mode 100755 index 0000000..8605bf9 --- /dev/null +++ b/node_modules/@types/node/util.d.ts @@ -0,0 +1,211 @@ +declare module 'node:util' { + export * from 'util'; +} + +declare module 'util' { + interface InspectOptions extends NodeJS.InspectOptions { } + type Style = 'special' | 'number' | 'bigint' | 'boolean' | 'undefined' | 'null' | 'string' | 'symbol' | 'date' | 'regexp' | 'module'; + type CustomInspectFunction = (depth: number, options: InspectOptionsStylized) => string; + interface InspectOptionsStylized extends InspectOptions { + stylize(text: string, styleType: Style): string; + } + function format(format?: any, ...param: any[]): string; + function formatWithOptions(inspectOptions: InspectOptions, format?: any, ...param: any[]): string; + /** @deprecated since v0.11.3 - use a third party module instead. */ + function log(string: string): void; + function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string; + function inspect(object: any, options: InspectOptions): string; + namespace inspect { + let colors: NodeJS.Dict<[number, number]>; + let styles: { + [K in Style]: string + }; + let defaultOptions: InspectOptions; + /** + * Allows changing inspect settings from the repl. + */ + let replDefaults: InspectOptions; + const custom: unique symbol; + } + /** @deprecated since v4.0.0 - use `Array.isArray()` instead. */ + function isArray(object: any): object is any[]; + /** @deprecated since v4.0.0 - use `util.types.isRegExp()` instead. */ + function isRegExp(object: any): object is RegExp; + /** @deprecated since v4.0.0 - use `util.types.isDate()` instead. */ + function isDate(object: any): object is Date; + /** @deprecated since v4.0.0 - use `util.types.isNativeError()` instead. */ + function isError(object: any): object is Error; + function inherits(constructor: any, superConstructor: any): void; + function debuglog(key: string): (msg: string, ...param: any[]) => void; + /** @deprecated since v4.0.0 - use `typeof value === 'boolean'` instead. */ + function isBoolean(object: any): object is boolean; + /** @deprecated since v4.0.0 - use `Buffer.isBuffer()` instead. */ + function isBuffer(object: any): object is Buffer; + /** @deprecated since v4.0.0 - use `typeof value === 'function'` instead. */ + function isFunction(object: any): boolean; + /** @deprecated since v4.0.0 - use `value === null` instead. */ + function isNull(object: any): object is null; + /** @deprecated since v4.0.0 - use `value === null || value === undefined` instead. */ + function isNullOrUndefined(object: any): object is null | undefined; + /** @deprecated since v4.0.0 - use `typeof value === 'number'` instead. */ + function isNumber(object: any): object is number; + /** @deprecated since v4.0.0 - use `value !== null && typeof value === 'object'` instead. */ + function isObject(object: any): boolean; + /** @deprecated since v4.0.0 - use `(typeof value !== 'object' && typeof value !== 'function') || value === null` instead. */ + function isPrimitive(object: any): boolean; + /** @deprecated since v4.0.0 - use `typeof value === 'string'` instead. */ + function isString(object: any): object is string; + /** @deprecated since v4.0.0 - use `typeof value === 'symbol'` instead. */ + function isSymbol(object: any): object is symbol; + /** @deprecated since v4.0.0 - use `value === undefined` instead. */ + function isUndefined(object: any): object is undefined; + function deprecate(fn: T, message: string, code?: string): T; + function isDeepStrictEqual(val1: any, val2: any): boolean; + + function callbackify(fn: () => Promise): (callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify(fn: () => Promise): (callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void; + function callbackify(fn: (arg1: T1) => Promise): (arg1: T1, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify(fn: (arg1: T1) => Promise): (arg1: T1, callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void; + function callbackify(fn: (arg1: T1, arg2: T2) => Promise): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify(fn: (arg1: T1, arg2: T2) => Promise): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + function callbackify(fn: (arg1: T1, arg2: T2, arg3: T3) => Promise): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3) => Promise): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6, callback: (err: NodeJS.ErrnoException) => void) => void; + function callbackify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + + interface CustomPromisifyLegacy extends Function { + __promisify__: TCustom; + } + + interface CustomPromisifySymbol extends Function { + [promisify.custom]: TCustom; + } + + type CustomPromisify = CustomPromisifySymbol | CustomPromisifyLegacy; + + function promisify(fn: CustomPromisify): TCustom; + function promisify(fn: (callback: (err: any, result: TResult) => void) => void): () => Promise; + function promisify(fn: (callback: (err?: any) => void) => void): () => Promise; + function promisify(fn: (arg1: T1, callback: (err: any, result: TResult) => void) => void): (arg1: T1) => Promise; + function promisify(fn: (arg1: T1, callback: (err?: any) => void) => void): (arg1: T1) => Promise; + function promisify(fn: (arg1: T1, arg2: T2, callback: (err: any, result: TResult) => void) => void): (arg1: T1, arg2: T2) => Promise; + function promisify(fn: (arg1: T1, arg2: T2, callback: (err?: any) => void) => void): (arg1: T1, arg2: T2) => Promise; + function promisify(fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err: any, result: TResult) => void) => void): + (arg1: T1, arg2: T2, arg3: T3) => Promise; + function promisify(fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err?: any) => void) => void): (arg1: T1, arg2: T2, arg3: T3) => Promise; + function promisify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise; + function promisify(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err?: any) => void) => void): + (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise; + function promisify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise; + function promisify( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err?: any) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise; + function promisify(fn: Function): Function; + namespace promisify { + const custom: unique symbol; + } + + namespace types { + function isAnyArrayBuffer(object: any): object is ArrayBufferLike; + function isArgumentsObject(object: any): object is IArguments; + function isArrayBuffer(object: any): object is ArrayBuffer; + function isArrayBufferView(object: any): object is NodeJS.ArrayBufferView; + function isAsyncFunction(object: any): boolean; + function isBigInt64Array(value: any): value is BigInt64Array; + function isBigUint64Array(value: any): value is BigUint64Array; + function isBooleanObject(object: any): object is Boolean; + function isBoxedPrimitive(object: any): object is String | Number | BigInt | Boolean | Symbol; + function isDataView(object: any): object is DataView; + function isDate(object: any): object is Date; + function isExternal(object: any): boolean; + function isFloat32Array(object: any): object is Float32Array; + function isFloat64Array(object: any): object is Float64Array; + function isGeneratorFunction(object: any): object is GeneratorFunction; + function isGeneratorObject(object: any): object is Generator; + function isInt8Array(object: any): object is Int8Array; + function isInt16Array(object: any): object is Int16Array; + function isInt32Array(object: any): object is Int32Array; + function isMap( + object: T | {}, + ): object is T extends ReadonlyMap + ? unknown extends T + ? never + : ReadonlyMap + : Map; + function isMapIterator(object: any): boolean; + function isModuleNamespaceObject(value: any): boolean; + function isNativeError(object: any): object is Error; + function isNumberObject(object: any): object is Number; + function isPromise(object: any): object is Promise; + function isProxy(object: any): boolean; + function isRegExp(object: any): object is RegExp; + function isSet( + object: T | {}, + ): object is T extends ReadonlySet + ? unknown extends T + ? never + : ReadonlySet + : Set; + function isSetIterator(object: any): boolean; + function isSharedArrayBuffer(object: any): object is SharedArrayBuffer; + function isStringObject(object: any): object is String; + function isSymbolObject(object: any): object is Symbol; + function isTypedArray(object: any): object is NodeJS.TypedArray; + function isUint8Array(object: any): object is Uint8Array; + function isUint8ClampedArray(object: any): object is Uint8ClampedArray; + function isUint16Array(object: any): object is Uint16Array; + function isUint32Array(object: any): object is Uint32Array; + function isWeakMap(object: any): object is WeakMap; + function isWeakSet(object: any): object is WeakSet; + } + + class TextDecoder { + readonly encoding: string; + readonly fatal: boolean; + readonly ignoreBOM: boolean; + constructor( + encoding?: string, + options?: { fatal?: boolean; ignoreBOM?: boolean } + ); + decode( + input?: NodeJS.ArrayBufferView | ArrayBuffer | null, + options?: { stream?: boolean } + ): string; + } + + interface EncodeIntoResult { + /** + * The read Unicode code units of input. + */ + + read: number; + /** + * The written UTF-8 bytes of output. + */ + written: number; + } + + class TextEncoder { + readonly encoding: string; + encode(input?: string): Uint8Array; + encodeInto(input: string, output: Uint8Array): EncodeIntoResult; + } +} diff --git a/node_modules/@types/node/v8.d.ts b/node_modules/@types/node/v8.d.ts new file mode 100755 index 0000000..c213196 --- /dev/null +++ b/node_modules/@types/node/v8.d.ts @@ -0,0 +1,191 @@ +declare module 'node:v8' { + export * from 'v8'; +} + +declare module 'v8' { + import { Readable } from 'node:stream'; + + interface HeapSpaceInfo { + space_name: string; + space_size: number; + space_used_size: number; + space_available_size: number; + physical_space_size: number; + } + + // ** Signifies if the --zap_code_space option is enabled or not. 1 == enabled, 0 == disabled. */ + type DoesZapCodeSpaceFlag = 0 | 1; + + interface HeapInfo { + total_heap_size: number; + total_heap_size_executable: number; + total_physical_size: number; + total_available_size: number; + used_heap_size: number; + heap_size_limit: number; + malloced_memory: number; + peak_malloced_memory: number; + does_zap_garbage: DoesZapCodeSpaceFlag; + number_of_native_contexts: number; + number_of_detached_contexts: number; + } + + interface HeapCodeStatistics { + code_and_metadata_size: number; + bytecode_and_metadata_size: number; + external_script_source_size: number; + } + + /** + * Returns an integer representing a "version tag" derived from the V8 version, command line flags and detected CPU features. + * This is useful for determining whether a vm.Script cachedData buffer is compatible with this instance of V8. + */ + function cachedDataVersionTag(): number; + + function getHeapStatistics(): HeapInfo; + function getHeapSpaceStatistics(): HeapSpaceInfo[]; + function setFlagsFromString(flags: string): void; + /** + * Generates a snapshot of the current V8 heap and returns a Readable + * Stream that may be used to read the JSON serialized representation. + * This conversation was marked as resolved by joyeecheung + * This JSON stream format is intended to be used with tools such as + * Chrome DevTools. The JSON schema is undocumented and specific to the + * V8 engine, and may change from one version of V8 to the next. + */ + function getHeapSnapshot(): Readable; + + /** + * + * @param fileName The file path where the V8 heap snapshot is to be + * saved. If not specified, a file name with the pattern + * `'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'` will be + * generated, where `{pid}` will be the PID of the Node.js process, + * `{thread_id}` will be `0` when `writeHeapSnapshot()` is called from + * the main Node.js thread or the id of a worker thread. + */ + function writeHeapSnapshot(fileName?: string): string; + + function getHeapCodeStatistics(): HeapCodeStatistics; + + class Serializer { + /** + * Writes out a header, which includes the serialization format version. + */ + writeHeader(): void; + + /** + * Serializes a JavaScript value and adds the serialized representation to the internal buffer. + * This throws an error if value cannot be serialized. + */ + writeValue(val: any): boolean; + + /** + * Returns the stored internal buffer. + * This serializer should not be used once the buffer is released. + * Calling this method results in undefined behavior if a previous write has failed. + */ + releaseBuffer(): Buffer; + + /** + * Marks an ArrayBuffer as having its contents transferred out of band.\ + * Pass the corresponding ArrayBuffer in the deserializing context to deserializer.transferArrayBuffer(). + */ + transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void; + + /** + * Write a raw 32-bit unsigned integer. + */ + writeUint32(value: number): void; + + /** + * Write a raw 64-bit unsigned integer, split into high and low 32-bit parts. + */ + writeUint64(hi: number, lo: number): void; + + /** + * Write a JS number value. + */ + writeDouble(value: number): void; + + /** + * Write raw bytes into the serializer’s internal buffer. + * The deserializer will require a way to compute the length of the buffer. + */ + writeRawBytes(buffer: NodeJS.TypedArray): void; + } + + /** + * A subclass of `Serializer` that serializes `TypedArray` (in particular `Buffer`) and `DataView` objects as host objects, + * and only stores the part of their underlying `ArrayBuffers` that they are referring to. + */ + class DefaultSerializer extends Serializer { + } + + class Deserializer { + constructor(data: NodeJS.TypedArray); + /** + * Reads and validates a header (including the format version). + * May, for example, reject an invalid or unsupported wire format. + * In that case, an Error is thrown. + */ + readHeader(): boolean; + + /** + * Deserializes a JavaScript value from the buffer and returns it. + */ + readValue(): any; + + /** + * Marks an ArrayBuffer as having its contents transferred out of band. + * Pass the corresponding `ArrayBuffer` in the serializing context to serializer.transferArrayBuffer() + * (or return the id from serializer._getSharedArrayBufferId() in the case of SharedArrayBuffers). + */ + transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void; + + /** + * Reads the underlying wire format version. + * Likely mostly to be useful to legacy code reading old wire format versions. + * May not be called before .readHeader(). + */ + getWireFormatVersion(): number; + + /** + * Read a raw 32-bit unsigned integer and return it. + */ + readUint32(): number; + + /** + * Read a raw 64-bit unsigned integer and return it as an array [hi, lo] with two 32-bit unsigned integer entries. + */ + readUint64(): [number, number]; + + /** + * Read a JS number value. + */ + readDouble(): number; + + /** + * Read raw bytes from the deserializer’s internal buffer. + * The length parameter must correspond to the length of the buffer that was passed to serializer.writeRawBytes(). + */ + readRawBytes(length: number): Buffer; + } + + /** + * A subclass of `Serializer` that serializes `TypedArray` (in particular `Buffer`) and `DataView` objects as host objects, + * and only stores the part of their underlying `ArrayBuffers` that they are referring to. + */ + class DefaultDeserializer extends Deserializer { + } + + /** + * Uses a `DefaultSerializer` to serialize value into a buffer. + */ + function serialize(value: any): Buffer; + + /** + * Uses a `DefaultDeserializer` with default options to read a JS value from a buffer. + */ + function deserialize(data: NodeJS.TypedArray): any; +} diff --git a/node_modules/@types/node/vm.d.ts b/node_modules/@types/node/vm.d.ts new file mode 100755 index 0000000..3e7d2c6 --- /dev/null +++ b/node_modules/@types/node/vm.d.ts @@ -0,0 +1,156 @@ +declare module 'node:vm' { + export * from 'vm'; +} + +declare module 'vm' { + interface Context extends NodeJS.Dict { } + interface BaseOptions { + /** + * Specifies the filename used in stack traces produced by this script. + * Default: `''`. + */ + filename?: string; + /** + * Specifies the line number offset that is displayed in stack traces produced by this script. + * Default: `0`. + */ + lineOffset?: number; + /** + * Specifies the column number offset that is displayed in stack traces produced by this script. + * Default: `0` + */ + columnOffset?: number; + } + interface ScriptOptions extends BaseOptions { + displayErrors?: boolean; + timeout?: number; + cachedData?: Buffer; + /** @deprecated in favor of `script.createCachedData()` */ + produceCachedData?: boolean; + } + interface RunningScriptOptions extends BaseOptions { + /** + * When `true`, if an `Error` occurs while compiling the `code`, the line of code causing the error is attached to the stack trace. + * Default: `true`. + */ + displayErrors?: boolean; + /** + * Specifies the number of milliseconds to execute code before terminating execution. + * If execution is terminated, an `Error` will be thrown. This value must be a strictly positive integer. + */ + timeout?: number; + /** + * If `true`, the execution will be terminated when `SIGINT` (Ctrl+C) is received. + * Existing handlers for the event that have been attached via `process.on('SIGINT')` will be disabled during script execution, but will continue to work after that. + * If execution is terminated, an `Error` will be thrown. + * Default: `false`. + */ + breakOnSigint?: boolean; + /** + * If set to `afterEvaluate`, microtasks will be run immediately after the script has run. + */ + microtaskMode?: 'afterEvaluate'; + } + interface CompileFunctionOptions extends BaseOptions { + /** + * Provides an optional data with V8's code cache data for the supplied source. + */ + cachedData?: Buffer; + /** + * Specifies whether to produce new cache data. + * Default: `false`, + */ + produceCachedData?: boolean; + /** + * The sandbox/context in which the said function should be compiled in. + */ + parsingContext?: Context; + + /** + * An array containing a collection of context extensions (objects wrapping the current scope) to be applied while compiling + */ + contextExtensions?: Object[]; + } + + interface CreateContextOptions { + /** + * Human-readable name of the newly created context. + * @default 'VM Context i' Where i is an ascending numerical index of the created context. + */ + name?: string; + /** + * Corresponds to the newly created context for display purposes. + * The origin should be formatted like a `URL`, but with only the scheme, host, and port (if necessary), + * like the value of the `url.origin` property of a URL object. + * Most notably, this string should omit the trailing slash, as that denotes a path. + * @default '' + */ + origin?: string; + codeGeneration?: { + /** + * If set to false any calls to eval or function constructors (Function, GeneratorFunction, etc) + * will throw an EvalError. + * @default true + */ + strings?: boolean; + /** + * If set to false any attempt to compile a WebAssembly module will throw a WebAssembly.CompileError. + * @default true + */ + wasm?: boolean; + }; + /** + * If set to `afterEvaluate`, microtasks will be run immediately after the script has run. + */ + microtaskMode?: 'afterEvaluate'; + } + + type MeasureMemoryMode = 'summary' | 'detailed'; + + interface MeasureMemoryOptions { + /** + * @default 'summary' + */ + mode?: MeasureMemoryMode; + context?: Context; + } + + interface MemoryMeasurement { + total: { + jsMemoryEstimate: number; + jsMemoryRange: [number, number]; + }; + } + + class Script { + constructor(code: string, options?: ScriptOptions); + runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; + runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; + runInThisContext(options?: RunningScriptOptions): any; + createCachedData(): Buffer; + cachedDataRejected?: boolean; + } + function createContext(sandbox?: Context, options?: CreateContextOptions): Context; + function isContext(sandbox: Context): boolean; + function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions | string): any; + function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions | string): any; + function runInThisContext(code: string, options?: RunningScriptOptions | string): any; + function compileFunction(code: string, params?: ReadonlyArray, options?: CompileFunctionOptions): Function; + + /** + * Measure the memory known to V8 and used by the current execution context or a specified context. + * + * The format of the object that the returned Promise may resolve with is + * specific to the V8 engine and may change from one version of V8 to the next. + * + * The returned result is different from the statistics returned by + * `v8.getHeapSpaceStatistics()` in that `vm.measureMemory()` measures + * the memory reachable by V8 from a specific context, while + * `v8.getHeapSpaceStatistics()` measures the memory used by an instance + * of V8 engine, which can switch among multiple contexts that reference + * objects in the heap of one engine. + * + * @experimental + */ + function measureMemory(options?: MeasureMemoryOptions): Promise; +} diff --git a/node_modules/@types/node/wasi.d.ts b/node_modules/@types/node/wasi.d.ts new file mode 100755 index 0000000..43b3854 --- /dev/null +++ b/node_modules/@types/node/wasi.d.ts @@ -0,0 +1,90 @@ +declare module 'node:wasi' { + export * from 'wasi'; +} + +declare module 'wasi' { + interface WASIOptions { + /** + * An array of strings that the WebAssembly application will + * see as command line arguments. The first argument is the virtual path to the + * WASI command itself. + */ + args?: string[]; + + /** + * An object similar to `process.env` that the WebAssembly + * application will see as its environment. + */ + env?: object; + + /** + * This object represents the WebAssembly application's + * sandbox directory structure. The string keys of `preopens` are treated as + * directories within the sandbox. The corresponding values in `preopens` are + * the real paths to those directories on the host machine. + */ + preopens?: NodeJS.Dict; + + /** + * By default, WASI applications terminate the Node.js + * process via the `__wasi_proc_exit()` function. Setting this option to `true` + * causes `wasi.start()` to return the exit code rather than terminate the + * process. + * @default false + */ + returnOnExit?: boolean; + + /** + * The file descriptor used as standard input in the WebAssembly application. + * @default 0 + */ + stdin?: number; + + /** + * The file descriptor used as standard output in the WebAssembly application. + * @default 1 + */ + stdout?: number; + + /** + * The file descriptor used as standard error in the WebAssembly application. + * @default 2 + */ + stderr?: number; + } + + class WASI { + constructor(options?: WASIOptions); + /** + * + * Attempt to begin execution of `instance` by invoking its `_start()` export. + * If `instance` does not contain a `_start()` export, then `start()` attempts to + * invoke the `__wasi_unstable_reactor_start()` export. If neither of those exports + * is present on `instance`, then `start()` does nothing. + * + * `start()` requires that `instance` exports a [`WebAssembly.Memory`][] named + * `memory`. If `instance` does not have a `memory` export an exception is thrown. + * + * If `start()` is called more than once, an exception is thrown. + */ + start(instance: object): void; // TODO: avoid DOM dependency until WASM moved to own lib. + + /** + * Attempt to initialize `instance` as a WASI reactor by invoking its `_initialize()` export, if it is present. + * If `instance` contains a `_start()` export, then an exception is thrown. + * + * `start()` requires that `instance` exports a [`WebAssembly.Memory`][] named + * `memory`. If `instance` does not have a `memory` export an exception is thrown. + * + * If `initialize()` is called more than once, an exception is thrown. + */ + initialize(instance: object): void; // TODO: avoid DOM dependency until WASM moved to own lib. + + /** + * Is an object that implements the WASI system call API. This object + * should be passed as the `wasi_snapshot_preview1` import during the instantiation of a + * [`WebAssembly.Instance`][]. + */ + readonly wasiImport: NodeJS.Dict; // TODO: Narrow to DOM types + } +} diff --git a/node_modules/@types/node/worker_threads.d.ts b/node_modules/@types/node/worker_threads.d.ts new file mode 100755 index 0000000..745231f --- /dev/null +++ b/node_modules/@types/node/worker_threads.d.ts @@ -0,0 +1,245 @@ +declare module 'node:worker_threads' { + export * from 'worker_threads'; +} + +declare module 'worker_threads' { + import { Context } from 'node:vm'; + import EventEmitter = require('node:events'); + import { Readable, Writable } from 'node:stream'; + import { URL } from 'node:url'; + import { FileHandle } from 'node:fs/promises'; + + const isMainThread: boolean; + const parentPort: null | MessagePort; + const resourceLimits: ResourceLimits; + const SHARE_ENV: unique symbol; + const threadId: number; + const workerData: any; + + class MessageChannel { + readonly port1: MessagePort; + readonly port2: MessagePort; + } + + type TransferListItem = ArrayBuffer | MessagePort | FileHandle; + + class MessagePort extends EventEmitter { + close(): void; + postMessage(value: any, transferList?: ReadonlyArray): void; + ref(): void; + unref(): void; + start(): void; + + addListener(event: "close", listener: () => void): this; + addListener(event: "message", listener: (value: any) => void): this; + addListener(event: "messageerror", listener: (error: Error) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "close"): boolean; + emit(event: "message", value: any): boolean; + emit(event: "messageerror", error: Error): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "close", listener: () => void): this; + on(event: "message", listener: (value: any) => void): this; + on(event: "messageerror", listener: (error: Error) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "close", listener: () => void): this; + once(event: "message", listener: (value: any) => void): this; + once(event: "messageerror", listener: (error: Error) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "close", listener: () => void): this; + prependListener(event: "message", listener: (value: any) => void): this; + prependListener(event: "messageerror", listener: (error: Error) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "message", listener: (value: any) => void): this; + prependOnceListener(event: "messageerror", listener: (error: Error) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + removeListener(event: "close", listener: () => void): this; + removeListener(event: "message", listener: (value: any) => void): this; + removeListener(event: "messageerror", listener: (error: Error) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + + off(event: "close", listener: () => void): this; + off(event: "message", listener: (value: any) => void): this; + off(event: "messageerror", listener: (error: Error) => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; + } + + interface WorkerOptions { + /** + * List of arguments which would be stringified and appended to + * `process.argv` in the worker. This is mostly similar to the `workerData` + * but the values will be available on the global `process.argv` as if they + * were passed as CLI options to the script. + */ + argv?: any[]; + env?: NodeJS.Dict | typeof SHARE_ENV; + eval?: boolean; + workerData?: any; + stdin?: boolean; + stdout?: boolean; + stderr?: boolean; + execArgv?: string[]; + resourceLimits?: ResourceLimits; + /** + * Additional data to send in the first worker message. + */ + transferList?: TransferListItem[]; + /** + * @default true + */ + trackUnmanagedFds?: boolean; + } + + interface ResourceLimits { + /** + * The maximum size of a heap space for recently created objects. + */ + maxYoungGenerationSizeMb?: number; + /** + * The maximum size of the main heap in MB. + */ + maxOldGenerationSizeMb?: number; + /** + * The size of a pre-allocated memory range used for generated code. + */ + codeRangeSizeMb?: number; + /** + * The default maximum stack size for the thread. Small values may lead to unusable Worker instances. + * @default 4 + */ + stackSizeMb?: number; + } + + class Worker extends EventEmitter { + readonly stdin: Writable | null; + readonly stdout: Readable; + readonly stderr: Readable; + readonly threadId: number; + readonly resourceLimits?: ResourceLimits; + + /** + * @param filename The path to the Worker’s main script or module. + * Must be either an absolute path or a relative path (i.e. relative to the current working directory) starting with ./ or ../, + * or a WHATWG URL object using file: protocol. If options.eval is true, this is a string containing JavaScript code rather than a path. + */ + constructor(filename: string | URL, options?: WorkerOptions); + + postMessage(value: any, transferList?: ReadonlyArray): void; + ref(): void; + unref(): void; + /** + * Stop all JavaScript execution in the worker thread as soon as possible. + * Returns a Promise for the exit code that is fulfilled when the `exit` event is emitted. + */ + terminate(): Promise; + + /** + * Returns a readable stream for a V8 snapshot of the current state of the Worker. + * See [`v8.getHeapSnapshot()`][] for more details. + * + * If the Worker thread is no longer running, which may occur before the + * [`'exit'` event][] is emitted, the returned `Promise` will be rejected + * immediately with an [`ERR_WORKER_NOT_RUNNING`][] error + */ + getHeapSnapshot(): Promise; + + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "exit", listener: (exitCode: number) => void): this; + addListener(event: "message", listener: (value: any) => void): this; + addListener(event: "messageerror", listener: (error: Error) => void): this; + addListener(event: "online", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + + emit(event: "error", err: Error): boolean; + emit(event: "exit", exitCode: number): boolean; + emit(event: "message", value: any): boolean; + emit(event: "messageerror", error: Error): boolean; + emit(event: "online"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + + on(event: "error", listener: (err: Error) => void): this; + on(event: "exit", listener: (exitCode: number) => void): this; + on(event: "message", listener: (value: any) => void): this; + on(event: "messageerror", listener: (error: Error) => void): this; + on(event: "online", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + + once(event: "error", listener: (err: Error) => void): this; + once(event: "exit", listener: (exitCode: number) => void): this; + once(event: "message", listener: (value: any) => void): this; + once(event: "messageerror", listener: (error: Error) => void): this; + once(event: "online", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "exit", listener: (exitCode: number) => void): this; + prependListener(event: "message", listener: (value: any) => void): this; + prependListener(event: "messageerror", listener: (error: Error) => void): this; + prependListener(event: "online", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "exit", listener: (exitCode: number) => void): this; + prependOnceListener(event: "message", listener: (value: any) => void): this; + prependOnceListener(event: "messageerror", listener: (error: Error) => void): this; + prependOnceListener(event: "online", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "exit", listener: (exitCode: number) => void): this; + removeListener(event: "message", listener: (value: any) => void): this; + removeListener(event: "messageerror", listener: (error: Error) => void): this; + removeListener(event: "online", listener: () => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + + off(event: "error", listener: (err: Error) => void): this; + off(event: "exit", listener: (exitCode: number) => void): this; + off(event: "message", listener: (value: any) => void): this; + off(event: "messageerror", listener: (error: Error) => void): this; + off(event: "online", listener: () => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; + } + + /** + * Mark an object as not transferable. + * If `object` occurs in the transfer list of a `port.postMessage()` call, it will be ignored. + * + * In particular, this makes sense for objects that can be cloned, rather than transferred, + * and which are used by other objects on the sending side. For example, Node.js marks + * the `ArrayBuffer`s it uses for its Buffer pool with this. + * + * This operation cannot be undone. + */ + function markAsUntransferable(object: object): void; + + /** + * Transfer a `MessagePort` to a different `vm` Context. The original `port` + * object will be rendered unusable, and the returned `MessagePort` instance will + * take its place. + * + * The returned `MessagePort` will be an object in the target context, and will + * inherit from its global `Object` class. Objects passed to the + * `port.onmessage()` listener will also be created in the target context + * and inherit from its global `Object` class. + * + * However, the created `MessagePort` will no longer inherit from + * `EventEmitter`, and only `port.onmessage()` can be used to receive + * events using it. + */ + function moveMessagePortToContext(port: MessagePort, context: Context): MessagePort; + + /** + * Receive a single message from a given `MessagePort`. If no message is available, + * `undefined` is returned, otherwise an object with a single `message` property + * that contains the message payload, corresponding to the oldest message in the + * `MessagePort`’s queue. + */ + function receiveMessageOnPort(port: MessagePort): { message: any } | undefined; +} diff --git a/node_modules/@types/node/zlib.d.ts b/node_modules/@types/node/zlib.d.ts new file mode 100755 index 0000000..f3fbc44 --- /dev/null +++ b/node_modules/@types/node/zlib.d.ts @@ -0,0 +1,365 @@ +declare module 'node:zlib' { + export * from 'zlib'; +} + +declare module 'zlib' { + import * as stream from 'node:stream'; + + interface ZlibOptions { + /** + * @default constants.Z_NO_FLUSH + */ + flush?: number; + /** + * @default constants.Z_FINISH + */ + finishFlush?: number; + /** + * @default 16*1024 + */ + chunkSize?: number; + windowBits?: number; + level?: number; // compression only + memLevel?: number; // compression only + strategy?: number; // compression only + dictionary?: NodeJS.ArrayBufferView | ArrayBuffer; // deflate/inflate only, empty dictionary by default + info?: boolean; + maxOutputLength?: number; + } + + interface BrotliOptions { + /** + * @default constants.BROTLI_OPERATION_PROCESS + */ + flush?: number; + /** + * @default constants.BROTLI_OPERATION_FINISH + */ + finishFlush?: number; + /** + * @default 16*1024 + */ + chunkSize?: number; + params?: { + /** + * Each key is a `constants.BROTLI_*` constant. + */ + [key: number]: boolean | number; + }; + maxOutputLength?: number; + } + + interface Zlib { + /** @deprecated Use bytesWritten instead. */ + readonly bytesRead: number; + readonly bytesWritten: number; + shell?: boolean | string; + close(callback?: () => void): void; + flush(kind?: number, callback?: () => void): void; + flush(callback?: () => void): void; + } + + interface ZlibParams { + params(level: number, strategy: number, callback: () => void): void; + } + + interface ZlibReset { + reset(): void; + } + + interface BrotliCompress extends stream.Transform, Zlib { } + interface BrotliDecompress extends stream.Transform, Zlib { } + interface Gzip extends stream.Transform, Zlib { } + interface Gunzip extends stream.Transform, Zlib { } + interface Deflate extends stream.Transform, Zlib, ZlibReset, ZlibParams { } + interface Inflate extends stream.Transform, Zlib, ZlibReset { } + interface DeflateRaw extends stream.Transform, Zlib, ZlibReset, ZlibParams { } + interface InflateRaw extends stream.Transform, Zlib, ZlibReset { } + interface Unzip extends stream.Transform, Zlib { } + + function createBrotliCompress(options?: BrotliOptions): BrotliCompress; + function createBrotliDecompress(options?: BrotliOptions): BrotliDecompress; + function createGzip(options?: ZlibOptions): Gzip; + function createGunzip(options?: ZlibOptions): Gunzip; + function createDeflate(options?: ZlibOptions): Deflate; + function createInflate(options?: ZlibOptions): Inflate; + function createDeflateRaw(options?: ZlibOptions): DeflateRaw; + function createInflateRaw(options?: ZlibOptions): InflateRaw; + function createUnzip(options?: ZlibOptions): Unzip; + + type InputType = string | ArrayBuffer | NodeJS.ArrayBufferView; + + type CompressCallback = (error: Error | null, result: Buffer) => void; + + function brotliCompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void; + function brotliCompress(buf: InputType, callback: CompressCallback): void; + namespace brotliCompress { + function __promisify__(buffer: InputType, options?: BrotliOptions): Promise; + } + + function brotliCompressSync(buf: InputType, options?: BrotliOptions): Buffer; + + function brotliDecompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void; + function brotliDecompress(buf: InputType, callback: CompressCallback): void; + namespace brotliDecompress { + function __promisify__(buffer: InputType, options?: BrotliOptions): Promise; + } + + function brotliDecompressSync(buf: InputType, options?: BrotliOptions): Buffer; + + function deflate(buf: InputType, callback: CompressCallback): void; + function deflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace deflate { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function deflateSync(buf: InputType, options?: ZlibOptions): Buffer; + + function deflateRaw(buf: InputType, callback: CompressCallback): void; + function deflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace deflateRaw { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function deflateRawSync(buf: InputType, options?: ZlibOptions): Buffer; + + function gzip(buf: InputType, callback: CompressCallback): void; + function gzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace gzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function gzipSync(buf: InputType, options?: ZlibOptions): Buffer; + + function gunzip(buf: InputType, callback: CompressCallback): void; + function gunzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace gunzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function gunzipSync(buf: InputType, options?: ZlibOptions): Buffer; + + function inflate(buf: InputType, callback: CompressCallback): void; + function inflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace inflate { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function inflateSync(buf: InputType, options?: ZlibOptions): Buffer; + + function inflateRaw(buf: InputType, callback: CompressCallback): void; + function inflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace inflateRaw { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function inflateRawSync(buf: InputType, options?: ZlibOptions): Buffer; + + function unzip(buf: InputType, callback: CompressCallback): void; + function unzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace unzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise; + } + + function unzipSync(buf: InputType, options?: ZlibOptions): Buffer; + + namespace constants { + const BROTLI_DECODE: number; + const BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: number; + const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: number; + const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: number; + const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: number; + const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: number; + const BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: number; + const BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: number; + const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: number; + const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: number; + const BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: number; + const BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: number; + const BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: number; + const BROTLI_DECODER_ERROR_FORMAT_DISTANCE: number; + const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: number; + const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: number; + const BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: number; + const BROTLI_DECODER_ERROR_FORMAT_PADDING_1: number; + const BROTLI_DECODER_ERROR_FORMAT_PADDING_2: number; + const BROTLI_DECODER_ERROR_FORMAT_RESERVED: number; + const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: number; + const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: number; + const BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: number; + const BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: number; + const BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: number; + const BROTLI_DECODER_ERROR_UNREACHABLE: number; + const BROTLI_DECODER_NEEDS_MORE_INPUT: number; + const BROTLI_DECODER_NEEDS_MORE_OUTPUT: number; + const BROTLI_DECODER_NO_ERROR: number; + const BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: number; + const BROTLI_DECODER_PARAM_LARGE_WINDOW: number; + const BROTLI_DECODER_RESULT_ERROR: number; + const BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: number; + const BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: number; + const BROTLI_DECODER_RESULT_SUCCESS: number; + const BROTLI_DECODER_SUCCESS: number; + + const BROTLI_DEFAULT_MODE: number; + const BROTLI_DEFAULT_QUALITY: number; + const BROTLI_DEFAULT_WINDOW: number; + const BROTLI_ENCODE: number; + const BROTLI_LARGE_MAX_WINDOW_BITS: number; + const BROTLI_MAX_INPUT_BLOCK_BITS: number; + const BROTLI_MAX_QUALITY: number; + const BROTLI_MAX_WINDOW_BITS: number; + const BROTLI_MIN_INPUT_BLOCK_BITS: number; + const BROTLI_MIN_QUALITY: number; + const BROTLI_MIN_WINDOW_BITS: number; + + const BROTLI_MODE_FONT: number; + const BROTLI_MODE_GENERIC: number; + const BROTLI_MODE_TEXT: number; + + const BROTLI_OPERATION_EMIT_METADATA: number; + const BROTLI_OPERATION_FINISH: number; + const BROTLI_OPERATION_FLUSH: number; + const BROTLI_OPERATION_PROCESS: number; + + const BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: number; + const BROTLI_PARAM_LARGE_WINDOW: number; + const BROTLI_PARAM_LGBLOCK: number; + const BROTLI_PARAM_LGWIN: number; + const BROTLI_PARAM_MODE: number; + const BROTLI_PARAM_NDIRECT: number; + const BROTLI_PARAM_NPOSTFIX: number; + const BROTLI_PARAM_QUALITY: number; + const BROTLI_PARAM_SIZE_HINT: number; + + const DEFLATE: number; + const DEFLATERAW: number; + const GUNZIP: number; + const GZIP: number; + const INFLATE: number; + const INFLATERAW: number; + const UNZIP: number; + + // Allowed flush values. + const Z_NO_FLUSH: number; + const Z_PARTIAL_FLUSH: number; + const Z_SYNC_FLUSH: number; + const Z_FULL_FLUSH: number; + const Z_FINISH: number; + const Z_BLOCK: number; + const Z_TREES: number; + + // Return codes for the compression/decompression functions. + // Negative values are errors, positive values are used for special but normal events. + const Z_OK: number; + const Z_STREAM_END: number; + const Z_NEED_DICT: number; + const Z_ERRNO: number; + const Z_STREAM_ERROR: number; + const Z_DATA_ERROR: number; + const Z_MEM_ERROR: number; + const Z_BUF_ERROR: number; + const Z_VERSION_ERROR: number; + + // Compression levels. + const Z_NO_COMPRESSION: number; + const Z_BEST_SPEED: number; + const Z_BEST_COMPRESSION: number; + const Z_DEFAULT_COMPRESSION: number; + + // Compression strategy. + const Z_FILTERED: number; + const Z_HUFFMAN_ONLY: number; + const Z_RLE: number; + const Z_FIXED: number; + const Z_DEFAULT_STRATEGY: number; + + const Z_DEFAULT_WINDOWBITS: number; + const Z_MIN_WINDOWBITS: number; + const Z_MAX_WINDOWBITS: number; + + const Z_MIN_CHUNK: number; + const Z_MAX_CHUNK: number; + const Z_DEFAULT_CHUNK: number; + + const Z_MIN_MEMLEVEL: number; + const Z_MAX_MEMLEVEL: number; + const Z_DEFAULT_MEMLEVEL: number; + + const Z_MIN_LEVEL: number; + const Z_MAX_LEVEL: number; + const Z_DEFAULT_LEVEL: number; + + const ZLIB_VERNUM: number; + } + + // Allowed flush values. + /** @deprecated Use `constants.Z_NO_FLUSH` */ + const Z_NO_FLUSH: number; + /** @deprecated Use `constants.Z_PARTIAL_FLUSH` */ + const Z_PARTIAL_FLUSH: number; + /** @deprecated Use `constants.Z_SYNC_FLUSH` */ + const Z_SYNC_FLUSH: number; + /** @deprecated Use `constants.Z_FULL_FLUSH` */ + const Z_FULL_FLUSH: number; + /** @deprecated Use `constants.Z_FINISH` */ + const Z_FINISH: number; + /** @deprecated Use `constants.Z_BLOCK` */ + const Z_BLOCK: number; + /** @deprecated Use `constants.Z_TREES` */ + const Z_TREES: number; + + // Return codes for the compression/decompression functions. + // Negative values are errors, positive values are used for special but normal events. + /** @deprecated Use `constants.Z_OK` */ + const Z_OK: number; + /** @deprecated Use `constants.Z_STREAM_END` */ + const Z_STREAM_END: number; + /** @deprecated Use `constants.Z_NEED_DICT` */ + const Z_NEED_DICT: number; + /** @deprecated Use `constants.Z_ERRNO` */ + const Z_ERRNO: number; + /** @deprecated Use `constants.Z_STREAM_ERROR` */ + const Z_STREAM_ERROR: number; + /** @deprecated Use `constants.Z_DATA_ERROR` */ + const Z_DATA_ERROR: number; + /** @deprecated Use `constants.Z_MEM_ERROR` */ + const Z_MEM_ERROR: number; + /** @deprecated Use `constants.Z_BUF_ERROR` */ + const Z_BUF_ERROR: number; + /** @deprecated Use `constants.Z_VERSION_ERROR` */ + const Z_VERSION_ERROR: number; + + // Compression levels. + /** @deprecated Use `constants.Z_NO_COMPRESSION` */ + const Z_NO_COMPRESSION: number; + /** @deprecated Use `constants.Z_BEST_SPEED` */ + const Z_BEST_SPEED: number; + /** @deprecated Use `constants.Z_BEST_COMPRESSION` */ + const Z_BEST_COMPRESSION: number; + /** @deprecated Use `constants.Z_DEFAULT_COMPRESSION` */ + const Z_DEFAULT_COMPRESSION: number; + + // Compression strategy. + /** @deprecated Use `constants.Z_FILTERED` */ + const Z_FILTERED: number; + /** @deprecated Use `constants.Z_HUFFMAN_ONLY` */ + const Z_HUFFMAN_ONLY: number; + /** @deprecated Use `constants.Z_RLE` */ + const Z_RLE: number; + /** @deprecated Use `constants.Z_FIXED` */ + const Z_FIXED: number; + /** @deprecated Use `constants.Z_DEFAULT_STRATEGY` */ + const Z_DEFAULT_STRATEGY: number; + + /** @deprecated */ + const Z_BINARY: number; + /** @deprecated */ + const Z_TEXT: number; + /** @deprecated */ + const Z_ASCII: number; + /** @deprecated */ + const Z_UNKNOWN: number; + /** @deprecated */ + const Z_DEFLATED: number; +} diff --git a/node_modules/@types/responselike/LICENSE b/node_modules/@types/responselike/LICENSE new file mode 100644 index 0000000..4b1ad51 --- /dev/null +++ b/node_modules/@types/responselike/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/responselike/README.md b/node_modules/@types/responselike/README.md new file mode 100644 index 0000000..4523ff9 --- /dev/null +++ b/node_modules/@types/responselike/README.md @@ -0,0 +1,16 @@ +# Installation +> `npm install --save @types/responselike` + +# Summary +This package contains type definitions for responselike ( https://github.com/lukechilds/responselike#readme ). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/responselike + +Additional Details + * Last updated: Wed, 30 Jan 2019 18:47:32 GMT + * Dependencies: @types/node + * Global values: none + +# Credits +These definitions were written by BendingBender . diff --git a/node_modules/@types/responselike/index.d.ts b/node_modules/@types/responselike/index.d.ts new file mode 100644 index 0000000..7152388 --- /dev/null +++ b/node_modules/@types/responselike/index.d.ts @@ -0,0 +1,34 @@ +// Type definitions for responselike 1.0 +// Project: https://github.com/lukechilds/responselike#readme +// Definitions by: BendingBender +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +import { IncomingMessage } from 'http'; +import { Stream } from 'stream'; + +export = ResponseLike; + +/** + * Returns a streamable response object similar to a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage). + */ +declare class ResponseLike extends Stream.Readable { + statusCode: number; + headers: { [header: string]: string | string[] | undefined }; + body: Buffer; + url: string; + + /** + * @param statusCode HTTP response status code. + * @param headers HTTP headers object. Keys will be automatically lowercased. + * @param body A Buffer containing the response body. The Buffer contents will be streamable but is also exposed directly as `response.body`. + * @param url Request URL string. + */ + constructor( + statusCode: number, + headers: { [header: string]: string | string[] | undefined }, + body: Buffer, + url: string + ); +} diff --git a/node_modules/@types/responselike/package.json b/node_modules/@types/responselike/package.json new file mode 100644 index 0000000..69b8caa --- /dev/null +++ b/node_modules/@types/responselike/package.json @@ -0,0 +1,25 @@ +{ + "name": "@types/responselike", + "version": "1.0.0", + "description": "TypeScript definitions for responselike", + "license": "MIT", + "contributors": [ + { + "name": "BendingBender", + "url": "https://github.com/BendingBender", + "githubUsername": "BendingBender" + } + ], + "main": "", + "types": "index", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git" + }, + "scripts": {}, + "dependencies": { + "@types/node": "*" + }, + "typesPublisherContentHash": "38ee8db1511cdb4a9133ff67b8bc16901de733aa4dc1efffdb5064b7daaa3f21", + "typeScriptVersion": "2.0" +} \ No newline at end of file diff --git a/node_modules/abort-controller/LICENSE b/node_modules/abort-controller/LICENSE new file mode 100644 index 0000000..c914149 --- /dev/null +++ b/node_modules/abort-controller/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Toru Nagashima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/abort-controller/README.md b/node_modules/abort-controller/README.md new file mode 100644 index 0000000..9de3e45 --- /dev/null +++ b/node_modules/abort-controller/README.md @@ -0,0 +1,98 @@ +# abort-controller + +[![npm version](https://img.shields.io/npm/v/abort-controller.svg)](https://www.npmjs.com/package/abort-controller) +[![Downloads/month](https://img.shields.io/npm/dm/abort-controller.svg)](http://www.npmtrends.com/abort-controller) +[![Build Status](https://travis-ci.org/mysticatea/abort-controller.svg?branch=master)](https://travis-ci.org/mysticatea/abort-controller) +[![Coverage Status](https://codecov.io/gh/mysticatea/abort-controller/branch/master/graph/badge.svg)](https://codecov.io/gh/mysticatea/abort-controller) +[![Dependency Status](https://david-dm.org/mysticatea/abort-controller.svg)](https://david-dm.org/mysticatea/abort-controller) + +An implementation of [WHATWG AbortController interface](https://dom.spec.whatwg.org/#interface-abortcontroller). + +```js +import AbortController from "abort-controller" + +const controller = new AbortController() +const signal = controller.signal + +signal.addEventListener("abort", () => { + console.log("aborted!") +}) + +controller.abort() +``` + +> https://jsfiddle.net/1r2994qp/1/ + +## 💿 Installation + +Use [npm](https://www.npmjs.com/) to install then use a bundler. + +``` +npm install abort-controller +``` + +Or download from [`dist` directory](./dist). + +- [dist/abort-controller.mjs](dist/abort-controller.mjs) ... ES modules version. +- [dist/abort-controller.js](dist/abort-controller.js) ... Common JS version. +- [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. + +## 📖 Usage + +### Basic + +```js +import AbortController from "abort-controller" +// or +const AbortController = require("abort-controller") + +// or UMD version defines a global variable: +const AbortController = window.AbortControllerShim +``` + +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). +If you wanted to polyfill `AbortController` for IE, use `abort-controller/polyfill`. + +### Polyfilling + +Importing `abort-controller/polyfill` assigns the `AbortController` shim to the `AbortController` global variable if the native implementation was nothing. + +```js +import "abort-controller/polyfill" +// or +require("abort-controller/polyfill") +``` + +### API + +#### AbortController + +> https://dom.spec.whatwg.org/#interface-abortcontroller + +##### controller.signal + +The [AbortSignal](https://dom.spec.whatwg.org/#interface-AbortSignal) object which is associated to this controller. + +##### controller.abort() + +Notify `abort` event to listeners that the `signal` has. + +## 📰 Changelog + +- See [GitHub releases](https://github.com/mysticatea/abort-controller/releases). + +## 🍻 Contributing + +Contributing is welcome ❤️ + +Please use GitHub issues/PRs. + +### Development tools + +- `npm install` installs dependencies for development. +- `npm test` runs tests and measures code coverage. +- `npm run clean` removes temporary files of tests. +- `npm run coverage` opens code coverage of the previous test with your default browser. +- `npm run lint` runs ESLint. +- `npm run build` generates `dist` codes. +- `npm run watch` runs tests on each file change. diff --git a/node_modules/abort-controller/browser.js b/node_modules/abort-controller/browser.js new file mode 100644 index 0000000..b0c5ec3 --- /dev/null +++ b/node_modules/abort-controller/browser.js @@ -0,0 +1,13 @@ +/*globals self, window */ +"use strict" + +/*eslint-disable @mysticatea/prettier */ +const { AbortController, AbortSignal } = + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + /* otherwise */ undefined +/*eslint-enable @mysticatea/prettier */ + +module.exports = AbortController +module.exports.AbortSignal = AbortSignal +module.exports.default = AbortController diff --git a/node_modules/abort-controller/browser.mjs b/node_modules/abort-controller/browser.mjs new file mode 100644 index 0000000..a8f321a --- /dev/null +++ b/node_modules/abort-controller/browser.mjs @@ -0,0 +1,11 @@ +/*globals self, window */ + +/*eslint-disable @mysticatea/prettier */ +const { AbortController, AbortSignal } = + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + /* otherwise */ undefined +/*eslint-enable @mysticatea/prettier */ + +export default AbortController +export { AbortController, AbortSignal } diff --git a/node_modules/abort-controller/dist/abort-controller.d.ts b/node_modules/abort-controller/dist/abort-controller.d.ts new file mode 100644 index 0000000..75852fb --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.d.ts @@ -0,0 +1,43 @@ +import { EventTarget } from "event-target-shim" + +type Events = { + abort: any +} +type EventAttributes = { + onabort: any +} +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +declare class AbortSignal extends EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() + /** + * Returns `true` if this `AbortSignal`"s `AbortController` has signaled to abort, and `false` otherwise. + */ + readonly aborted: boolean +} +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +declare class AbortController { + /** + * Initialize this controller. + */ + constructor() + /** + * Returns the `AbortSignal` object associated with this object. + */ + readonly signal: AbortSignal + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort(): void +} + +export default AbortController +export { AbortController, AbortSignal } diff --git a/node_modules/abort-controller/dist/abort-controller.js b/node_modules/abort-controller/dist/abort-controller.js new file mode 100644 index 0000000..49af739 --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.js @@ -0,0 +1,127 @@ +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var eventTargetShim = require('event-target-shim'); + +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +class AbortSignal extends eventTargetShim.EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() { + super(); + throw new TypeError("AbortSignal cannot be constructed directly"); + } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + get aborted() { + const aborted = abortedFlags.get(this); + if (typeof aborted !== "boolean") { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`); + } + return aborted; + } +} +eventTargetShim.defineEventAttribute(AbortSignal.prototype, "abort"); +/** + * Create an AbortSignal object. + */ +function createAbortSignal() { + const signal = Object.create(AbortSignal.prototype); + eventTargetShim.EventTarget.call(signal); + abortedFlags.set(signal, false); + return signal; +} +/** + * Abort a given signal. + */ +function abortSignal(signal) { + if (abortedFlags.get(signal) !== false) { + return; + } + abortedFlags.set(signal, true); + signal.dispatchEvent({ type: "abort" }); +} +/** + * Aborted flag for each instances. + */ +const abortedFlags = new WeakMap(); +// Properties should be enumerable. +Object.defineProperties(AbortSignal.prototype, { + aborted: { enumerable: true }, +}); +// `toString()` should return `"[object AbortSignal]"` +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortSignal", + }); +} + +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +class AbortController { + /** + * Initialize this controller. + */ + constructor() { + signals.set(this, createAbortSignal()); + } + /** + * Returns the `AbortSignal` object associated with this object. + */ + get signal() { + return getSignal(this); + } + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort() { + abortSignal(getSignal(this)); + } +} +/** + * Associated signals. + */ +const signals = new WeakMap(); +/** + * Get the associated signal of a given controller. + */ +function getSignal(controller) { + const signal = signals.get(controller); + if (signal == null) { + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`); + } + return signal; +} +// Properties should be enumerable. +Object.defineProperties(AbortController.prototype, { + signal: { enumerable: true }, + abort: { enumerable: true }, +}); +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortController", + }); +} + +exports.AbortController = AbortController; +exports.AbortSignal = AbortSignal; +exports.default = AbortController; + +module.exports = AbortController +module.exports.AbortController = module.exports["default"] = AbortController +module.exports.AbortSignal = AbortSignal +//# sourceMappingURL=abort-controller.js.map diff --git a/node_modules/abort-controller/dist/abort-controller.js.map b/node_modules/abort-controller/dist/abort-controller.js.map new file mode 100644 index 0000000..cfdcafd --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.js.map @@ -0,0 +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 {\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()\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()\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 diff --git a/node_modules/abort-controller/dist/abort-controller.mjs b/node_modules/abort-controller/dist/abort-controller.mjs new file mode 100644 index 0000000..88ba22d --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.mjs @@ -0,0 +1,118 @@ +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */ +import { EventTarget, defineEventAttribute } from 'event-target-shim'; + +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +class AbortSignal extends EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() { + super(); + throw new TypeError("AbortSignal cannot be constructed directly"); + } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + get aborted() { + const aborted = abortedFlags.get(this); + if (typeof aborted !== "boolean") { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`); + } + return aborted; + } +} +defineEventAttribute(AbortSignal.prototype, "abort"); +/** + * Create an AbortSignal object. + */ +function createAbortSignal() { + const signal = Object.create(AbortSignal.prototype); + EventTarget.call(signal); + abortedFlags.set(signal, false); + return signal; +} +/** + * Abort a given signal. + */ +function abortSignal(signal) { + if (abortedFlags.get(signal) !== false) { + return; + } + abortedFlags.set(signal, true); + signal.dispatchEvent({ type: "abort" }); +} +/** + * Aborted flag for each instances. + */ +const abortedFlags = new WeakMap(); +// Properties should be enumerable. +Object.defineProperties(AbortSignal.prototype, { + aborted: { enumerable: true }, +}); +// `toString()` should return `"[object AbortSignal]"` +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortSignal", + }); +} + +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +class AbortController { + /** + * Initialize this controller. + */ + constructor() { + signals.set(this, createAbortSignal()); + } + /** + * Returns the `AbortSignal` object associated with this object. + */ + get signal() { + return getSignal(this); + } + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort() { + abortSignal(getSignal(this)); + } +} +/** + * Associated signals. + */ +const signals = new WeakMap(); +/** + * Get the associated signal of a given controller. + */ +function getSignal(controller) { + const signal = signals.get(controller); + if (signal == null) { + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`); + } + return signal; +} +// Properties should be enumerable. +Object.defineProperties(AbortController.prototype, { + signal: { enumerable: true }, + abort: { enumerable: true }, +}); +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortController", + }); +} + +export default AbortController; +export { AbortController, AbortSignal }; +//# sourceMappingURL=abort-controller.mjs.map diff --git a/node_modules/abort-controller/dist/abort-controller.mjs.map b/node_modules/abort-controller/dist/abort-controller.mjs.map new file mode 100644 index 0000000..1e8fa6b --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.mjs.map @@ -0,0 +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 {\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()\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()\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 diff --git a/node_modules/abort-controller/dist/abort-controller.umd.js b/node_modules/abort-controller/dist/abort-controller.umd.js new file mode 100644 index 0000000..f643cfd --- /dev/null +++ b/node_modules/abort-controller/dist/abort-controller.umd.js @@ -0,0 +1,5 @@ +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */(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\n * @copyright 2015 Toru Nagashima. All rights reserved.\n * See LICENSE file in root directory for full license.\n */\n/**\n * @typedef {object} PrivateData\n * @property {EventTarget} eventTarget The event target.\n * @property {{type:string}} event The original event object.\n * @property {number} eventPhase The current event phase.\n * @property {EventTarget|null} currentTarget The current event target.\n * @property {boolean} canceled The flag to prevent default.\n * @property {boolean} stopped The flag to stop propagation.\n * @property {boolean} immediateStopped The flag to stop propagation immediately.\n * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.\n * @property {number} timeStamp The unix time.\n * @private\n */\n\n/**\n * Private data for event wrappers.\n * @type {WeakMap}\n * @private\n */\nconst privateData = new WeakMap();\n\n/**\n * Cache for wrapper classes.\n * @type {WeakMap}\n * @private\n */\nconst wrappers = new WeakMap();\n\n/**\n * Get private data.\n * @param {Event} event The event object to get private data.\n * @returns {PrivateData} The private data of the event.\n * @private\n */\nfunction pd(event) {\n const retv = privateData.get(event);\n console.assert(\n retv != null,\n \"'this' is expected an Event object, but got\",\n event\n );\n return retv\n}\n\n/**\n * https://dom.spec.whatwg.org/#set-the-canceled-flag\n * @param data {PrivateData} private data.\n */\nfunction setCancelFlag(data) {\n if (data.passiveListener != null) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(\n \"Unable to preventDefault inside passive event listener invocation.\",\n data.passiveListener\n );\n }\n return\n }\n if (!data.event.cancelable) {\n return\n }\n\n data.canceled = true;\n if (typeof data.event.preventDefault === \"function\") {\n data.event.preventDefault();\n }\n}\n\n/**\n * @see https://dom.spec.whatwg.org/#interface-event\n * @private\n */\n/**\n * The event wrapper.\n * @constructor\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Event|{type:string}} event The original event to wrap.\n */\nfunction Event(eventTarget, event) {\n privateData.set(this, {\n eventTarget,\n event,\n eventPhase: 2,\n currentTarget: eventTarget,\n canceled: false,\n stopped: false,\n immediateStopped: false,\n passiveListener: null,\n timeStamp: event.timeStamp || Date.now(),\n });\n\n // https://heycam.github.io/webidl/#Unforgeable\n Object.defineProperty(this, \"isTrusted\", { value: false, enumerable: true });\n\n // Define accessors\n const keys = Object.keys(event);\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i];\n if (!(key in this)) {\n Object.defineProperty(this, key, defineRedirectDescriptor(key));\n }\n }\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEvent.prototype = {\n /**\n * The type of this event.\n * @type {string}\n */\n get type() {\n return pd(this).event.type\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get target() {\n return pd(this).eventTarget\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get currentTarget() {\n return pd(this).currentTarget\n },\n\n /**\n * @returns {EventTarget[]} The composed path of this event.\n */\n composedPath() {\n const currentTarget = pd(this).currentTarget;\n if (currentTarget == null) {\n return []\n }\n return [currentTarget]\n },\n\n /**\n * Constant of NONE.\n * @type {number}\n */\n get NONE() {\n return 0\n },\n\n /**\n * Constant of CAPTURING_PHASE.\n * @type {number}\n */\n get CAPTURING_PHASE() {\n return 1\n },\n\n /**\n * Constant of AT_TARGET.\n * @type {number}\n */\n get AT_TARGET() {\n return 2\n },\n\n /**\n * Constant of BUBBLING_PHASE.\n * @type {number}\n */\n get BUBBLING_PHASE() {\n return 3\n },\n\n /**\n * The target of this event.\n * @type {number}\n */\n get eventPhase() {\n return pd(this).eventPhase\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopPropagation() {\n const data = pd(this);\n\n data.stopped = true;\n if (typeof data.event.stopPropagation === \"function\") {\n data.event.stopPropagation();\n }\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopImmediatePropagation() {\n const data = pd(this);\n\n data.stopped = true;\n data.immediateStopped = true;\n if (typeof data.event.stopImmediatePropagation === \"function\") {\n data.event.stopImmediatePropagation();\n }\n },\n\n /**\n * The flag to be bubbling.\n * @type {boolean}\n */\n get bubbles() {\n return Boolean(pd(this).event.bubbles)\n },\n\n /**\n * The flag to be cancelable.\n * @type {boolean}\n */\n get cancelable() {\n return Boolean(pd(this).event.cancelable)\n },\n\n /**\n * Cancel this event.\n * @returns {void}\n */\n preventDefault() {\n setCancelFlag(pd(this));\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n */\n get defaultPrevented() {\n return pd(this).canceled\n },\n\n /**\n * The flag to be composed.\n * @type {boolean}\n */\n get composed() {\n return Boolean(pd(this).event.composed)\n },\n\n /**\n * The unix time of this event.\n * @type {number}\n */\n get timeStamp() {\n return pd(this).timeStamp\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n * @deprecated\n */\n get srcElement() {\n return pd(this).eventTarget\n },\n\n /**\n * The flag to stop event bubbling.\n * @type {boolean}\n * @deprecated\n */\n get cancelBubble() {\n return pd(this).stopped\n },\n set cancelBubble(value) {\n if (!value) {\n return\n }\n const data = pd(this);\n\n data.stopped = true;\n if (typeof data.event.cancelBubble === \"boolean\") {\n data.event.cancelBubble = true;\n }\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n * @deprecated\n */\n get returnValue() {\n return !pd(this).canceled\n },\n set returnValue(value) {\n if (!value) {\n setCancelFlag(pd(this));\n }\n },\n\n /**\n * Initialize this event object. But do nothing under event dispatching.\n * @param {string} type The event type.\n * @param {boolean} [bubbles=false] The flag to be possible to bubble up.\n * @param {boolean} [cancelable=false] The flag to be possible to cancel.\n * @deprecated\n */\n initEvent() {\n // Do nothing.\n },\n};\n\n// `constructor` is not enumerable.\nObject.defineProperty(Event.prototype, \"constructor\", {\n value: Event,\n configurable: true,\n writable: true,\n});\n\n// Ensure `event instanceof window.Event` is `true`.\nif (typeof window !== \"undefined\" && typeof window.Event !== \"undefined\") {\n Object.setPrototypeOf(Event.prototype, window.Event.prototype);\n\n // Make association for wrappers.\n wrappers.set(window.Event.prototype, Event);\n}\n\n/**\n * Get the property descriptor to redirect a given property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to redirect the property.\n * @private\n */\nfunction defineRedirectDescriptor(key) {\n return {\n get() {\n return pd(this).event[key]\n },\n set(value) {\n pd(this).event[key] = value;\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Get the property descriptor to call a given method property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to call the method property.\n * @private\n */\nfunction defineCallDescriptor(key) {\n return {\n value() {\n const event = pd(this).event;\n return event[key].apply(event, arguments)\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define new wrapper class.\n * @param {Function} BaseEvent The base wrapper class.\n * @param {Object} proto The prototype of the original event.\n * @returns {Function} The defined wrapper class.\n * @private\n */\nfunction defineWrapper(BaseEvent, proto) {\n const keys = Object.keys(proto);\n if (keys.length === 0) {\n return BaseEvent\n }\n\n /** CustomEvent */\n function CustomEvent(eventTarget, event) {\n BaseEvent.call(this, eventTarget, event);\n }\n\n CustomEvent.prototype = Object.create(BaseEvent.prototype, {\n constructor: { value: CustomEvent, configurable: true, writable: true },\n });\n\n // Define accessors.\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i];\n if (!(key in BaseEvent.prototype)) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key);\n const isFunc = typeof descriptor.value === \"function\";\n Object.defineProperty(\n CustomEvent.prototype,\n key,\n isFunc\n ? defineCallDescriptor(key)\n : defineRedirectDescriptor(key)\n );\n }\n }\n\n return CustomEvent\n}\n\n/**\n * Get the wrapper class of a given prototype.\n * @param {Object} proto The prototype of the original event to get its wrapper.\n * @returns {Function} The wrapper class.\n * @private\n */\nfunction getWrapper(proto) {\n if (proto == null || proto === Object.prototype) {\n return Event\n }\n\n let wrapper = wrappers.get(proto);\n if (wrapper == null) {\n wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto);\n wrappers.set(proto, wrapper);\n }\n return wrapper\n}\n\n/**\n * Wrap a given event to management a dispatching.\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Object} event The event to wrap.\n * @returns {Event} The wrapper instance.\n * @private\n */\nfunction wrapEvent(eventTarget, event) {\n const Wrapper = getWrapper(Object.getPrototypeOf(event));\n return new Wrapper(eventTarget, event)\n}\n\n/**\n * Get the immediateStopped flag of a given event.\n * @param {Event} event The event to get.\n * @returns {boolean} The flag to stop propagation immediately.\n * @private\n */\nfunction isStopped(event) {\n return pd(event).immediateStopped\n}\n\n/**\n * Set the current event phase of a given event.\n * @param {Event} event The event to set current target.\n * @param {number} eventPhase New event phase.\n * @returns {void}\n * @private\n */\nfunction setEventPhase(event, eventPhase) {\n pd(event).eventPhase = eventPhase;\n}\n\n/**\n * Set the current target of a given event.\n * @param {Event} event The event to set current target.\n * @param {EventTarget|null} currentTarget New current target.\n * @returns {void}\n * @private\n */\nfunction setCurrentTarget(event, currentTarget) {\n pd(event).currentTarget = currentTarget;\n}\n\n/**\n * Set a passive listener of a given event.\n * @param {Event} event The event to set current target.\n * @param {Function|null} passiveListener New passive listener.\n * @returns {void}\n * @private\n */\nfunction setPassiveListener(event, passiveListener) {\n pd(event).passiveListener = passiveListener;\n}\n\n/**\n * @typedef {object} ListenerNode\n * @property {Function} listener\n * @property {1|2|3} listenerType\n * @property {boolean} passive\n * @property {boolean} once\n * @property {ListenerNode|null} next\n * @private\n */\n\n/**\n * @type {WeakMap>}\n * @private\n */\nconst listenersMap = new WeakMap();\n\n// Listener types\nconst CAPTURE = 1;\nconst BUBBLE = 2;\nconst ATTRIBUTE = 3;\n\n/**\n * Check whether a given value is an object or not.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is an object.\n */\nfunction isObject(x) {\n return x !== null && typeof x === \"object\" //eslint-disable-line no-restricted-syntax\n}\n\n/**\n * Get listeners.\n * @param {EventTarget} eventTarget The event target to get.\n * @returns {Map} The listeners.\n * @private\n */\nfunction getListeners(eventTarget) {\n const listeners = listenersMap.get(eventTarget);\n if (listeners == null) {\n throw new TypeError(\n \"'this' is expected an EventTarget object, but got another value.\"\n )\n }\n return listeners\n}\n\n/**\n * Get the property descriptor for the event attribute of a given event.\n * @param {string} eventName The event name to get property descriptor.\n * @returns {PropertyDescriptor} The property descriptor.\n * @private\n */\nfunction defineEventAttributeDescriptor(eventName) {\n return {\n get() {\n const listeners = getListeners(this);\n let node = listeners.get(eventName);\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n return node.listener\n }\n node = node.next;\n }\n return null\n },\n\n set(listener) {\n if (typeof listener !== \"function\" && !isObject(listener)) {\n listener = null; // eslint-disable-line no-param-reassign\n }\n const listeners = getListeners(this);\n\n // Traverse to the tail while removing old value.\n let prev = null;\n let node = listeners.get(eventName);\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n // Remove old value.\n if (prev !== null) {\n prev.next = node.next;\n } else if (node.next !== null) {\n listeners.set(eventName, node.next);\n } else {\n listeners.delete(eventName);\n }\n } else {\n prev = node;\n }\n\n node = node.next;\n }\n\n // Add new value.\n if (listener !== null) {\n const newNode = {\n listener,\n listenerType: ATTRIBUTE,\n passive: false,\n once: false,\n next: null,\n };\n if (prev === null) {\n listeners.set(eventName, newNode);\n } else {\n prev.next = newNode;\n }\n }\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define an event attribute (e.g. `eventTarget.onclick`).\n * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.\n * @param {string} eventName The event name to define.\n * @returns {void}\n */\nfunction defineEventAttribute(eventTargetPrototype, eventName) {\n Object.defineProperty(\n eventTargetPrototype,\n `on${eventName}`,\n defineEventAttributeDescriptor(eventName)\n );\n}\n\n/**\n * Define a custom EventTarget with event attributes.\n * @param {string[]} eventNames Event names for event attributes.\n * @returns {EventTarget} The custom EventTarget.\n * @private\n */\nfunction defineCustomEventTarget(eventNames) {\n /** CustomEventTarget */\n function CustomEventTarget() {\n EventTarget.call(this);\n }\n\n CustomEventTarget.prototype = Object.create(EventTarget.prototype, {\n constructor: {\n value: CustomEventTarget,\n configurable: true,\n writable: true,\n },\n });\n\n for (let i = 0; i < eventNames.length; ++i) {\n defineEventAttribute(CustomEventTarget.prototype, eventNames[i]);\n }\n\n return CustomEventTarget\n}\n\n/**\n * EventTarget.\n *\n * - This is constructor if no arguments.\n * - This is a function which returns a CustomEventTarget constructor if there are arguments.\n *\n * For example:\n *\n * class A extends EventTarget {}\n * class B extends EventTarget(\"message\") {}\n * class C extends EventTarget(\"message\", \"error\") {}\n * class D extends EventTarget([\"message\", \"error\"]) {}\n */\nfunction EventTarget() {\n /*eslint-disable consistent-return */\n if (this instanceof EventTarget) {\n listenersMap.set(this, new Map());\n return\n }\n if (arguments.length === 1 && Array.isArray(arguments[0])) {\n return defineCustomEventTarget(arguments[0])\n }\n if (arguments.length > 0) {\n const types = new Array(arguments.length);\n for (let i = 0; i < arguments.length; ++i) {\n types[i] = arguments[i];\n }\n return defineCustomEventTarget(types)\n }\n throw new TypeError(\"Cannot call a class as a function\")\n /*eslint-enable consistent-return */\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEventTarget.prototype = {\n /**\n * Add a given listener to this event target.\n * @param {string} eventName The event name to add.\n * @param {Function} listener The listener to add.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n addEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n if (typeof listener !== \"function\" && !isObject(listener)) {\n throw new TypeError(\"'listener' should be a function or an object.\")\n }\n\n const listeners = getListeners(this);\n const optionsIsObj = isObject(options);\n const capture = optionsIsObj\n ? Boolean(options.capture)\n : Boolean(options);\n const listenerType = capture ? CAPTURE : BUBBLE;\n const newNode = {\n listener,\n listenerType,\n passive: optionsIsObj && Boolean(options.passive),\n once: optionsIsObj && Boolean(options.once),\n next: null,\n };\n\n // Set it as the first node if the first node is null.\n let node = listeners.get(eventName);\n if (node === undefined) {\n listeners.set(eventName, newNode);\n return\n }\n\n // Traverse to the tail while checking duplication..\n let prev = null;\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n // Should ignore duplication.\n return\n }\n prev = node;\n node = node.next;\n }\n\n // Add it.\n prev.next = newNode;\n },\n\n /**\n * Remove a given listener from this event target.\n * @param {string} eventName The event name to remove.\n * @param {Function} listener The listener to remove.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n removeEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n\n const listeners = getListeners(this);\n const capture = isObject(options)\n ? Boolean(options.capture)\n : Boolean(options);\n const listenerType = capture ? CAPTURE : BUBBLE;\n\n let prev = null;\n let node = listeners.get(eventName);\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n if (prev !== null) {\n prev.next = node.next;\n } else if (node.next !== null) {\n listeners.set(eventName, node.next);\n } else {\n listeners.delete(eventName);\n }\n return\n }\n\n prev = node;\n node = node.next;\n }\n },\n\n /**\n * Dispatch a given event.\n * @param {Event|{type:string}} event The event to dispatch.\n * @returns {boolean} `false` if canceled.\n */\n dispatchEvent(event) {\n if (event == null || typeof event.type !== \"string\") {\n throw new TypeError('\"event.type\" should be a string.')\n }\n\n // If listeners aren't registered, terminate.\n const listeners = getListeners(this);\n const eventName = event.type;\n let node = listeners.get(eventName);\n if (node == null) {\n return true\n }\n\n // Since we cannot rewrite several properties, so wrap object.\n const wrappedEvent = wrapEvent(this, event);\n\n // This doesn't process capturing phase and bubbling phase.\n // This isn't participating in a tree.\n let prev = null;\n while (node != null) {\n // Remove this listener if it's once\n if (node.once) {\n if (prev !== null) {\n prev.next = node.next;\n } else if (node.next !== null) {\n listeners.set(eventName, node.next);\n } else {\n listeners.delete(eventName);\n }\n } else {\n prev = node;\n }\n\n // Call this listener\n setPassiveListener(\n wrappedEvent,\n node.passive ? node.listener : null\n );\n if (typeof node.listener === \"function\") {\n try {\n node.listener.call(this, wrappedEvent);\n } catch (err) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(err);\n }\n }\n } else if (\n node.listenerType !== ATTRIBUTE &&\n typeof node.listener.handleEvent === \"function\"\n ) {\n node.listener.handleEvent(wrappedEvent);\n }\n\n // Break if `event.stopImmediatePropagation` was called.\n if (isStopped(wrappedEvent)) {\n break\n }\n\n node = node.next;\n }\n setPassiveListener(wrappedEvent, null);\n setEventPhase(wrappedEvent, 0);\n setCurrentTarget(wrappedEvent, null);\n\n return !wrappedEvent.defaultPrevented\n },\n};\n\n// `constructor` is not enumerable.\nObject.defineProperty(EventTarget.prototype, \"constructor\", {\n value: EventTarget,\n configurable: true,\n writable: true,\n});\n\n// Ensure `eventTarget instanceof window.EventTarget` is `true`.\nif (\n typeof window !== \"undefined\" &&\n typeof window.EventTarget !== \"undefined\"\n) {\n Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype);\n}\n\nexport default EventTarget;\nexport { defineEventAttribute, EventTarget };\n//# sourceMappingURL=event-target-shim.mjs.map\n","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 {\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()\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()\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":["pd","event","retv","privateData","get","console","assert","setCancelFlag","data","passiveListener","cancelable","canceled","preventDefault","error","Event","eventTarget","set","eventPhase","currentTarget","stopped","immediateStopped","timeStamp","Date","now","Object","defineProperty","value","enumerable","key","keys","i","length","defineRedirectDescriptor","configurable","defineCallDescriptor","apply","arguments","defineWrapper","BaseEvent","proto","CustomEvent","call","prototype","create","constructor","writable","descriptor","getOwnPropertyDescriptor","isFunc","getWrapper","wrapper","wrappers","getPrototypeOf","wrapEvent","Wrapper","isStopped","setEventPhase","setCurrentTarget","setPassiveListener","createAbortSignal","signal","AbortSignal","EventTarget","abortedFlags","abortSignal","dispatchEvent","type","getSignal","controller","signals","TypeError","WeakMap","target","composedPath","NONE","CAPTURING_PHASE","AT_TARGET","BUBBLING_PHASE","stopPropagation","stopImmediatePropagation","bubbles","defaultPrevented","composed","srcElement","cancelBubble","returnValue","initEvent","window","setPrototypeOf","aborted","defineEventAttribute","defineProperties","Symbol","_typeof","toStringTag","AbortController","abort"],"mappings":";;;+3CAkCA,QAASA,CAAAA,CAAT,CAAYC,CAAZ,CAAmB,IACTC,CAAAA,CAAI,CAAGC,CAAW,CAACC,GAAZ,CAAgBH,CAAhB,QACbI,CAAAA,OAAO,CAACC,MAAR,CACY,IAAR,EAAAJ,CADJ,CAEI,6CAFJ,CAGID,CAHJ,EAKOC,EAOX,QAASK,CAAAA,CAAT,CAAuBC,CAAvB,CAA6B,OACG,KAAxB,EAAAA,CAAI,CAACC,eADgB,MAarB,CAACD,CAAI,CAACP,KAAL,CAAWS,UAbS,GAiBzBF,CAAI,CAACG,QAAL,GAjByB,CAkBgB,UAArC,QAAOH,CAAAA,CAAI,CAACP,KAAL,CAAWW,cAlBG,EAmBrBJ,CAAI,CAACP,KAAL,CAAWW,cAAX,EAnBqB,QAGE,WAAnB,QAAOP,CAAAA,OAAP,EACyB,UAAzB,QAAOA,CAAAA,OAAO,CAACQ,KAJE,EAMjBR,OAAO,CAACQ,KAAR,CACI,oEADJ,CAEIL,CAAI,CAACC,eAFT,CANiB,EAiC7B,QAASK,CAAAA,CAAT,CAAeC,CAAf,CAA4Bd,CAA5B,CAAmC,CAC/BE,CAAW,CAACa,GAAZ,CAAgB,IAAhB,CAAsB,CAClBD,WAAW,CAAXA,CADkB,CAElBd,KAAK,CAALA,CAFkB,CAGlBgB,UAAU,CAAE,CAHM,CAIlBC,aAAa,CAAEH,CAJG,CAKlBJ,QAAQ,GALU,CAMlBQ,OAAO,GANW,CAOlBC,gBAAgB,GAPE,CAQlBX,eAAe,CAAE,IARC,CASlBY,SAAS,CAAEpB,CAAK,CAACoB,SAAN,EAAmBC,IAAI,CAACC,GAAL,EATZ,CAAtB,CAD+B,CAc/BC,MAAM,CAACC,cAAP,CAAsB,IAAtB,CAA4B,WAA5B,CAAyC,CAAEC,KAAK,GAAP,CAAgBC,UAAU,GAA1B,CAAzC,CAd+B,QAmBrBC,CAAAA,EAFJC,CAAI,CAAGL,MAAM,CAACK,IAAP,CAAY5B,CAAZ,EACJ6B,CAAC,CAAG,EAAGA,CAAC,CAAGD,CAAI,CAACE,OAAQ,EAAED,EACzBF,EAAMC,CAAI,CAACC,CAAD,EACVF,CAAG,GAAI,OACTJ,MAAM,CAACC,cAAP,CAAsB,IAAtB,CAA4BG,CAA5B,CAAiCI,CAAwB,CAACJ,CAAD,CAAzD,EAyOZ,QAASI,CAAAA,CAAT,CAAkCJ,CAAlC,CAAuC,OAC5B,CACHxB,GADG,WACG,OACKJ,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAe2B,CAAf,CAFR,CAAA,CAIHZ,GAJG,UAICU,EAAO,CACP1B,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAe2B,CAAf,EAAsBF,CALvB,CAAA,CAOHO,YAAY,GAPT,CAQHN,UAAU,GARP,EAkBX,QAASO,CAAAA,CAAT,CAA8BN,CAA9B,CAAmC,OACxB,CACHF,KADG,WACK,IACEzB,CAAAA,CAAK,CAAGD,CAAE,CAAC,IAAD,CAAF,CAASC,YAChBA,CAAAA,CAAK,CAAC2B,CAAD,CAAL,CAAWO,KAAX,CAAiBlC,CAAjB,CAAwBmC,SAAxB,CAHR,CAAA,CAKHH,YAAY,GALT,CAMHN,UAAU,GANP,EAiBX,QAASU,CAAAA,CAAT,CAAuBC,CAAvB,CAAkCC,CAAlC,CAAyC,SAO5BC,CAAAA,EAAYzB,EAAad,EAAO,CACrCqC,CAAS,CAACG,IAAV,CAAe,IAAf,CAAqB1B,CAArB,CAAkCd,CAAlC,KAPE4B,CAAAA,CAAI,CAAGL,MAAM,CAACK,IAAP,CAAYU,CAAZ,KACO,CAAhB,GAAAV,CAAI,CAACE,aACEO,CAAAA,EAQXE,CAAW,CAACE,SAAZ,CAAwBlB,MAAM,CAACmB,MAAP,CAAcL,CAAS,CAACI,SAAxB,CAAmC,CACvDE,WAAW,CAAE,CAAElB,KAAK,CAAEc,CAAT,CAAsBP,YAAY,GAAlC,CAA0CY,QAAQ,GAAlD,CAD0C,CAAnC,CAXa,KAgBhC,GACKjB,CAAAA,CADL,CAAIE,CAAC,CAAG,EAAGA,CAAC,CAAGD,CAAI,CAACE,OAAQ,EAAED,KACzBF,EAAMC,CAAI,CAACC,CAAD,EACZ,EAAEF,CAAG,GAAIU,CAAAA,CAAS,CAACI,SAAnB,EAA+B,IACzBI,CAAAA,CAAU,CAAGtB,MAAM,CAACuB,wBAAP,CAAgCR,CAAhC,CAAuCX,CAAvC,CADY,CAEzBoB,CAAM,CAA+B,UAA5B,QAAOF,CAAAA,CAAU,CAACpB,KAFF,CAG/BF,MAAM,CAACC,cAAP,CACIe,CAAW,CAACE,SADhB,CAEId,CAFJ,CAGIoB,CAAM,CACAd,CAAoB,CAACN,CAAD,CADpB,CAEAI,CAAwB,CAACJ,CAAD,CALlC,QAUDY,CAAAA,EASX,QAASS,CAAAA,CAAT,CAAoBV,CAApB,CAA2B,IACV,IAAT,EAAAA,CAAK,EAAYA,CAAK,GAAKf,MAAM,CAACkB,gBAC3B5B,CAAAA,KAGPoC,CAAAA,CAAO,CAAGC,CAAQ,CAAC/C,GAAT,CAAamC,CAAb,QACC,KAAX,EAAAW,IACAA,CAAO,CAAGb,CAAa,CAACY,CAAU,CAACzB,MAAM,CAAC4B,cAAP,CAAsBb,CAAtB,CAAD,CAAX,CAA2CA,CAA3C,EACvBY,CAAQ,CAACnC,GAAT,CAAauB,CAAb,CAAoBW,CAApB,GAEGA,EAUJ,QAASG,CAAAA,CAAT,CAAmBtC,CAAnB,CAAgCd,CAAhC,CAAuC,IACpCqD,CAAAA,CAAO,CAAGL,CAAU,CAACzB,MAAM,CAAC4B,cAAP,CAAsBnD,CAAtB,CAAD,QACnB,IAAIqD,CAAAA,CAAJ,CAAYvC,CAAZ,CAAyBd,CAAzB,EASJ,QAASsD,CAAAA,CAAT,CAAmBtD,CAAnB,CAA0B,OACtBD,CAAAA,CAAE,CAACC,CAAD,CAAF,CAAUmB,iBAUd,QAASoC,CAAAA,CAAT,CAAuBvD,CAAvB,CAA8BgB,CAA9B,CAA0C,CAC7CjB,CAAE,CAACC,CAAD,CAAF,CAAUgB,UAAV,CAAuBA,EAUpB,QAASwC,CAAAA,CAAT,CAA0BxD,CAA1B,CAAiCiB,CAAjC,CAAgD,CACnDlB,CAAE,CAACC,CAAD,CAAF,CAAUiB,aAAV,CAA0BA,EAUvB,QAASwC,CAAAA,CAAT,CAA4BzD,CAA5B,CAAmCQ,CAAnC,CAAoD,CACvDT,CAAE,CAACC,CAAD,CAAF,CAAUQ,eAAV,CAA4BA,ysCC1ahBkD,CAAAA,OACNC,CAAAA,CAAM,CAAGpC,MAAM,CAACmB,MAAPnB,CAAcqC,CAAW,CAACnB,SAA1BlB,QACfsC,CAAAA,CAAW,CAACrB,IAAZqB,CAAiBF,CAAjBE,EACAC,CAAY,CAAC/C,GAAb+C,CAAiBH,CAAjBG,KACOH,UAMKI,CAAAA,EAAYJ,GACpBG,KAAAA,CAAY,CAAC3D,GAAb2D,CAAiBH,CAAjBG,IAIJA,CAAY,CAAC/C,GAAb+C,CAAiBH,CAAjBG,KACAH,CAAM,CAACK,aAAPL,CAA8B,CAAEM,IAAI,CAAE,OAAR,CAA9BN,GC9BJ,QAASO,CAAAA,CAAT,CAAmBC,CAAnB,KACUR,CAAAA,CAAM,CAAGS,CAAO,CAACjE,GAARiE,CAAYD,CAAZC,KACD,IAAVT,EAAAA,OACM,IAAIU,CAAAA,SAAJ,sEAEiB,IAAfF,GAAAA,CAAU,CAAY,MAAZ,GAA4BA,GAFxC,QAMHR,CAAAA,KF3BLzD,CAAAA,CAAW,CAAG,GAAIoE,CAAAA,QAOlBpB,CAAQ,CAAG,GAAIoB,CAAAA,QAkFrBzD,CAAK,CAAC4B,SAAN,CAAkB,IAKVwB,CAAAA,MAAO,OACAlE,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAeiE,IANZ,CAAA,IAaVM,CAAAA,QAAS,OACFxE,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASe,WAdN,CAAA,IAqBVG,CAAAA,eAAgB,OACTlB,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASkB,aAtBN,CAAA,CA4BduD,YA5Bc,WA4BC,IACLvD,CAAAA,CAAa,CAAGlB,CAAE,CAAC,IAAD,CAAF,CAASkB,cADpB,MAEU,KAAjB,EAAAA,CAFO,CAGA,EAHA,CAKJ,CAACA,CAAD,CAjCG,CAAA,IAwCVwD,CAAAA,MAAO,OACA,EAzCG,CAAA,IAgDVC,CAAAA,iBAAkB,OACX,EAjDG,CAAA,IAwDVC,CAAAA,WAAY,OACL,EAzDG,CAAA,IAgEVC,CAAAA,gBAAiB,OACV,EAjEG,CAAA,IAwEV5D,CAAAA,YAAa,OACNjB,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASiB,UAzEN,CAAA,CAgFd6D,eAhFc,WAgFI,IACRtE,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAAL,GAHc,CAI4B,UAAtC,QAAOX,CAAAA,CAAI,CAACP,KAAL,CAAW6E,eAJR,EAKVtE,CAAI,CAACP,KAAL,CAAW6E,eAAX,EArFM,CAAA,CA6FdC,wBA7Fc,WA6Fa,IACjBvE,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAAL,GAHuB,CAIvBX,CAAI,CAACY,gBAAL,GAJuB,CAK4B,UAA/C,QAAOZ,CAAAA,CAAI,CAACP,KAAL,CAAW8E,wBALC,EAMnBvE,CAAI,CAACP,KAAL,CAAW8E,wBAAX,EAnGM,CAAA,IA2GVC,CAAAA,SAAU,SACKhF,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAe+E,OA5GpB,CAAA,IAmHVtE,CAAAA,YAAa,SACEV,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAeS,UApHpB,CAAA,CA2HdE,cA3Hc,WA2HG,CACbL,CAAa,CAACP,CAAE,CAAC,IAAD,CAAH,CA5HH,CAAA,IAmIViF,CAAAA,kBAAmB,OACZjF,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASW,QApIN,CAAA,IA2IVuE,CAAAA,UAAW,SACIlF,CAAE,CAAC,IAAD,CAAF,CAASC,KAAT,CAAeiF,QA5IpB,CAAA,IAmJV7D,CAAAA,WAAY,OACLrB,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASqB,SApJN,CAAA,IA4JV8D,CAAAA,YAAa,OACNnF,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASe,WA7JN,CAAA,IAqKVqE,CAAAA,cAAe,OACRpF,CAAAA,CAAE,CAAC,IAAD,CAAF,CAASmB,OAtKN,CAAA,IAwKViE,CAAAA,aAAa1D,EAAO,IACfA,MAGClB,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAAL,IACuC,SAAnC,QAAOX,CAAAA,CAAI,CAACP,KAAL,CAAWmF,eAClB5E,CAAI,CAACP,KAAL,CAAWmF,YAAX,KAhLM,CAAA,IAyLVC,CAAAA,aAAc,OACP,CAACrF,CAAE,CAAC,IAAD,CAAF,CAASW,QA1LP,CAAA,IA4LV0E,CAAAA,YAAY3D,EAAO,CACdA,CADc,EAEfnB,CAAa,CAACP,CAAE,CAAC,IAAD,CAAH,CA9LP,CAAA,CAyMdsF,SAzMc,WAyMF,EAzME,EA+MlB9D,MAAM,CAACC,cAAP,CAAsBX,CAAK,CAAC4B,SAA5B,CAAuC,aAAvC,CAAsD,CAClDhB,KAAK,CAAEZ,CAD2C,CAElDmB,YAAY,GAFsC,CAGlDY,QAAQ,GAH0C,CAAtD,EAOsB,WAAlB,QAAO0C,CAAAA,MAAP,EAAyD,WAAxB,QAAOA,CAAAA,MAAM,CAACzE,QAC/CU,MAAM,CAACgE,cAAP,CAAsB1E,CAAK,CAAC4B,SAA5B,CAAuC6C,MAAM,CAACzE,KAAP,CAAa4B,SAApD,EAGAS,CAAQ,CAACnC,GAAT,CAAauE,MAAM,CAACzE,KAAP,CAAa4B,SAA1B,CAAqC5B,CAArC,wiDChTiB+C,CAAAA,2EAMP,GAAIS,CAAAA,SAAJ,CAAc,4CAAd,sDAOAmB,CAAAA,CAAO,CAAG1B,CAAY,CAAC3D,GAAb2D,CAAiB,IAAjBA,KACO,SAAnB,QAAO0B,CAAAA,OACD,IAAInB,CAAAA,SAAJ,kEAEW,IAAT,QAAgB,MAAhB,GAAgC,MAFlC,QAMHmB,CAAAA,SArB0B3B,GAwBzC4B,CAAoB,CAAC7B,CAAW,CAACnB,SAAb,CAAwB,OAAxB,EA2BpB,GAAMqB,CAAAA,CAAY,CAAG,GAAIQ,CAAAA,OAAzB,CAGA/C,MAAM,CAACmE,gBAAPnE,CAAwBqC,CAAW,CAACnB,SAApClB,CAA+C,CAC3CiE,OAAO,CAAE,CAAE9D,UAAU,GAAZ,CADkC,CAA/CH,EAKsB,UAAlB,QAAOoE,CAAAA,MAAP,EAA8D,QAA9B,GAAAC,EAAOD,MAAM,CAACE,cAC9CtE,MAAM,CAACC,cAAPD,CAAsBqC,CAAW,CAACnB,SAAlClB,CAA6CoE,MAAM,CAACE,WAApDtE,CAAiE,CAC7DS,YAAY,GADiD,CAE7DP,KAAK,CAAE,aAFsD,CAAjEF,KC5EiBuE,CAAAA,oCAKb1B,CAAO,CAACrD,GAARqD,CAAY,IAAZA,CAAkBV,CAAiB,EAAnCU,4CAcAL,CAAW,CAACG,CAAS,CAAC,IAAD,CAAV,uCAPJA,CAAAA,CAAS,CAAC,IAAD,WAclBE,CAAO,CAAG,GAAIE,CAAAA,WAkBpB/C,MAAM,CAACmE,gBAAPnE,CAAwBuE,CAAe,CAACrD,SAAxClB,CAAmD,CAC/CoC,MAAM,CAAE,CAAEjC,UAAU,GAAZ,CADuC,CAE/CqE,KAAK,CAAE,CAAErE,UAAU,GAAZ,CAFwC,CAAnDH,EAKsB,UAAlB,QAAOoE,CAAAA,MAAP,EAA8D,QAA9B,GAAAC,EAAOD,MAAM,CAACE,cAC9CtE,MAAM,CAACC,cAAPD,CAAsBuE,CAAe,CAACrD,SAAtClB,CAAiDoE,MAAM,CAACE,WAAxDtE,CAAqE,CACjES,YAAY,GADqD,CAEjEP,KAAK,CAAE,iBAF0D,CAArEF"} \ No newline at end of file diff --git a/node_modules/abort-controller/package.json b/node_modules/abort-controller/package.json new file mode 100644 index 0000000..fc705e0 --- /dev/null +++ b/node_modules/abort-controller/package.json @@ -0,0 +1,97 @@ +{ + "name": "abort-controller", + "version": "3.0.0", + "description": "An implementation of WHATWG AbortController interface.", + "main": "dist/abort-controller", + "files": [ + "dist", + "polyfill.*", + "browser.*" + ], + "engines": { + "node": ">=6.5" + }, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "browser": "./browser.js", + "devDependencies": { + "@babel/core": "^7.2.2", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/preset-env": "^7.3.0", + "@babel/register": "^7.0.0", + "@mysticatea/eslint-plugin": "^8.0.1", + "@mysticatea/spy": "^0.1.2", + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.18", + "assert": "^1.4.1", + "codecov": "^3.1.0", + "dts-bundle-generator": "^2.0.0", + "eslint": "^5.12.1", + "karma": "^3.1.4", + "karma-chrome-launcher": "^2.2.0", + "karma-coverage": "^1.1.2", + "karma-firefox-launcher": "^1.1.0", + "karma-growl-reporter": "^1.0.0", + "karma-ie-launcher": "^1.0.0", + "karma-mocha": "^1.3.0", + "karma-rollup-preprocessor": "^7.0.0-rc.2", + "mocha": "^5.2.0", + "npm-run-all": "^4.1.5", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "rimraf": "^2.6.3", + "rollup": "^1.1.2", + "rollup-plugin-babel": "^4.3.2", + "rollup-plugin-babel-minify": "^7.0.0", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-node-resolve": "^4.0.0", + "rollup-plugin-sourcemaps": "^0.4.2", + "rollup-plugin-typescript": "^1.0.0", + "rollup-watch": "^4.3.1", + "ts-node": "^8.0.1", + "type-tester": "^1.0.0", + "typescript": "^3.2.4" + }, + "scripts": { + "preversion": "npm test", + "version": "npm run -s build && git add dist/*", + "postversion": "git push && git push --tags", + "clean": "rimraf .nyc_output coverage", + "coverage": "opener coverage/lcov-report/index.html", + "lint": "eslint . --ext .ts", + "build": "run-s -s build:*", + "build:rollup": "rollup -c", + "build:dts": "dts-bundle-generator -o dist/abort-controller.d.ts src/abort-controller.ts && ts-node scripts/fix-dts", + "test": "run-s -s lint test:*", + "test:mocha": "nyc mocha test/*.ts", + "test:karma": "karma start --single-run", + "watch": "run-p -s watch:*", + "watch:mocha": "mocha test/*.ts --require ts-node/register --watch-extensions ts --watch --growl", + "watch:karma": "karma start --watch", + "codecov": "codecov" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mysticatea/abort-controller.git" + }, + "keywords": [ + "w3c", + "whatwg", + "event", + "events", + "abort", + "cancel", + "abortcontroller", + "abortsignal", + "controller", + "signal", + "shim" + ], + "author": "Toru Nagashima (https://github.com/mysticatea)", + "license": "MIT", + "bugs": { + "url": "https://github.com/mysticatea/abort-controller/issues" + }, + "homepage": "https://github.com/mysticatea/abort-controller#readme" +} diff --git a/node_modules/abort-controller/polyfill.js b/node_modules/abort-controller/polyfill.js new file mode 100644 index 0000000..3ca8923 --- /dev/null +++ b/node_modules/abort-controller/polyfill.js @@ -0,0 +1,21 @@ +/*globals require, self, window */ +"use strict" + +const ac = require("./dist/abort-controller") + +/*eslint-disable @mysticatea/prettier */ +const g = + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + /* otherwise */ undefined +/*eslint-enable @mysticatea/prettier */ + +if (g) { + if (typeof g.AbortController === "undefined") { + g.AbortController = ac.AbortController + } + if (typeof g.AbortSignal === "undefined") { + g.AbortSignal = ac.AbortSignal + } +} diff --git a/node_modules/abort-controller/polyfill.mjs b/node_modules/abort-controller/polyfill.mjs new file mode 100644 index 0000000..0602a64 --- /dev/null +++ b/node_modules/abort-controller/polyfill.mjs @@ -0,0 +1,19 @@ +/*globals self, window */ +import * as ac from "./dist/abort-controller" + +/*eslint-disable @mysticatea/prettier */ +const g = + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + /* otherwise */ undefined +/*eslint-enable @mysticatea/prettier */ + +if (g) { + if (typeof g.AbortController === "undefined") { + g.AbortController = ac.AbortController + } + if (typeof g.AbortSignal === "undefined") { + g.AbortSignal = ac.AbortSignal + } +} diff --git a/node_modules/asynckit/LICENSE b/node_modules/asynckit/LICENSE new file mode 100644 index 0000000..c9eca5d --- /dev/null +++ b/node_modules/asynckit/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Alex Indigo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/asynckit/README.md b/node_modules/asynckit/README.md new file mode 100644 index 0000000..ddcc7e6 --- /dev/null +++ b/node_modules/asynckit/README.md @@ -0,0 +1,233 @@ +# asynckit [![NPM Module](https://img.shields.io/npm/v/asynckit.svg?style=flat)](https://www.npmjs.com/package/asynckit) + +Minimal async jobs utility library, with streams support. + +[![PhantomJS Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=browser&style=flat)](https://travis-ci.org/alexindigo/asynckit) +[![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) +[![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) + +[![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) +[![Dependency Status](https://img.shields.io/david/alexindigo/asynckit/v0.4.0.svg?style=flat)](https://david-dm.org/alexindigo/asynckit) +[![bitHound Overall Score](https://www.bithound.io/github/alexindigo/asynckit/badges/score.svg)](https://www.bithound.io/github/alexindigo/asynckit) + + + +AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects. +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. + +It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators. + +| compression | size | +| :----------------- | -------: | +| asynckit.js | 12.34 kB | +| asynckit.min.js | 4.11 kB | +| asynckit.min.js.gz | 1.47 kB | + + +## Install + +```sh +$ npm install --save asynckit +``` + +## Examples + +### Parallel Jobs + +Runs iterator over provided array in parallel. Stores output in the `result` array, +on the matching positions. In unlikely event of an error from one of the jobs, +will terminate rest of the active jobs (if abort function is provided) +and return error along with salvaged data to the main callback function. + +#### Input Array + +```javascript +var parallel = require('asynckit').parallel + , assert = require('assert') + ; + +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] + , target = [] + ; + +parallel(source, asyncJob, function(err, result) +{ + assert.deepEqual(result, expectedResult); + assert.deepEqual(target, expectedTarget); +}); + +// async job accepts one element from the array +// and a callback function +function asyncJob(item, cb) +{ + // different delays (in ms) per item + var delay = item * 25; + + // pretend different jobs take different time to finish + // and not in consequential order + var timeoutId = setTimeout(function() { + target.push(item); + cb(null, item * 2); + }, delay); + + // allow to cancel "leftover" jobs upon error + // return function, invoking of which will abort this job + return clearTimeout.bind(null, timeoutId); +} +``` + +More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js). + +#### Input Object + +Also it supports named jobs, listed via object. + +```javascript +var parallel = require('asynckit/parallel') + , assert = require('assert') + ; + +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] + , expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ] + , target = [] + , keys = [] + ; + +parallel(source, asyncJob, function(err, result) +{ + assert.deepEqual(result, expectedResult); + assert.deepEqual(target, expectedTarget); + assert.deepEqual(keys, expectedKeys); +}); + +// supports full value, key, callback (shortcut) interface +function asyncJob(item, key, cb) +{ + // different delays (in ms) per item + var delay = item * 25; + + // pretend different jobs take different time to finish + // and not in consequential order + var timeoutId = setTimeout(function() { + keys.push(key); + target.push(item); + cb(null, item * 2); + }, delay); + + // allow to cancel "leftover" jobs upon error + // return function, invoking of which will abort this job + return clearTimeout.bind(null, timeoutId); +} +``` + +More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js). + +### Serial Jobs + +Runs iterator over provided array sequentially. Stores output in the `result` array, +on the matching positions. In unlikely event of an error from one of the jobs, +will not proceed to the rest of the items in the list +and return error along with salvaged data to the main callback function. + +#### Input Array + +```javascript +var serial = require('asynckit/serial') + , assert = require('assert') + ; + +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] + , target = [] + ; + +serial(source, asyncJob, function(err, result) +{ + assert.deepEqual(result, expectedResult); + assert.deepEqual(target, expectedTarget); +}); + +// extended interface (item, key, callback) +// also supported for arrays +function asyncJob(item, key, cb) +{ + target.push(key); + + // it will be automatically made async + // even it iterator "returns" in the same event loop + cb(null, item * 2); +} +``` + +More examples could be found in [test/test-serial-array.js](test/test-serial-array.js). + +#### Input Object + +Also it supports named jobs, listed via object. + +```javascript +var serial = require('asynckit').serial + , assert = require('assert') + ; + +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] + , target = [] + ; + +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } + , expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ] + , target = [] + ; + + +serial(source, asyncJob, function(err, result) +{ + assert.deepEqual(result, expectedResult); + assert.deepEqual(target, expectedTarget); +}); + +// shortcut interface (item, callback) +// works for object as well as for the arrays +function asyncJob(item, cb) +{ + target.push(item); + + // it will be automatically made async + // even it iterator "returns" in the same event loop + cb(null, item * 2); +} +``` + +More examples could be found in [test/test-serial-object.js](test/test-serial-object.js). + +_Note: Since _object_ is an _unordered_ collection of properties, +it may produce unexpected results with sequential iterations. +Whenever order of the jobs' execution is important please use `serialOrdered` method._ + +### Ordered Serial Iterations + +TBD + +For example [compare-property](compare-property) package. + +### Streaming interface + +TBD + +## Want to Know More? + +More examples can be found in [test folder](test/). + +Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions. + +## License + +AsyncKit is licensed under the MIT license. diff --git a/node_modules/asynckit/bench.js b/node_modules/asynckit/bench.js new file mode 100644 index 0000000..c612f1a --- /dev/null +++ b/node_modules/asynckit/bench.js @@ -0,0 +1,76 @@ +/* eslint no-console: "off" */ + +var asynckit = require('./') + , async = require('async') + , assert = require('assert') + , expected = 0 + ; + +var Benchmark = require('benchmark'); +var suite = new Benchmark.Suite; + +var source = []; +for (var z = 1; z < 100; z++) +{ + source.push(z); + expected += z; +} + +suite +// add tests + +.add('async.map', function(deferred) +{ + var total = 0; + + async.map(source, + function(i, cb) + { + setImmediate(function() + { + total += i; + cb(null, total); + }); + }, + function(err, result) + { + assert.ifError(err); + assert.equal(result[result.length - 1], expected); + deferred.resolve(); + }); +}, {'defer': true}) + + +.add('asynckit.parallel', function(deferred) +{ + var total = 0; + + asynckit.parallel(source, + function(i, cb) + { + setImmediate(function() + { + total += i; + cb(null, total); + }); + }, + function(err, result) + { + assert.ifError(err); + assert.equal(result[result.length - 1], expected); + deferred.resolve(); + }); +}, {'defer': true}) + + +// add listeners +.on('cycle', function(ev) +{ + console.log(String(ev.target)); +}) +.on('complete', function() +{ + console.log('Fastest is ' + this.filter('fastest').map('name')); +}) +// run async +.run({ 'async': true }); diff --git a/node_modules/asynckit/index.js b/node_modules/asynckit/index.js new file mode 100644 index 0000000..455f945 --- /dev/null +++ b/node_modules/asynckit/index.js @@ -0,0 +1,6 @@ +module.exports = +{ + parallel : require('./parallel.js'), + serial : require('./serial.js'), + serialOrdered : require('./serialOrdered.js') +}; diff --git a/node_modules/asynckit/lib/abort.js b/node_modules/asynckit/lib/abort.js new file mode 100644 index 0000000..114367e --- /dev/null +++ b/node_modules/asynckit/lib/abort.js @@ -0,0 +1,29 @@ +// API +module.exports = abort; + +/** + * Aborts leftover active jobs + * + * @param {object} state - current state object + */ +function abort(state) +{ + Object.keys(state.jobs).forEach(clean.bind(state)); + + // reset leftover jobs + state.jobs = {}; +} + +/** + * Cleans up leftover job by invoking abort function for the provided job id + * + * @this state + * @param {string|number} key - job id to abort + */ +function clean(key) +{ + if (typeof this.jobs[key] == 'function') + { + this.jobs[key](); + } +} diff --git a/node_modules/asynckit/lib/async.js b/node_modules/asynckit/lib/async.js new file mode 100644 index 0000000..7f1288a --- /dev/null +++ b/node_modules/asynckit/lib/async.js @@ -0,0 +1,34 @@ +var defer = require('./defer.js'); + +// API +module.exports = async; + +/** + * Runs provided callback asynchronously + * even if callback itself is not + * + * @param {function} callback - callback to invoke + * @returns {function} - augmented callback + */ +function async(callback) +{ + var isAsync = false; + + // check if async happened + defer(function() { isAsync = true; }); + + return function async_callback(err, result) + { + if (isAsync) + { + callback(err, result); + } + else + { + defer(function nextTick_callback() + { + callback(err, result); + }); + } + }; +} diff --git a/node_modules/asynckit/lib/defer.js b/node_modules/asynckit/lib/defer.js new file mode 100644 index 0000000..b67110c --- /dev/null +++ b/node_modules/asynckit/lib/defer.js @@ -0,0 +1,26 @@ +module.exports = defer; + +/** + * Runs provided function on next iteration of the event loop + * + * @param {function} fn - function to run + */ +function defer(fn) +{ + var nextTick = typeof setImmediate == 'function' + ? setImmediate + : ( + typeof process == 'object' && typeof process.nextTick == 'function' + ? process.nextTick + : null + ); + + if (nextTick) + { + nextTick(fn); + } + else + { + setTimeout(fn, 0); + } +} diff --git a/node_modules/asynckit/lib/iterate.js b/node_modules/asynckit/lib/iterate.js new file mode 100644 index 0000000..5d2839a --- /dev/null +++ b/node_modules/asynckit/lib/iterate.js @@ -0,0 +1,75 @@ +var async = require('./async.js') + , abort = require('./abort.js') + ; + +// API +module.exports = iterate; + +/** + * Iterates over each job object + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {object} state - current job status + * @param {function} callback - invoked when all elements processed + */ +function iterate(list, iterator, state, callback) +{ + // store current index + var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; + + state.jobs[key] = runJob(iterator, key, list[key], function(error, output) + { + // don't repeat yourself + // skip secondary callbacks + if (!(key in state.jobs)) + { + return; + } + + // clean up jobs + delete state.jobs[key]; + + if (error) + { + // don't process rest of the results + // stop still active jobs + // and reset the list + abort(state); + } + else + { + state.results[key] = output; + } + + // return salvaged results + callback(error, state.results); + }); +} + +/** + * Runs iterator over provided job element + * + * @param {function} iterator - iterator to invoke + * @param {string|number} key - key/index of the element in the list of jobs + * @param {mixed} item - job description + * @param {function} callback - invoked after iterator is done with the job + * @returns {function|mixed} - job abort function or something else + */ +function runJob(iterator, key, item, callback) +{ + var aborter; + + // allow shortcut if iterator expects only two arguments + if (iterator.length == 2) + { + aborter = iterator(item, async(callback)); + } + // otherwise go with full three arguments + else + { + aborter = iterator(item, key, async(callback)); + } + + return aborter; +} diff --git a/node_modules/asynckit/lib/readable_asynckit.js b/node_modules/asynckit/lib/readable_asynckit.js new file mode 100644 index 0000000..78ad240 --- /dev/null +++ b/node_modules/asynckit/lib/readable_asynckit.js @@ -0,0 +1,91 @@ +var streamify = require('./streamify.js') + , defer = require('./defer.js') + ; + +// API +module.exports = ReadableAsyncKit; + +/** + * Base constructor for all streams + * used to hold properties/methods + */ +function ReadableAsyncKit() +{ + ReadableAsyncKit.super_.apply(this, arguments); + + // list of active jobs + this.jobs = {}; + + // add stream methods + this.destroy = destroy; + this._start = _start; + this._read = _read; +} + +/** + * Destroys readable stream, + * by aborting outstanding jobs + * + * @returns {void} + */ +function destroy() +{ + if (this.destroyed) + { + return; + } + + this.destroyed = true; + + if (typeof this.terminator == 'function') + { + this.terminator(); + } +} + +/** + * Starts provided jobs in async manner + * + * @private + */ +function _start() +{ + // first argument – runner function + var runner = arguments[0] + // take away first argument + , args = Array.prototype.slice.call(arguments, 1) + // second argument - input data + , input = args[0] + // last argument - result callback + , endCb = streamify.callback.call(this, args[args.length - 1]) + ; + + args[args.length - 1] = endCb; + // third argument - iterator + args[1] = streamify.iterator.call(this, args[1]); + + // allow time for proper setup + defer(function() + { + if (!this.destroyed) + { + this.terminator = runner.apply(null, args); + } + else + { + endCb(null, Array.isArray(input) ? [] : {}); + } + }.bind(this)); +} + + +/** + * Implement _read to comply with Readable streams + * Doesn't really make sense for flowing object mode + * + * @private + */ +function _read() +{ + +} diff --git a/node_modules/asynckit/lib/readable_parallel.js b/node_modules/asynckit/lib/readable_parallel.js new file mode 100644 index 0000000..5d2929f --- /dev/null +++ b/node_modules/asynckit/lib/readable_parallel.js @@ -0,0 +1,25 @@ +var parallel = require('../parallel.js'); + +// API +module.exports = ReadableParallel; + +/** + * Streaming wrapper to `asynckit.parallel` + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableParallel(list, iterator, callback) +{ + if (!(this instanceof ReadableParallel)) + { + return new ReadableParallel(list, iterator, callback); + } + + // turn on object mode + ReadableParallel.super_.call(this, {objectMode: true}); + + this._start(parallel, list, iterator, callback); +} diff --git a/node_modules/asynckit/lib/readable_serial.js b/node_modules/asynckit/lib/readable_serial.js new file mode 100644 index 0000000..7822698 --- /dev/null +++ b/node_modules/asynckit/lib/readable_serial.js @@ -0,0 +1,25 @@ +var serial = require('../serial.js'); + +// API +module.exports = ReadableSerial; + +/** + * Streaming wrapper to `asynckit.serial` + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableSerial(list, iterator, callback) +{ + if (!(this instanceof ReadableSerial)) + { + return new ReadableSerial(list, iterator, callback); + } + + // turn on object mode + ReadableSerial.super_.call(this, {objectMode: true}); + + this._start(serial, list, iterator, callback); +} diff --git a/node_modules/asynckit/lib/readable_serial_ordered.js b/node_modules/asynckit/lib/readable_serial_ordered.js new file mode 100644 index 0000000..3de89c4 --- /dev/null +++ b/node_modules/asynckit/lib/readable_serial_ordered.js @@ -0,0 +1,29 @@ +var serialOrdered = require('../serialOrdered.js'); + +// API +module.exports = ReadableSerialOrdered; +// expose sort helpers +module.exports.ascending = serialOrdered.ascending; +module.exports.descending = serialOrdered.descending; + +/** + * Streaming wrapper to `asynckit.serialOrdered` + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} sortMethod - custom sort function + * @param {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableSerialOrdered(list, iterator, sortMethod, callback) +{ + if (!(this instanceof ReadableSerialOrdered)) + { + return new ReadableSerialOrdered(list, iterator, sortMethod, callback); + } + + // turn on object mode + ReadableSerialOrdered.super_.call(this, {objectMode: true}); + + this._start(serialOrdered, list, iterator, sortMethod, callback); +} diff --git a/node_modules/asynckit/lib/state.js b/node_modules/asynckit/lib/state.js new file mode 100644 index 0000000..cbea7ad --- /dev/null +++ b/node_modules/asynckit/lib/state.js @@ -0,0 +1,37 @@ +// API +module.exports = state; + +/** + * Creates initial state object + * for iteration over list + * + * @param {array|object} list - list to iterate over + * @param {function|null} sortMethod - function to use for keys sort, + * or `null` to keep them as is + * @returns {object} - initial state object + */ +function state(list, sortMethod) +{ + var isNamedList = !Array.isArray(list) + , initState = + { + index : 0, + keyedList: isNamedList || sortMethod ? Object.keys(list) : null, + jobs : {}, + results : isNamedList ? {} : [], + size : isNamedList ? Object.keys(list).length : list.length + } + ; + + if (sortMethod) + { + // sort array keys based on it's values + // sort object's keys just on own merit + initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) + { + return sortMethod(list[a], list[b]); + }); + } + + return initState; +} diff --git a/node_modules/asynckit/lib/streamify.js b/node_modules/asynckit/lib/streamify.js new file mode 100644 index 0000000..f56a1c9 --- /dev/null +++ b/node_modules/asynckit/lib/streamify.js @@ -0,0 +1,141 @@ +var async = require('./async.js'); + +// API +module.exports = { + iterator: wrapIterator, + callback: wrapCallback +}; + +/** + * Wraps iterators with long signature + * + * @this ReadableAsyncKit# + * @param {function} iterator - function to wrap + * @returns {function} - wrapped function + */ +function wrapIterator(iterator) +{ + var stream = this; + + return function(item, key, cb) + { + var aborter + , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key)) + ; + + stream.jobs[key] = wrappedCb; + + // it's either shortcut (item, cb) + if (iterator.length == 2) + { + aborter = iterator(item, wrappedCb); + } + // or long format (item, key, cb) + else + { + aborter = iterator(item, key, wrappedCb); + } + + return aborter; + }; +} + +/** + * Wraps provided callback function + * allowing to execute snitch function before + * real callback + * + * @this ReadableAsyncKit# + * @param {function} callback - function to wrap + * @returns {function} - wrapped function + */ +function wrapCallback(callback) +{ + var stream = this; + + var wrapped = function(error, result) + { + return finisher.call(stream, error, result, callback); + }; + + return wrapped; +} + +/** + * Wraps provided iterator callback function + * makes sure snitch only called once, + * but passes secondary calls to the original callback + * + * @this ReadableAsyncKit# + * @param {function} callback - callback to wrap + * @param {number|string} key - iteration key + * @returns {function} wrapped callback + */ +function wrapIteratorCallback(callback, key) +{ + var stream = this; + + return function(error, output) + { + // don't repeat yourself + if (!(key in stream.jobs)) + { + callback(error, output); + return; + } + + // clean up jobs + delete stream.jobs[key]; + + return streamer.call(stream, error, {key: key, value: output}, callback); + }; +} + +/** + * Stream wrapper for iterator callback + * + * @this ReadableAsyncKit# + * @param {mixed} error - error response + * @param {mixed} output - iterator output + * @param {function} callback - callback that expects iterator results + */ +function streamer(error, output, callback) +{ + if (error && !this.error) + { + this.error = error; + this.pause(); + this.emit('error', error); + // send back value only, as expected + callback(error, output && output.value); + return; + } + + // stream stuff + this.push(output); + + // back to original track + // send back value only, as expected + callback(error, output && output.value); +} + +/** + * Stream wrapper for finishing callback + * + * @this ReadableAsyncKit# + * @param {mixed} error - error response + * @param {mixed} output - iterator output + * @param {function} callback - callback that expects final results + */ +function finisher(error, output, callback) +{ + // signal end of the stream + // only for successfully finished streams + if (!error) + { + this.push(null); + } + + // back to original track + callback(error, output); +} diff --git a/node_modules/asynckit/lib/terminator.js b/node_modules/asynckit/lib/terminator.js new file mode 100644 index 0000000..d6eb992 --- /dev/null +++ b/node_modules/asynckit/lib/terminator.js @@ -0,0 +1,29 @@ +var abort = require('./abort.js') + , async = require('./async.js') + ; + +// API +module.exports = terminator; + +/** + * Terminates jobs in the attached state context + * + * @this AsyncKitState# + * @param {function} callback - final callback to invoke after termination + */ +function terminator(callback) +{ + if (!Object.keys(this.jobs).length) + { + return; + } + + // fast forward iteration index + this.index = this.size; + + // abort jobs + abort(this); + + // send back results we have so far + async(callback)(null, this.results); +} diff --git a/node_modules/asynckit/package.json b/node_modules/asynckit/package.json new file mode 100644 index 0000000..51147d6 --- /dev/null +++ b/node_modules/asynckit/package.json @@ -0,0 +1,63 @@ +{ + "name": "asynckit", + "version": "0.4.0", + "description": "Minimal async jobs utility library, with streams support", + "main": "index.js", + "scripts": { + "clean": "rimraf coverage", + "lint": "eslint *.js lib/*.js test/*.js", + "test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec", + "win-test": "tape test/test-*.js", + "browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec", + "report": "istanbul report", + "size": "browserify index.js | size-table asynckit", + "debug": "tape test/test-*.js" + }, + "pre-commit": [ + "clean", + "lint", + "test", + "browser", + "report", + "size" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/alexindigo/asynckit.git" + }, + "keywords": [ + "async", + "jobs", + "parallel", + "serial", + "iterator", + "array", + "object", + "stream", + "destroy", + "terminate", + "abort" + ], + "author": "Alex Indigo ", + "license": "MIT", + "bugs": { + "url": "https://github.com/alexindigo/asynckit/issues" + }, + "homepage": "https://github.com/alexindigo/asynckit#readme", + "devDependencies": { + "browserify": "^13.0.0", + "browserify-istanbul": "^2.0.0", + "coveralls": "^2.11.9", + "eslint": "^2.9.0", + "istanbul": "^0.4.3", + "obake": "^0.1.2", + "phantomjs-prebuilt": "^2.1.7", + "pre-commit": "^1.1.3", + "reamde": "^1.1.0", + "rimraf": "^2.5.2", + "size-table": "^0.2.0", + "tap-spec": "^4.1.1", + "tape": "^4.5.1" + }, + "dependencies": {} +} diff --git a/node_modules/asynckit/parallel.js b/node_modules/asynckit/parallel.js new file mode 100644 index 0000000..3c50344 --- /dev/null +++ b/node_modules/asynckit/parallel.js @@ -0,0 +1,43 @@ +var iterate = require('./lib/iterate.js') + , initState = require('./lib/state.js') + , terminator = require('./lib/terminator.js') + ; + +// Public API +module.exports = parallel; + +/** + * Runs iterator over provided array elements in parallel + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function parallel(list, iterator, callback) +{ + var state = initState(list); + + while (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, function(error, result) + { + if (error) + { + callback(error, result); + return; + } + + // looks like it's the last one + if (Object.keys(state.jobs).length === 0) + { + callback(null, state.results); + return; + } + }); + + state.index++; + } + + return terminator.bind(state, callback); +} diff --git a/node_modules/asynckit/serial.js b/node_modules/asynckit/serial.js new file mode 100644 index 0000000..6cd949a --- /dev/null +++ b/node_modules/asynckit/serial.js @@ -0,0 +1,17 @@ +var serialOrdered = require('./serialOrdered.js'); + +// Public API +module.exports = serial; + +/** + * Runs iterator over provided array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serial(list, iterator, callback) +{ + return serialOrdered(list, iterator, null, callback); +} diff --git a/node_modules/asynckit/serialOrdered.js b/node_modules/asynckit/serialOrdered.js new file mode 100644 index 0000000..607eafe --- /dev/null +++ b/node_modules/asynckit/serialOrdered.js @@ -0,0 +1,75 @@ +var iterate = require('./lib/iterate.js') + , initState = require('./lib/state.js') + , terminator = require('./lib/terminator.js') + ; + +// Public API +module.exports = serialOrdered; +// sorting helpers +module.exports.ascending = ascending; +module.exports.descending = descending; + +/** + * Runs iterator over provided sorted array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} sortMethod - custom sort function + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serialOrdered(list, iterator, sortMethod, callback) +{ + var state = initState(list, sortMethod); + + iterate(list, iterator, state, function iteratorHandler(error, result) + { + if (error) + { + callback(error, result); + return; + } + + state.index++; + + // are we there yet? + if (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, iteratorHandler); + return; + } + + // done here + callback(null, state.results); + }); + + return terminator.bind(state, callback); +} + +/* + * -- Sort methods + */ + +/** + * sort helper to sort array elements in ascending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function ascending(a, b) +{ + return a < b ? -1 : a > b ? 1 : 0; +} + +/** + * sort helper to sort array elements in descending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function descending(a, b) +{ + return -1 * ascending(a, b); +} diff --git a/node_modules/asynckit/stream.js b/node_modules/asynckit/stream.js new file mode 100644 index 0000000..d43465f --- /dev/null +++ b/node_modules/asynckit/stream.js @@ -0,0 +1,21 @@ +var inherits = require('util').inherits + , Readable = require('stream').Readable + , ReadableAsyncKit = require('./lib/readable_asynckit.js') + , ReadableParallel = require('./lib/readable_parallel.js') + , ReadableSerial = require('./lib/readable_serial.js') + , ReadableSerialOrdered = require('./lib/readable_serial_ordered.js') + ; + +// API +module.exports = +{ + parallel : ReadableParallel, + serial : ReadableSerial, + serialOrdered : ReadableSerialOrdered, +}; + +inherits(ReadableAsyncKit, Readable); + +inherits(ReadableParallel, ReadableAsyncKit); +inherits(ReadableSerial, ReadableAsyncKit); +inherits(ReadableSerialOrdered, ReadableAsyncKit); diff --git a/node_modules/cacheable-lookup/LICENSE b/node_modules/cacheable-lookup/LICENSE new file mode 100755 index 0000000..92498ed --- /dev/null +++ b/node_modules/cacheable-lookup/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Szymon Marczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/cacheable-lookup/README.md b/node_modules/cacheable-lookup/README.md new file mode 100755 index 0000000..2507155 --- /dev/null +++ b/node_modules/cacheable-lookup/README.md @@ -0,0 +1,240 @@ +# cacheable-lookup + +> A cacheable [`dns.lookup(…)`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) that respects TTL :tada: + +[![Node CI](https://github.com/szmarczak/cacheable-lookup/workflows/Node%20CI/badge.svg)](https://github.com/szmarczak/cacheable-lookup/actions) +[![Coverage Status](https://coveralls.io/repos/github/szmarczak/cacheable-lookup/badge.svg?branch=master)](https://coveralls.io/github/szmarczak/cacheable-lookup?branch=master) +[![npm](https://img.shields.io/npm/dm/cacheable-lookup.svg)](https://www.npmjs.com/package/cacheable-lookup) +[![install size](https://packagephobia.now.sh/badge?p=cacheable-lookup)](https://packagephobia.now.sh/result?p=cacheable-lookup) + +Making lots of HTTP requests? You can save some time by caching DNS lookups :zap: + +## Usage + +### Using the `lookup` option + +```js +const http = require('http'); +const CacheableLookup = require('cacheable-lookup'); + +const cacheable = new CacheableLookup(); + +http.get('http://example.com', {lookup: cacheable.lookup}, response => { + // Handle the response here +}); +``` + +### Attaching CacheableLookup to an Agent + +```js +const http = require('http'); +const CacheableLookup = require('cacheable-lookup'); + +const cacheable = new CacheableLookup(); +cacheable.install(http.globalAgent); + +http.get('http://example.com', response => { + // Handle the response here +}); +``` + +## API + +### new CacheableLookup(options) + +Returns a new instance of `CacheableLookup`. + +#### options + +Type: `object`
+Default: `{}` + +Options used to cache the DNS lookups. + +##### cache + +Type: `Map` | [`Keyv`](https://github.com/lukechilds/keyv/)
+Default: `new Map()` + +Custom cache instance. If `undefined`, it will create a new one. + +**Note**: If you decide to use Keyv instead of the native implementation, the performance will drop by 10x. Memory leaks may occur as it doesn't provide any way to remove all the deprecated values at once. + +**Tip**: [`QuickLRU`](https://github.com/sindresorhus/quick-lru) is fully compatible with the Map API, you can use it to limit the amount of cached entries. Example: + +```js +const http = require('http'); +const CacheableLookup = require('cacheable-lookup'); +const QuickLRU = require('quick-lru'); + +const cacheable = new CacheableLookup({ + cache: new QuickLRU({maxSize: 1000}) +}); + +http.get('http://example.com', {lookup: cacheable.lookup}, response => { + // Handle the response here +}); +``` + +##### options.maxTtl + +Type: `number`
+Default: `Infinity` + +The maximum lifetime of the entries received from the specifed DNS server (TTL in seconds). + +If set to `0`, it will make a new DNS query each time. + +**Pro Tip**: This shouldn't be lower than your DNS server response time in order to prevent bottlenecks. For example, if you use Cloudflare, this value should be greater than `0.01`. + +##### options.fallbackDuration + +Type: `number`
+Default: `3600` (1 hour) + +When the DNS server responds with `ENOTFOUND` or `ENODATA` and the OS reports that the entry is available, it will use `dns.lookup(...)` directly for the requested hostnames for the specified amount of time (in seconds). + +If you don't query internal hostnames (such as `localhost`, `database.local` etc.), it is strongly recommended to set this value to `0`. + +##### options.errorTtl + +Type: `number`
+Default: `0.15` + +The time how long it needs to remember queries that threw `ENOTFOUND` or `ENODATA` (TTL in seconds). + +**Note**: This option is independent, `options.maxTtl` does not affect this. + +**Pro Tip**: This shouldn't be lower than your DNS server response time in order to prevent bottlenecks. For example, if you use Cloudflare, this value should be greater than `0.01`. + +##### options.resolver + +Type: `dns.Resolver | dns.promises.Resolver`
+Default: [`new dns.promises.Resolver()`](https://nodejs.org/api/dns.html#dns_class_dns_resolver) + +An instance of [DNS Resolver](https://nodejs.org/api/dns.html#dns_class_dns_resolver) used to make DNS queries. + +##### options.lookup + +Type: `Function`
+Default: [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) + +The fallback function to use when the DNS server responds with `ENOTFOUND` or `ENODATA`. + +**Note**: This has no effect if the `fallbackDuration` option is less than `1`. + +### Entry object + +Type: `object` + +#### address + +Type: `string` + +The IP address (can be an IPv4 or IPv6 address). + +#### family + +Type: `number` + +The IP family (`4` or `6`). + +##### expires + +Type: `number` + +**Note**: This is not present when falling back to `dns.lookup(...)`! + +The timestamp (`Date.now() + ttl * 1000`) when the entry expires. + +#### ttl + +**Note**: This is not present when falling back to `dns.lookup(...)`! + +The time in seconds for its lifetime. + +### Entry object (callback-style) + +When `options.all` is `false`, then `callback(error, address, family, expires, ttl)` is called.
+When `options.all` is `true`, then `callback(error, entries)` is called. + +### CacheableLookup instance + +#### servers + +Type: `Array` + +The DNS servers used to make queries. Can be overridden - doing so will clear the cache. + +#### [lookup(hostname, options, callback)](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) + +#### lookupAsync(hostname, options) + +The asynchronous version of `dns.lookup(…)`. + +Returns an [entry object](#entry-object).
+If `options.all` is true, returns an array of entry objects. + +##### hostname + +Type: `string` + +##### options + +Type: `object` + +The same as the [`dns.lookup(…)`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) options. + +#### query(hostname) + +An asynchronous function which returns cached DNS lookup entries.
+This is the base for `lookupAsync(hostname, options)` and `lookup(hostname, options, callback)`. + +**Note**: This function has no options. + +Returns an array of objects with `address`, `family`, `ttl` and `expires` properties. + +#### queryAndCache(hostname) + +An asynchronous function which makes two DNS queries: A and AAAA. The result is cached.
+This is used by `query(hostname)` if no entry in the database is present. + +Returns an array of objects with `address`, `family`, `ttl` and `expires` properties. + +#### updateInterfaceInfo() + +Updates interface info. For example, you need to run this when you plug or unplug your WiFi driver. + +**Note:** Running `updateInterfaceInfo()` will trigger `clear()` only on network interface removal. + +#### clear(hostname?) + +Clears the cache for the given hostname. If the hostname argument is not present, the entire cache will be emptied. + +## High performance + +Performed on: +- Query: `example.com` +- CPU: i7-7700k +- CPU governor: performance + +``` +CacheableLookup#lookupAsync x 2,896,251 ops/sec ±1.07% (85 runs sampled) +CacheableLookup#lookupAsync.all x 2,842,664 ops/sec ±1.11% (88 runs sampled) +CacheableLookup#lookupAsync.all.ADDRCONFIG x 2,598,283 ops/sec ±1.21% (88 runs sampled) +CacheableLookup#lookup x 2,565,913 ops/sec ±1.56% (85 runs sampled) +CacheableLookup#lookup.all x 2,609,039 ops/sec ±1.01% (86 runs sampled) +CacheableLookup#lookup.all.ADDRCONFIG x 2,416,242 ops/sec ±0.89% (85 runs sampled) +dns#lookup x 7,272 ops/sec ±0.36% (86 runs sampled) +dns#lookup.all x 7,249 ops/sec ±0.40% (86 runs sampled) +dns#lookup.all.ADDRCONFIG x 5,693 ops/sec ±0.28% (85 runs sampled) +Fastest is CacheableLookup#lookupAsync.all +``` + +## Related + + - [cacheable-request](https://github.com/lukechilds/cacheable-request) - Wrap native HTTP requests with RFC compliant cache support + +## License + +MIT diff --git a/node_modules/cacheable-lookup/index.d.ts b/node_modules/cacheable-lookup/index.d.ts new file mode 100755 index 0000000..528b1e2 --- /dev/null +++ b/node_modules/cacheable-lookup/index.d.ts @@ -0,0 +1,139 @@ +import {Resolver, promises as dnsPromises, lookup} from 'dns'; +import {Agent} from 'http'; + +type AsyncResolver = dnsPromises.Resolver; + +export type IPFamily = 4 | 6; + +type TPromise = T | Promise; + +export interface CacheInstance { + set(hostname: string, entries: EntryObject[], ttl: number): TPromise; + get(hostname: string): TPromise; + delete(hostname: string): TPromise; + clear(): TPromise; +} + +export interface Options { + /** + * Custom cache instance. If `undefined`, it will create a new one. + * @default undefined + */ + cache?: CacheInstance; + /** + * Limits the cache time (TTL). If set to `0`, it will make a new DNS query each time. + * @default Infinity + */ + maxTtl?: number; + /** + * DNS Resolver used to make DNS queries. + * @default new dns.promises.Resolver() + */ + resolver?: Resolver | AsyncResolver; + /** + * When the DNS server responds with `ENOTFOUND` or `ENODATA` and the OS reports that the entry is available, + * it will use `dns.lookup(...)` directly for the requested hostnames for the specified amount of time (in seconds). + * + * If you don't query internal hostnames (such as `localhost`, `database.local` etc.), + * it is strongly recommended to set this value to `0`. + * @default 3600 + */ + fallbackDuration?: number; + /** + * The time how long it needs to remember failed queries (TTL in seconds). + * + * **Note**: This option is independent, `options.maxTtl` does not affect this. + * @default 0.15 + */ + errorTtl?: number; + /** + * The fallback function to use when the DNS server responds with `ENOTFOUND` or `ENODATA`. + * + * **Note**: This has no effect if the `fallbackDuration` option is less than `1`. + * @default dns.lookup + */ + lookup?: typeof lookup; +} + +export interface EntryObject { + /** + * The IP address (can be an IPv4 or IPv5 address). + */ + readonly address: string; + /** + * The IP family. + */ + readonly family: IPFamily; + /** + * The original TTL. + */ + readonly ttl?: number; + /** + * The expiration timestamp. + */ + readonly expires?: number; +} + +export interface LookupOptions { + /** + * One or more supported getaddrinfo flags. Multiple flags may be passed by bitwise ORing their values. + */ + hints?: number; + /** + * The record family. Must be `4` or `6`. IPv4 and IPv6 addresses are both returned by default. + */ + family?: IPFamily; + /** + * When `true`, the callback returns all resolved addresses in an array. Otherwise, returns a single address. + * @default false + */ + all?: boolean; +} + +export default class CacheableLookup { + constructor(options?: Options); + /** + * The DNS servers used to make queries. Can be overridden - doing so will clear the cache. + */ + servers: string[]; + /** + * @see https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback + */ + lookup(hostname: string, family: IPFamily, callback: (error: NodeJS.ErrnoException, address: string, family: IPFamily) => void): void; + lookup(hostname: string, callback: (error: NodeJS.ErrnoException, address: string, family: IPFamily) => void): void; + lookup(hostname: string, options: LookupOptions & {all: true}, callback: (error: NodeJS.ErrnoException, result: ReadonlyArray) => void): void; + lookup(hostname: string, options: LookupOptions, callback: (error: NodeJS.ErrnoException, address: string, family: IPFamily) => void): void; + /** + * The asynchronous version of `dns.lookup(…)`. + */ + lookupAsync(hostname: string, options: LookupOptions & {all: true}): Promise>; + lookupAsync(hostname: string, options: LookupOptions): Promise; + lookupAsync(hostname: string): Promise; + lookupAsync(hostname: string, family: IPFamily): Promise; + /** + * An asynchronous function which returns cached DNS lookup entries. This is the base for `lookupAsync(hostname, options)` and `lookup(hostname, options, callback)`. + */ + query(hostname: string): Promise>; + /** + * An asynchronous function which makes a new DNS lookup query and updates the database. This is used by `query(hostname, family)` if no entry in the database is present. Returns an array of objects with `address`, `family`, `ttl` and `expires` properties. + */ + queryAndCache(hostname: string): Promise>; + /** + * Attaches itself to an Agent instance. + */ + install(agent: Agent): void; + /** + * Removes itself from an Agent instance. + */ + uninstall(agent: Agent): void; + /** + * Updates interface info. For example, you need to run this when you plug or unplug your WiFi driver. + * + * **Note:** Running `updateInterfaceInfo()` will trigger `clear()` only on network interface removal. + */ + updateInterfaceInfo(): void; + /** + * Clears the cache for the given hostname. If the hostname argument is not present, the entire cache will be emptied. + */ + clear(hostname?: string): void; +} diff --git a/node_modules/cacheable-lookup/package.json b/node_modules/cacheable-lookup/package.json new file mode 100755 index 0000000..f20991e --- /dev/null +++ b/node_modules/cacheable-lookup/package.json @@ -0,0 +1,45 @@ +{ + "name": "cacheable-lookup", + "version": "5.0.4", + "description": "A cacheable dns.lookup(…) that respects the TTL", + "engines": { + "node": ">=10.6.0" + }, + "files": [ + "source", + "index.d.ts" + ], + "main": "source/index.js", + "types": "index.d.ts", + "scripts": { + "test": "xo && nyc --reporter=lcovonly --reporter=text ava && tsd" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/szmarczak/cacheable-lookup.git" + }, + "keywords": [ + "dns", + "lookup", + "cacheable", + "ttl" + ], + "author": "Szymon Marczak", + "license": "MIT", + "bugs": { + "url": "https://github.com/szmarczak/cacheable-lookup/issues" + }, + "homepage": "https://github.com/szmarczak/cacheable-lookup#readme", + "devDependencies": { + "@types/keyv": "^3.1.1", + "ava": "^3.8.2", + "benchmark": "^2.1.4", + "coveralls": "^3.0.9", + "keyv": "^4.0.0", + "nyc": "^15.0.0", + "proxyquire": "^2.1.3", + "tsd": "^0.11.0", + "quick-lru": "^5.1.0", + "xo": "^0.25.3" + } +} diff --git a/node_modules/cacheable-lookup/source/index.js b/node_modules/cacheable-lookup/source/index.js new file mode 100755 index 0000000..21f731e --- /dev/null +++ b/node_modules/cacheable-lookup/source/index.js @@ -0,0 +1,436 @@ +'use strict'; +const { + V4MAPPED, + ADDRCONFIG, + ALL, + promises: { + Resolver: AsyncResolver + }, + lookup: dnsLookup +} = require('dns'); +const {promisify} = require('util'); +const os = require('os'); + +const kCacheableLookupCreateConnection = Symbol('cacheableLookupCreateConnection'); +const kCacheableLookupInstance = Symbol('cacheableLookupInstance'); +const kExpires = Symbol('expires'); + +const supportsALL = typeof ALL === 'number'; + +const verifyAgent = agent => { + if (!(agent && typeof agent.createConnection === 'function')) { + throw new Error('Expected an Agent instance as the first argument'); + } +}; + +const map4to6 = entries => { + for (const entry of entries) { + if (entry.family === 6) { + continue; + } + + entry.address = `::ffff:${entry.address}`; + entry.family = 6; + } +}; + +const getIfaceInfo = () => { + let has4 = false; + let has6 = false; + + for (const device of Object.values(os.networkInterfaces())) { + for (const iface of device) { + if (iface.internal) { + continue; + } + + if (iface.family === 'IPv6') { + has6 = true; + } else { + has4 = true; + } + + if (has4 && has6) { + return {has4, has6}; + } + } + } + + return {has4, has6}; +}; + +const isIterable = map => { + return Symbol.iterator in map; +}; + +const ttl = {ttl: true}; +const all = {all: true}; + +class CacheableLookup { + constructor({ + cache = new Map(), + maxTtl = Infinity, + fallbackDuration = 3600, + errorTtl = 0.15, + resolver = new AsyncResolver(), + lookup = dnsLookup + } = {}) { + this.maxTtl = maxTtl; + this.errorTtl = errorTtl; + + this._cache = cache; + this._resolver = resolver; + this._dnsLookup = promisify(lookup); + + if (this._resolver instanceof AsyncResolver) { + this._resolve4 = this._resolver.resolve4.bind(this._resolver); + this._resolve6 = this._resolver.resolve6.bind(this._resolver); + } else { + this._resolve4 = promisify(this._resolver.resolve4.bind(this._resolver)); + this._resolve6 = promisify(this._resolver.resolve6.bind(this._resolver)); + } + + this._iface = getIfaceInfo(); + + this._pending = {}; + this._nextRemovalTime = false; + this._hostnamesToFallback = new Set(); + + if (fallbackDuration < 1) { + this._fallback = false; + } else { + this._fallback = true; + + const interval = setInterval(() => { + this._hostnamesToFallback.clear(); + }, fallbackDuration * 1000); + + /* istanbul ignore next: There is no `interval.unref()` when running inside an Electron renderer */ + if (interval.unref) { + interval.unref(); + } + } + + this.lookup = this.lookup.bind(this); + this.lookupAsync = this.lookupAsync.bind(this); + } + + set servers(servers) { + this.clear(); + + this._resolver.setServers(servers); + } + + get servers() { + return this._resolver.getServers(); + } + + lookup(hostname, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } else if (typeof options === 'number') { + options = { + family: options + }; + } + + if (!callback) { + throw new Error('Callback must be a function.'); + } + + // eslint-disable-next-line promise/prefer-await-to-then + this.lookupAsync(hostname, options).then(result => { + if (options.all) { + callback(null, result); + } else { + callback(null, result.address, result.family, result.expires, result.ttl); + } + }, callback); + } + + async lookupAsync(hostname, options = {}) { + if (typeof options === 'number') { + options = { + family: options + }; + } + + let cached = await this.query(hostname); + + if (options.family === 6) { + const filtered = cached.filter(entry => entry.family === 6); + + if (options.hints & V4MAPPED) { + if ((supportsALL && options.hints & ALL) || filtered.length === 0) { + map4to6(cached); + } else { + cached = filtered; + } + } else { + cached = filtered; + } + } else if (options.family === 4) { + cached = cached.filter(entry => entry.family === 4); + } + + if (options.hints & ADDRCONFIG) { + const {_iface} = this; + cached = cached.filter(entry => entry.family === 6 ? _iface.has6 : _iface.has4); + } + + if (cached.length === 0) { + const error = new Error(`cacheableLookup ENOTFOUND ${hostname}`); + error.code = 'ENOTFOUND'; + error.hostname = hostname; + + throw error; + } + + if (options.all) { + return cached; + } + + return cached[0]; + } + + async query(hostname) { + let cached = await this._cache.get(hostname); + + if (!cached) { + const pending = this._pending[hostname]; + + if (pending) { + cached = await pending; + } else { + const newPromise = this.queryAndCache(hostname); + this._pending[hostname] = newPromise; + + try { + cached = await newPromise; + } finally { + delete this._pending[hostname]; + } + } + } + + cached = cached.map(entry => { + return {...entry}; + }); + + return cached; + } + + async _resolve(hostname) { + const wrap = async promise => { + try { + return await promise; + } catch (error) { + if (error.code === 'ENODATA' || error.code === 'ENOTFOUND') { + return []; + } + + throw error; + } + }; + + // ANY is unsafe as it doesn't trigger new queries in the underlying server. + const [A, AAAA] = await Promise.all([ + this._resolve4(hostname, ttl), + this._resolve6(hostname, ttl) + ].map(promise => wrap(promise))); + + let aTtl = 0; + let aaaaTtl = 0; + let cacheTtl = 0; + + const now = Date.now(); + + for (const entry of A) { + entry.family = 4; + entry.expires = now + (entry.ttl * 1000); + + aTtl = Math.max(aTtl, entry.ttl); + } + + for (const entry of AAAA) { + entry.family = 6; + entry.expires = now + (entry.ttl * 1000); + + aaaaTtl = Math.max(aaaaTtl, entry.ttl); + } + + if (A.length > 0) { + if (AAAA.length > 0) { + cacheTtl = Math.min(aTtl, aaaaTtl); + } else { + cacheTtl = aTtl; + } + } else { + cacheTtl = aaaaTtl; + } + + return { + entries: [ + ...A, + ...AAAA + ], + cacheTtl + }; + } + + async _lookup(hostname) { + try { + const entries = await this._dnsLookup(hostname, { + all: true + }); + + return { + entries, + cacheTtl: 0 + }; + } catch (_) { + return { + entries: [], + cacheTtl: 0 + }; + } + } + + async _set(hostname, data, cacheTtl) { + if (this.maxTtl > 0 && cacheTtl > 0) { + cacheTtl = Math.min(cacheTtl, this.maxTtl) * 1000; + data[kExpires] = Date.now() + cacheTtl; + + try { + await this._cache.set(hostname, data, cacheTtl); + } catch (error) { + this.lookupAsync = async () => { + const cacheError = new Error('Cache Error. Please recreate the CacheableLookup instance.'); + cacheError.cause = error; + + throw cacheError; + }; + } + + if (isIterable(this._cache)) { + this._tick(cacheTtl); + } + } + } + + async queryAndCache(hostname) { + if (this._hostnamesToFallback.has(hostname)) { + return this._dnsLookup(hostname, all); + } + + let query = await this._resolve(hostname); + + if (query.entries.length === 0 && this._fallback) { + query = await this._lookup(hostname); + + if (query.entries.length !== 0) { + // Use `dns.lookup(...)` for that particular hostname + this._hostnamesToFallback.add(hostname); + } + } + + const cacheTtl = query.entries.length === 0 ? this.errorTtl : query.cacheTtl; + await this._set(hostname, query.entries, cacheTtl); + + return query.entries; + } + + _tick(ms) { + const nextRemovalTime = this._nextRemovalTime; + + if (!nextRemovalTime || ms < nextRemovalTime) { + clearTimeout(this._removalTimeout); + + this._nextRemovalTime = ms; + + this._removalTimeout = setTimeout(() => { + this._nextRemovalTime = false; + + let nextExpiry = Infinity; + + const now = Date.now(); + + for (const [hostname, entries] of this._cache) { + const expires = entries[kExpires]; + + if (now >= expires) { + this._cache.delete(hostname); + } else if (expires < nextExpiry) { + nextExpiry = expires; + } + } + + if (nextExpiry !== Infinity) { + this._tick(nextExpiry - now); + } + }, ms); + + /* istanbul ignore next: There is no `timeout.unref()` when running inside an Electron renderer */ + if (this._removalTimeout.unref) { + this._removalTimeout.unref(); + } + } + } + + install(agent) { + verifyAgent(agent); + + if (kCacheableLookupCreateConnection in agent) { + throw new Error('CacheableLookup has been already installed'); + } + + agent[kCacheableLookupCreateConnection] = agent.createConnection; + agent[kCacheableLookupInstance] = this; + + agent.createConnection = (options, callback) => { + if (!('lookup' in options)) { + options.lookup = this.lookup; + } + + return agent[kCacheableLookupCreateConnection](options, callback); + }; + } + + uninstall(agent) { + verifyAgent(agent); + + if (agent[kCacheableLookupCreateConnection]) { + if (agent[kCacheableLookupInstance] !== this) { + throw new Error('The agent is not owned by this CacheableLookup instance'); + } + + agent.createConnection = agent[kCacheableLookupCreateConnection]; + + delete agent[kCacheableLookupCreateConnection]; + delete agent[kCacheableLookupInstance]; + } + } + + updateInterfaceInfo() { + const {_iface} = this; + + this._iface = getIfaceInfo(); + + if ((_iface.has4 && !this._iface.has4) || (_iface.has6 && !this._iface.has6)) { + this._cache.clear(); + } + } + + clear(hostname) { + if (hostname) { + this._cache.delete(hostname); + return; + } + + this._cache.clear(); + } +} + +module.exports = CacheableLookup; +module.exports.default = CacheableLookup; diff --git a/node_modules/cacheable-request/LICENSE b/node_modules/cacheable-request/LICENSE new file mode 100644 index 0000000..f27ee9b --- /dev/null +++ b/node_modules/cacheable-request/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Luke Childs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/cacheable-request/README.md b/node_modules/cacheable-request/README.md new file mode 100644 index 0000000..725e7e0 --- /dev/null +++ b/node_modules/cacheable-request/README.md @@ -0,0 +1,206 @@ +# cacheable-request + +> Wrap native HTTP requests with RFC compliant cache support + +[![Build Status](https://travis-ci.org/lukechilds/cacheable-request.svg?branch=master)](https://travis-ci.org/lukechilds/cacheable-request) +[![Coverage Status](https://coveralls.io/repos/github/lukechilds/cacheable-request/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/cacheable-request?branch=master) +[![npm](https://img.shields.io/npm/dm/cacheable-request.svg)](https://www.npmjs.com/package/cacheable-request) +[![npm](https://img.shields.io/npm/v/cacheable-request.svg)](https://www.npmjs.com/package/cacheable-request) + +[RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching for native Node.js HTTP/HTTPS requests. Caching works out of the box in memory or is easily pluggable with a wide range of storage adapters. + +**Note:** This is a low level wrapper around the core HTTP modules, it's not a high level request library. + +## Features + +- Only stores cacheable responses as defined by RFC 7234 +- Fresh cache entries are served directly from cache +- Stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers +- 304 responses from revalidation requests use cached body +- Updates `Age` header on cached responses +- Can completely bypass cache on a per request basis +- In memory cache by default +- Official support for Redis, MongoDB, SQLite, PostgreSQL and MySQL storage adapters +- Easily plug in your own or third-party storage adapters +- If DB connection fails, cache is automatically bypassed ([disabled by default](#optsautomaticfailover)) +- Adds cache support to any existing HTTP code with minimal changes +- Uses [http-cache-semantics](https://github.com/pornel/http-cache-semantics) internally for HTTP RFC 7234 compliance + +## Install + +```shell +npm install cacheable-request +``` + +## Usage + +```js +const http = require('http'); +const CacheableRequest = require('cacheable-request'); + +// Then instead of +const req = http.request('http://example.com', cb); +req.end(); + +// You can do +const cacheableRequest = new CacheableRequest(http.request); +const cacheReq = cacheableRequest('http://example.com', cb); +cacheReq.on('request', req => req.end()); +// Future requests to 'example.com' will be returned from cache if still valid + +// You pass in any other http.request API compatible method to be wrapped with cache support: +const cacheableRequest = new CacheableRequest(https.request); +const cacheableRequest = new CacheableRequest(electron.net); +``` + +## Storage Adapters + +`cacheable-request` uses [Keyv](https://github.com/lukechilds/keyv) to support a wide range of storage adapters. + +For example, to use Redis as a cache backend, you just need to install the official Redis Keyv storage adapter: + +``` +npm install @keyv/redis +``` + +And then you can pass `CacheableRequest` your connection string: + +```js +const cacheableRequest = new CacheableRequest(http.request, 'redis://user:pass@localhost:6379'); +``` + +[View all official Keyv storage adapters.](https://github.com/lukechilds/keyv#official-storage-adapters) + +Keyv also supports anything that follows the Map API so it's easy to write your own storage adapter or use a third-party solution. + +e.g The following are all valid storage adapters + +```js +const storageAdapter = new Map(); +// or +const storageAdapter = require('./my-storage-adapter'); +// or +const QuickLRU = require('quick-lru'); +const storageAdapter = new QuickLRU({ maxSize: 1000 }); + +const cacheableRequest = new CacheableRequest(http.request, storageAdapter); +``` + +View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters. + +## API + +### new cacheableRequest(request, [storageAdapter]) + +Returns the provided request function wrapped with cache support. + +#### request + +Type: `function` + +Request function to wrap with cache support. Should be [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) or a similar API compatible request function. + +#### storageAdapter + +Type: `Keyv storage adapter`
+Default: `new Map()` + +A [Keyv](https://github.com/lukechilds/keyv) storage adapter instance, or connection string if using with an official Keyv storage adapter. + +### Instance + +#### cacheableRequest(opts, [cb]) + +Returns an event emitter. + +##### opts + +Type: `object`, `string` + +- Any of the default request functions options. +- Any [`http-cache-semantics`](https://github.com/kornelski/http-cache-semantics#constructor-options) options. +- Any of the following: + +###### opts.cache + +Type: `boolean`
+Default: `true` + +If the cache should be used. Setting this to false will completely bypass the cache for the current request. + +###### opts.strictTtl + +Type: `boolean`
+Default: `false` + +If set to `true` once a cached resource has expired it is deleted and will have to be re-requested. + +If set to `false` (default), after a cached resource's TTL expires it is kept in the cache and will be revalidated on the next request with `If-None-Match`/`If-Modified-Since` headers. + +###### opts.maxTtl + +Type: `number`
+Default: `undefined` + +Limits TTL. The `number` represents milliseconds. + +###### opts.automaticFailover + +Type: `boolean`
+Default: `false` + +When set to `true`, if the DB connection fails we will automatically fallback to a network request. DB errors will still be emitted to notify you of the problem even though the request callback may succeed. + +###### opts.forceRefresh + +Type: `boolean`
+Default: `false` + +Forces refreshing the cache. If the response could be retrieved from the cache, it will perform a new request and override the cache instead. + +##### cb + +Type: `function` + +The callback function which will receive the response as an argument. + +The response can be either a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) or a [responselike object](https://github.com/lukechilds/responselike). The response will also have a `fromCache` property set with a boolean value. + +##### .on('request', request) + +`request` event to get the request object of the request. + +**Note:** This event will only fire if an HTTP request is actually made, not when a response is retrieved from cache. However, you should always handle the `request` event to end the request and handle any potential request errors. + +##### .on('response', response) + +`response` event to get the response object from the HTTP request or cache. + +##### .on('error', error) + +`error` event emitted in case of an error with the cache. + +Errors emitted here will be an instance of `CacheableRequest.RequestError` or `CacheableRequest.CacheError`. You will only ever receive a `RequestError` if the request function throws (normally caused by invalid user input). Normal request errors should be handled inside the `request` event. + +To properly handle all error scenarios you should use the following pattern: + +```js +cacheableRequest('example.com', cb) + .on('error', err => { + if (err instanceof CacheableRequest.CacheError) { + handleCacheError(err); // Cache error + } else if (err instanceof CacheableRequest.RequestError) { + handleRequestError(err); // Request function thrown + } + }) + .on('request', req => { + req.on('error', handleRequestError); // Request error emitted + req.end(); + }); +``` + +**Note:** Database connection errors are emitted here, however `cacheable-request` will attempt to re-request the resource and bypass the cache on a connection error. Therefore a database connection error doesn't necessarily mean the request won't be fulfilled. + +## License + +MIT © Luke Childs diff --git a/node_modules/cacheable-request/package.json b/node_modules/cacheable-request/package.json new file mode 100644 index 0000000..fec4797 --- /dev/null +++ b/node_modules/cacheable-request/package.json @@ -0,0 +1,56 @@ +{ + "name": "cacheable-request", + "version": "7.0.1", + "description": "Wrap native HTTP requests with RFC compliant cache support", + "license": "MIT", + "repository": "lukechilds/cacheable-request", + "author": "Luke Childs (http://lukechilds.co.uk)", + "main": "src/index.js", + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && nyc ava", + "coverage": "nyc report --reporter=text-lcov | coveralls" + }, + "files": [ + "src" + ], + "keywords": [ + "HTTP", + "HTTPS", + "cache", + "caching", + "layer", + "cacheable", + "RFC 7234", + "RFC", + "7234", + "compliant" + ], + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + }, + "devDependencies": { + "@keyv/sqlite": "^2.0.0", + "ava": "^1.1.0", + "coveralls": "^3.0.0", + "create-test-server": "3.0.0", + "delay": "^4.0.0", + "eslint-config-xo-lukechilds": "^1.0.0", + "nyc": "^14.1.1", + "pify": "^4.0.0", + "sqlite3": "^4.0.2", + "this": "^1.0.2", + "xo": "^0.23.0" + }, + "xo": { + "extends": "xo-lukechilds" + } +} diff --git a/node_modules/cacheable-request/src/index.js b/node_modules/cacheable-request/src/index.js new file mode 100644 index 0000000..3fcea3f --- /dev/null +++ b/node_modules/cacheable-request/src/index.js @@ -0,0 +1,251 @@ +'use strict'; + +const EventEmitter = require('events'); +const urlLib = require('url'); +const normalizeUrl = require('normalize-url'); +const getStream = require('get-stream'); +const CachePolicy = require('http-cache-semantics'); +const Response = require('responselike'); +const lowercaseKeys = require('lowercase-keys'); +const cloneResponse = require('clone-response'); +const Keyv = require('keyv'); + +class CacheableRequest { + constructor(request, cacheAdapter) { + if (typeof request !== 'function') { + throw new TypeError('Parameter `request` must be a function'); + } + + this.cache = new Keyv({ + uri: typeof cacheAdapter === 'string' && cacheAdapter, + store: typeof cacheAdapter !== 'string' && cacheAdapter, + namespace: 'cacheable-request' + }); + + return this.createCacheableRequest(request); + } + + createCacheableRequest(request) { + return (opts, cb) => { + let url; + if (typeof opts === 'string') { + url = normalizeUrlObject(urlLib.parse(opts)); + opts = {}; + } else if (opts instanceof urlLib.URL) { + url = normalizeUrlObject(urlLib.parse(opts.toString())); + opts = {}; + } else { + const [pathname, ...searchParts] = (opts.path || '').split('?'); + const search = searchParts.length > 0 ? + `?${searchParts.join('?')}` : + ''; + url = normalizeUrlObject({ ...opts, pathname, search }); + } + + opts = { + headers: {}, + method: 'GET', + cache: true, + strictTtl: false, + automaticFailover: false, + ...opts, + ...urlObjectToRequestOptions(url) + }; + opts.headers = lowercaseKeys(opts.headers); + + const ee = new EventEmitter(); + const normalizedUrlString = normalizeUrl( + urlLib.format(url), + { + stripWWW: false, + removeTrailingSlash: false, + stripAuthentication: false + } + ); + const key = `${opts.method}:${normalizedUrlString}`; + let revalidate = false; + let madeRequest = false; + + const makeRequest = opts => { + madeRequest = true; + let requestErrored = false; + let requestErrorCallback; + + const requestErrorPromise = new Promise(resolve => { + requestErrorCallback = () => { + if (!requestErrored) { + requestErrored = true; + resolve(); + } + }; + }); + + const handler = response => { + if (revalidate && !opts.forceRefresh) { + response.status = response.statusCode; + const revalidatedPolicy = CachePolicy.fromObject(revalidate.cachePolicy).revalidatedPolicy(opts, response); + if (!revalidatedPolicy.modified) { + const headers = revalidatedPolicy.policy.responseHeaders(); + response = new Response(revalidate.statusCode, headers, revalidate.body, revalidate.url); + response.cachePolicy = revalidatedPolicy.policy; + response.fromCache = true; + } + } + + if (!response.fromCache) { + response.cachePolicy = new CachePolicy(opts, response, opts); + response.fromCache = false; + } + + let clonedResponse; + if (opts.cache && response.cachePolicy.storable()) { + clonedResponse = cloneResponse(response); + + (async () => { + try { + const bodyPromise = getStream.buffer(response); + + await Promise.race([ + requestErrorPromise, + new Promise(resolve => response.once('end', resolve)) + ]); + + if (requestErrored) { + return; + } + + const body = await bodyPromise; + + const value = { + cachePolicy: response.cachePolicy.toObject(), + url: response.url, + statusCode: response.fromCache ? revalidate.statusCode : response.statusCode, + body + }; + + let ttl = opts.strictTtl ? response.cachePolicy.timeToLive() : undefined; + if (opts.maxTtl) { + ttl = ttl ? Math.min(ttl, opts.maxTtl) : opts.maxTtl; + } + + await this.cache.set(key, value, ttl); + } catch (error) { + ee.emit('error', new CacheableRequest.CacheError(error)); + } + })(); + } else if (opts.cache && revalidate) { + (async () => { + try { + await this.cache.delete(key); + } catch (error) { + ee.emit('error', new CacheableRequest.CacheError(error)); + } + })(); + } + + ee.emit('response', clonedResponse || response); + if (typeof cb === 'function') { + cb(clonedResponse || response); + } + }; + + try { + const req = request(opts, handler); + req.once('error', requestErrorCallback); + req.once('abort', requestErrorCallback); + ee.emit('request', req); + } catch (error) { + ee.emit('error', new CacheableRequest.RequestError(error)); + } + }; + + (async () => { + const get = async opts => { + await Promise.resolve(); + + const cacheEntry = opts.cache ? await this.cache.get(key) : undefined; + if (typeof cacheEntry === 'undefined') { + return makeRequest(opts); + } + + const policy = CachePolicy.fromObject(cacheEntry.cachePolicy); + if (policy.satisfiesWithoutRevalidation(opts) && !opts.forceRefresh) { + const headers = policy.responseHeaders(); + const response = new Response(cacheEntry.statusCode, headers, cacheEntry.body, cacheEntry.url); + response.cachePolicy = policy; + response.fromCache = true; + + ee.emit('response', response); + if (typeof cb === 'function') { + cb(response); + } + } else { + revalidate = cacheEntry; + opts.headers = policy.revalidationHeaders(opts); + makeRequest(opts); + } + }; + + const errorHandler = error => ee.emit('error', new CacheableRequest.CacheError(error)); + this.cache.once('error', errorHandler); + ee.on('response', () => this.cache.removeListener('error', errorHandler)); + + try { + await get(opts); + } catch (error) { + if (opts.automaticFailover && !madeRequest) { + makeRequest(opts); + } + + ee.emit('error', new CacheableRequest.CacheError(error)); + } + })(); + + return ee; + }; + } +} + +function urlObjectToRequestOptions(url) { + const options = { ...url }; + options.path = `${url.pathname || '/'}${url.search || ''}`; + delete options.pathname; + delete options.search; + return options; +} + +function normalizeUrlObject(url) { + // If url was parsed by url.parse or new URL: + // - hostname will be set + // - host will be hostname[:port] + // - port will be set if it was explicit in the parsed string + // Otherwise, url was from request options: + // - hostname or host may be set + // - host shall not have port encoded + return { + protocol: url.protocol, + auth: url.auth, + hostname: url.hostname || url.host || 'localhost', + port: url.port, + pathname: url.pathname, + search: url.search + }; +} + +CacheableRequest.RequestError = class extends Error { + constructor(error) { + super(error.message); + this.name = 'RequestError'; + Object.assign(this, error); + } +}; + +CacheableRequest.CacheError = class extends Error { + constructor(error) { + super(error.message); + this.name = 'CacheError'; + Object.assign(this, error); + } +}; + +module.exports = CacheableRequest; diff --git a/node_modules/clone-response/LICENSE b/node_modules/clone-response/LICENSE new file mode 100644 index 0000000..f27ee9b --- /dev/null +++ b/node_modules/clone-response/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Luke Childs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/clone-response/README.md b/node_modules/clone-response/README.md new file mode 100644 index 0000000..d037cfe --- /dev/null +++ b/node_modules/clone-response/README.md @@ -0,0 +1,62 @@ +# clone-response + +> Clone a Node.js HTTP response stream + +[![Build Status](https://travis-ci.org/lukechilds/clone-response.svg?branch=master)](https://travis-ci.org/lukechilds/clone-response) +[![Coverage Status](https://coveralls.io/repos/github/lukechilds/clone-response/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/clone-response?branch=master) +[![npm](https://img.shields.io/npm/dm/clone-response.svg)](https://www.npmjs.com/package/clone-response) +[![npm](https://img.shields.io/npm/v/clone-response.svg)](https://www.npmjs.com/package/clone-response) + +Returns a new stream and copies over all properties and methods from the original response giving you a complete duplicate. + +This is useful in situations where you need to consume the response stream but also want to pass an unconsumed stream somewhere else to be consumed later. + +## Install + +```shell +npm install --save clone-response +``` + +## Usage + +```js +const http = require('http'); +const cloneResponse = require('clone-response'); + +http.get('http://example.com', response => { + const clonedResponse = cloneResponse(response); + response.pipe(process.stdout); + + setImmediate(() => { + // The response stream has already been consumed by the time this executes, + // however the cloned response stream is still available. + doSomethingWithResponse(clonedResponse); + }); +}); +``` + +Please bear in mind that the process of cloning a stream consumes it. However, you can consume a stream multiple times in the same tick, therefore allowing you to create multiple clones. e.g: + +```js +const clone1 = cloneResponse(response); +const clone2 = cloneResponse(response); +// response can still be consumed in this tick but cannot be consumed if passed +// into any async callbacks. clone1 and clone2 can be passed around and be +// consumed in the future. +``` + +## API + +### cloneResponse(response) + +Returns a clone of the passed in response. + +#### response + +Type: `stream` + +A [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) to clone. + +## License + +MIT © Luke Childs diff --git a/node_modules/clone-response/package.json b/node_modules/clone-response/package.json new file mode 100644 index 0000000..2cb9aa6 --- /dev/null +++ b/node_modules/clone-response/package.json @@ -0,0 +1,44 @@ +{ + "name": "clone-response", + "version": "1.0.2", + "description": "Clone a Node.js HTTP response stream", + "main": "src/index.js", + "scripts": { + "test": "xo && nyc ava", + "coverage": "nyc report --reporter=text-lcov | coveralls" + }, + "xo": { + "extends": "xo-lukechilds" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lukechilds/clone-response.git" + }, + "keywords": [ + "clone", + "duplicate", + "copy", + "response", + "HTTP", + "stream" + ], + "author": "Luke Childs (http://lukechilds.co.uk)", + "license": "MIT", + "bugs": { + "url": "https://github.com/lukechilds/clone-response/issues" + }, + "homepage": "https://github.com/lukechilds/clone-response", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "devDependencies": { + "ava": "^0.22.0", + "coveralls": "^2.13.1", + "create-test-server": "^2.0.1", + "eslint-config-xo-lukechilds": "^1.0.0", + "get-stream": "^3.0.0", + "nyc": "^11.0.2", + "pify": "^3.0.0", + "xo": "^0.19.0" + } +} diff --git a/node_modules/clone-response/src/index.js b/node_modules/clone-response/src/index.js new file mode 100644 index 0000000..0285dff --- /dev/null +++ b/node_modules/clone-response/src/index.js @@ -0,0 +1,17 @@ +'use strict'; + +const PassThrough = require('stream').PassThrough; +const mimicResponse = require('mimic-response'); + +const cloneResponse = response => { + if (!(response && response.pipe)) { + throw new TypeError('Parameter `response` must be a response stream.'); + } + + const clone = new PassThrough(); + mimicResponse(response, clone); + + return response.pipe(clone); +}; + +module.exports = cloneResponse; diff --git a/node_modules/combined-stream/License b/node_modules/combined-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/combined-stream/Readme.md b/node_modules/combined-stream/Readme.md new file mode 100644 index 0000000..9e367b5 --- /dev/null +++ b/node_modules/combined-stream/Readme.md @@ -0,0 +1,138 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +**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`. + +- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module. + +- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = `true` + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = `2 * 1024 * 1024` + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = `0` + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/combined-stream/lib/combined_stream.js b/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 0000000..125f097 --- /dev/null +++ b/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,208 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; + this._insideLoop = false; + this._pendingNext = false; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + var newStream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + stream.on('data', this._checkDataSize.bind(this)); + stream = newStream; + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); + return dest; +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + + if (this._insideLoop) { + this._pendingNext = true; + return; // defer call + } + + this._insideLoop = true; + try { + do { + this._pendingNext = false; + this._realGetNext(); + } while (this._pendingNext); + } finally { + this._insideLoop = false; + } +}; + +CombinedStream.prototype._realGetNext = function() { + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)); + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause(); + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume(); + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'; + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/combined-stream/package.json b/node_modules/combined-stream/package.json new file mode 100644 index 0000000..6982b6d --- /dev/null +++ b/node_modules/combined-stream/package.json @@ -0,0 +1,25 @@ +{ + "author": "Felix Geisendörfer (http://debuggable.com/)", + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "1.0.8", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "scripts": { + "test": "node test/run.js" + }, + "engines": { + "node": ">= 0.8" + }, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "devDependencies": { + "far": "~0.0.7" + }, + "license": "MIT" +} diff --git a/node_modules/combined-stream/yarn.lock b/node_modules/combined-stream/yarn.lock new file mode 100644 index 0000000..7edf418 --- /dev/null +++ b/node_modules/combined-stream/yarn.lock @@ -0,0 +1,17 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +far@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/far/-/far-0.0.7.tgz#01c1fd362bcd26ce9cf161af3938aa34619f79a7" + dependencies: + oop "0.0.3" + +oop@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/oop/-/oop-0.0.3.tgz#70fa405a5650891a194fdc82ca68dad6dabf4401" diff --git a/node_modules/decompress-response/index.d.ts b/node_modules/decompress-response/index.d.ts new file mode 100644 index 0000000..c0be175 --- /dev/null +++ b/node_modules/decompress-response/index.d.ts @@ -0,0 +1,22 @@ +/// +import {IncomingMessage} from 'http'; + +/** +Decompress a HTTP response if needed. + +@param response - The HTTP incoming stream with compressed data. +@returns The decompressed HTTP response stream. + +@example +``` +import {http} from 'http'; +import decompressResponse = require('decompress-response'); + +http.get('https://sindresorhus.com', response => { + response = decompressResponse(response); +}); +``` +*/ +declare function decompressResponse(response: IncomingMessage): IncomingMessage; + +export = decompressResponse; diff --git a/node_modules/decompress-response/index.js b/node_modules/decompress-response/index.js new file mode 100644 index 0000000..c861036 --- /dev/null +++ b/node_modules/decompress-response/index.js @@ -0,0 +1,58 @@ +'use strict'; +const {Transform, PassThrough} = require('stream'); +const zlib = require('zlib'); +const mimicResponse = require('mimic-response'); + +module.exports = response => { + const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase(); + + if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) { + return response; + } + + // TODO: Remove this when targeting Node.js 12. + const isBrotli = contentEncoding === 'br'; + if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') { + response.destroy(new Error('Brotli is not supported on Node.js < 12')); + return response; + } + + let isEmpty = true; + + const checker = new Transform({ + transform(data, _encoding, callback) { + isEmpty = false; + + callback(null, data); + }, + + flush(callback) { + callback(); + } + }); + + const finalStream = new PassThrough({ + autoDestroy: false, + destroy(error, callback) { + response.destroy(); + + callback(error); + } + }); + + const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip(); + + decompressStream.once('error', error => { + if (isEmpty && !response.readable) { + finalStream.end(); + return; + } + + finalStream.destroy(error); + }); + + mimicResponse(response, finalStream); + response.pipe(checker).pipe(decompressStream).pipe(finalStream); + + return finalStream; +}; diff --git a/node_modules/decompress-response/license b/node_modules/decompress-response/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/decompress-response/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/decompress-response/node_modules/mimic-response/index.d.ts b/node_modules/decompress-response/node_modules/mimic-response/index.d.ts new file mode 100644 index 0000000..65a51e9 --- /dev/null +++ b/node_modules/decompress-response/node_modules/mimic-response/index.d.ts @@ -0,0 +1,17 @@ +import {IncomingMessage} from 'http'; + +/** +Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + +Makes `toStream` include the properties from `fromStream`. + +@param fromStream - The stream to copy the properties from. +@param toStream - The stream to copy the properties to. +@return The same object as `toStream`. +*/ +declare function mimicResponse( + fromStream: IncomingMessage, // eslint-disable-line @typescript-eslint/prefer-readonly-parameter-types + toStream: T, +): T & IncomingMessage; + +export = mimicResponse; diff --git a/node_modules/decompress-response/node_modules/mimic-response/index.js b/node_modules/decompress-response/node_modules/mimic-response/index.js new file mode 100644 index 0000000..404e111 --- /dev/null +++ b/node_modules/decompress-response/node_modules/mimic-response/index.js @@ -0,0 +1,77 @@ +'use strict'; + +// We define these manually to ensure they're always copied +// even if they would move up the prototype chain +// https://nodejs.org/api/http.html#http_class_http_incomingmessage +const knownProperties = [ + 'aborted', + 'complete', + 'headers', + 'httpVersion', + 'httpVersionMinor', + 'httpVersionMajor', + 'method', + 'rawHeaders', + 'rawTrailers', + 'setTimeout', + 'socket', + 'statusCode', + 'statusMessage', + 'trailers', + 'url' +]; + +module.exports = (fromStream, toStream) => { + if (toStream._readableState.autoDestroy) { + throw new Error('The second stream must have the `autoDestroy` option set to `false`'); + } + + const fromProperties = new Set(Object.keys(fromStream).concat(knownProperties)); + + const properties = {}; + + for (const property of fromProperties) { + // Don't overwrite existing properties. + if (property in toStream) { + continue; + } + + properties[property] = { + get() { + const value = fromStream[property]; + const isFunction = typeof value === 'function'; + + return isFunction ? value.bind(fromStream) : value; + }, + set(value) { + fromStream[property] = value; + }, + enumerable: true, + configurable: false + }; + } + + Object.defineProperties(toStream, properties); + + fromStream.once('aborted', () => { + toStream.destroy(); + + toStream.emit('aborted'); + }); + + fromStream.once('close', () => { + if (fromStream.complete) { + if (toStream.readable) { + toStream.once('end', () => { + toStream.emit('close'); + }); + } else { + toStream.emit('close'); + } + } else { + toStream.emit('close'); + } + }); + + return toStream; +}; diff --git a/node_modules/decompress-response/node_modules/mimic-response/license b/node_modules/decompress-response/node_modules/mimic-response/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/decompress-response/node_modules/mimic-response/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/decompress-response/node_modules/mimic-response/package.json b/node_modules/decompress-response/node_modules/mimic-response/package.json new file mode 100644 index 0000000..d478b0f --- /dev/null +++ b/node_modules/decompress-response/node_modules/mimic-response/package.json @@ -0,0 +1,42 @@ +{ + "name": "mimic-response", + "version": "3.1.0", + "description": "Mimic a Node.js HTTP response stream", + "license": "MIT", + "repository": "sindresorhus/mimic-response", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=10" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.d.ts", + "index.js" + ], + "keywords": [ + "mimic", + "response", + "stream", + "http", + "https", + "request", + "get", + "core" + ], + "devDependencies": { + "@types/node": "^14.0.1", + "ava": "^2.4.0", + "create-test-server": "^2.4.0", + "p-event": "^4.1.0", + "pify": "^5.0.0", + "tsd": "^0.11.0", + "xo": "^0.30.0" + } +} diff --git a/node_modules/decompress-response/node_modules/mimic-response/readme.md b/node_modules/decompress-response/node_modules/mimic-response/readme.md new file mode 100644 index 0000000..e968620 --- /dev/null +++ b/node_modules/decompress-response/node_modules/mimic-response/readme.md @@ -0,0 +1,78 @@ +# mimic-response [![Build Status](https://travis-ci.com/sindresorhus/mimic-response.svg?branch=master)](https://travis-ci.com/sindresorhus/mimic-response) + +> Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + +## Install + +``` +$ npm install mimic-response +``` + +## Usage + +```js +const stream = require('stream'); +const mimicResponse = require('mimic-response'); + +const responseStream = getHttpResponseStream(); +const myStream = new stream.PassThrough(); + +mimicResponse(responseStream, myStream); + +console.log(myStream.statusCode); +//=> 200 +``` + +## API + +### mimicResponse(from, to) + +**Note #1:** The `from.destroy(error)` function is not proxied. You have to call it manually: + +```js +const stream = require('stream'); +const mimicResponse = require('mimic-response'); + +const responseStream = getHttpResponseStream(); + +const myStream = new stream.PassThrough({ + destroy(error, callback) { + responseStream.destroy(); + + callback(error); + } +}); + +myStream.destroy(); +``` + +Please note that `myStream` and `responseStream` never throws. The error is passed to the request instead. + +#### from + +Type: `Stream` + +[Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + +#### to + +Type: `Stream` + +Any stream. + +## Related + +- [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one +- [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream + +--- + +

+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/decompress-response/package.json b/node_modules/decompress-response/package.json new file mode 100644 index 0000000..57df889 --- /dev/null +++ b/node_modules/decompress-response/package.json @@ -0,0 +1,56 @@ +{ + "name": "decompress-response", + "version": "6.0.0", + "description": "Decompress a HTTP response if needed", + "license": "MIT", + "repository": "sindresorhus/decompress-response", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=10" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "decompress", + "response", + "http", + "https", + "zlib", + "gzip", + "zip", + "deflate", + "unzip", + "ungzip", + "incoming", + "message", + "stream", + "compressed", + "brotli" + ], + "dependencies": { + "mimic-response": "^3.1.0" + }, + "devDependencies": { + "@types/node": "^14.0.1", + "ava": "^2.2.0", + "get-stream": "^5.0.0", + "pify": "^5.0.0", + "tsd": "^0.11.0", + "xo": "^0.30.0" + }, + "xo": { + "rules": { + "@typescript-eslint/prefer-readonly-parameter-types": "off" + } + } +} diff --git a/node_modules/decompress-response/readme.md b/node_modules/decompress-response/readme.md new file mode 100644 index 0000000..58523ef --- /dev/null +++ b/node_modules/decompress-response/readme.md @@ -0,0 +1,48 @@ +# decompress-response [![Build Status](https://travis-ci.com/sindresorhus/decompress-response.svg?branch=master)](https://travis-ci.com/sindresorhus/decompress-response) + +> Decompress a HTTP response if needed + +Decompresses the [response](https://nodejs.org/api/http.html#http_class_http_incomingmessage) from [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) if it's gzipped, deflated or compressed with Brotli, otherwise just passes it through. + +Used by [`got`](https://github.com/sindresorhus/got). + +## Install + +``` +$ npm install decompress-response +``` + +## Usage + +```js +const http = require('http'); +const decompressResponse = require('decompress-response'); + +http.get('https://sindresorhus.com', response => { + response = decompressResponse(response); +}); +``` + +## API + +### decompressResponse(response) + +Returns the decompressed HTTP response stream. + +#### response + +Type: [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + +The HTTP incoming stream with compressed data. + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/defer-to-connect/LICENSE b/node_modules/defer-to-connect/LICENSE new file mode 100644 index 0000000..15ad2e8 --- /dev/null +++ b/node_modules/defer-to-connect/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Szymon Marczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/defer-to-connect/README.md b/node_modules/defer-to-connect/README.md new file mode 100644 index 0000000..4dd36c2 --- /dev/null +++ b/node_modules/defer-to-connect/README.md @@ -0,0 +1,38 @@ +# defer-to-connect + +> The safe way to handle the `connect` socket event + +[![Coverage Status](https://coveralls.io/repos/github/szmarczak/defer-to-connect/badge.svg?branch=master)](https://coveralls.io/github/szmarczak/defer-to-connect?branch=master) + +Once you receive the socket, it may be already connected (or disconnected).
+To avoid checking that, use `defer-to-connect`. It'll do that for you. + +## Usage + +```js +const deferToConnect = require('defer-to-connect'); + +deferToConnect(socket, () => { + console.log('Connected!'); +}); +``` + +## API + +### deferToConnect(socket, connectListener) + +Calls `connectListener()` when connected. + +### deferToConnect(socket, listeners) + +#### listeners + +An object representing `connect`, `secureConnect` and `close` properties. + +Calls `connect()` when the socket is connected.
+Calls `secureConnect()` when the socket is securely connected.
+Calls `close()` when the socket is destroyed. + +## License + +MIT diff --git a/node_modules/defer-to-connect/dist/source/index.d.ts b/node_modules/defer-to-connect/dist/source/index.d.ts new file mode 100644 index 0000000..8db8dbb --- /dev/null +++ b/node_modules/defer-to-connect/dist/source/index.d.ts @@ -0,0 +1,10 @@ +/// +import { Socket } from 'net'; +import { TLSSocket } from 'tls'; +interface Listeners { + connect?: () => void; + secureConnect?: () => void; + close?: (hadError: boolean) => void; +} +declare const deferToConnect: (socket: TLSSocket | Socket, fn: Listeners | (() => void)) => void; +export default deferToConnect; diff --git a/node_modules/defer-to-connect/dist/source/index.js b/node_modules/defer-to-connect/dist/source/index.js new file mode 100644 index 0000000..f26c4fa --- /dev/null +++ b/node_modules/defer-to-connect/dist/source/index.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isTLSSocket(socket) { + return socket.encrypted; +} +const deferToConnect = (socket, fn) => { + let listeners; + if (typeof fn === 'function') { + const connect = fn; + listeners = { connect }; + } + else { + listeners = fn; + } + const hasConnectListener = typeof listeners.connect === 'function'; + const hasSecureConnectListener = typeof listeners.secureConnect === 'function'; + const hasCloseListener = typeof listeners.close === 'function'; + const onConnect = () => { + if (hasConnectListener) { + listeners.connect(); + } + if (isTLSSocket(socket) && hasSecureConnectListener) { + if (socket.authorized) { + listeners.secureConnect(); + } + else if (!socket.authorizationError) { + socket.once('secureConnect', listeners.secureConnect); + } + } + if (hasCloseListener) { + socket.once('close', listeners.close); + } + }; + if (socket.writable && !socket.connecting) { + onConnect(); + } + else if (socket.connecting) { + socket.once('connect', onConnect); + } + else if (socket.destroyed && hasCloseListener) { + listeners.close(socket._hadError); + } +}; +exports.default = deferToConnect; +// For CommonJS default export support +module.exports = deferToConnect; +module.exports.default = deferToConnect; diff --git a/node_modules/defer-to-connect/package.json b/node_modules/defer-to-connect/package.json new file mode 100644 index 0000000..4dbd1c6 --- /dev/null +++ b/node_modules/defer-to-connect/package.json @@ -0,0 +1,71 @@ +{ + "name": "defer-to-connect", + "version": "2.0.1", + "description": "The safe way to handle the `connect` socket event", + "main": "dist/source", + "files": [ + "dist/source" + ], + "engines": { + "node": ">=10" + }, + "scripts": { + "build": "del-cli dist && tsc", + "prepare": "npm run build", + "test": "xo && tsc --noEmit && nyc ava", + "coveralls": "nyc report --reporter=text-lcov | coveralls" + }, + "keywords": [ + "socket", + "connect", + "event" + ], + "author": "Szymon Marczak", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/szmarczak/defer-to-connect.git" + }, + "bugs": { + "url": "https://github.com/szmarczak/defer-to-connect/issues" + }, + "homepage": "https://github.com/szmarczak/defer-to-connect#readme", + "xo": { + "extends": "xo-typescript", + "extensions": [ + "ts" + ] + }, + "devDependencies": { + "@ava/typescript": "^1.1.0", + "@sindresorhus/tsconfig": "^0.7.0", + "@types/node": "^13.5.0", + "@typescript-eslint/eslint-plugin": "^2.18.0", + "@typescript-eslint/parser": "^2.18.0", + "ava": "^3.2.0", + "coveralls": "^3.0.9", + "create-cert": "^1.0.6", + "del-cli": "^3.0.0", + "eslint-config-xo-typescript": "^0.24.1", + "nyc": "^15.0.0", + "p-event": "^4.1.0", + "typescript": "^3.7.5", + "xo": "^0.25.3" + }, + "nyc": { + "include": [ + "dist/source" + ], + "extension": [ + ".ts" + ] + }, + "ava": { + "typescript": { + "rewritePaths": { + "tests/": "dist/tests/" + } + } + }, + "types": "dist/source/index.d.ts" +} diff --git a/node_modules/delayed-stream/.npmignore b/node_modules/delayed-stream/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/delayed-stream/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/delayed-stream/License b/node_modules/delayed-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/delayed-stream/Makefile b/node_modules/delayed-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/delayed-stream/Readme.md b/node_modules/delayed-stream/Readme.md new file mode 100644 index 0000000..aca36f9 --- /dev/null +++ b/node_modules/delayed-stream/Readme.md @@ -0,0 +1,141 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 0000000..b38fc85 --- /dev/null +++ b/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,107 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +Object.defineProperty(DelayedStream.prototype, 'readable', { + configurable: true, + enumerable: true, + get: function() { + return this.source.readable; + } +}); + +DelayedStream.prototype.setEncoding = function() { + return this.source.setEncoding.apply(this.source, arguments); +}; + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/delayed-stream/package.json b/node_modules/delayed-stream/package.json new file mode 100644 index 0000000..eea3291 --- /dev/null +++ b/node_modules/delayed-stream/package.json @@ -0,0 +1,27 @@ +{ + "author": "Felix Geisendörfer (http://debuggable.com/)", + "contributors": [ + "Mike Atkins " + ], + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "license": "MIT", + "version": "1.0.0", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "scripts": { + "test": "make test" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + } +} diff --git a/node_modules/discord.js/.tern-project b/node_modules/discord.js/.tern-project new file mode 100644 index 0000000..f5ce948 --- /dev/null +++ b/node_modules/discord.js/.tern-project @@ -0,0 +1,17 @@ +{ + "ecmaVersion": 7, + "libs": [], + "loadEagerly": ["./src/*.js"], + "dontLoad": ["node_modules/**"], + "plugins": { + "es_modules": {}, + "node": {}, + "doc_comment": { + "fullDocs": true, + "strong": true + }, + "webpack": { + "configPath": "./webpack.config.js" + } + } +} diff --git a/node_modules/discord.js/LICENSE b/node_modules/discord.js/LICENSE new file mode 100644 index 0000000..9997d13 --- /dev/null +++ b/node_modules/discord.js/LICENSE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 - 2020 Amish Shah + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/discord.js/README.md b/node_modules/discord.js/README.md new file mode 100644 index 0000000..cbc2bb0 --- /dev/null +++ b/node_modules/discord.js/README.md @@ -0,0 +1,111 @@ +
+
+

+ discord.js +

+
+

+ Discord server + NPM version + NPM downloads + Build status + Dependencies + Patreon +

+

+ npm installnfo +

+
+ +## Table of contents + +- [About](#about) +- [Installation](#installation) + - [Audio engines](#audio-engines) + - [Optional packages](#optional-packages) +- [Example Usage](#example-usage) +- [Links](#links) + - [Extensions](#extensions) +- [Contributing](#contributing) +- [Help](#help) + +## About + +discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the +[Discord API](https://discord.com/developers/docs/intro). + +- Object-oriented +- Predictable abstractions +- Performant +- 100% coverage of the Discord API + +## Installation + +**Node.js 12.0.0 or newer is required.** +Ignore any warnings about unmet peer dependencies, as they're all optional. + +Without voice support: `npm install discord.js` +With voice support ([@discordjs/opus](https://www.npmjs.com/package/@discordjs/opus)): `npm install discord.js @discordjs/opus` +With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript` + +### Audio engines + +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. +Using opusscript is only recommended for development environments where @discordjs/opus is tough to get working. +For production bots, using @discordjs/opus should be considered a necessity, especially if they're going to be running on multiple servers. + +### Optional packages + +- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`) +- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`) +- One of the following packages can be installed for faster voice packet encryption and decryption: + - [sodium](https://www.npmjs.com/package/sodium) (`npm install sodium`) + - [libsodium.js](https://www.npmjs.com/package/libsodium-wrappers) (`npm install libsodium-wrappers`) +- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`) +- [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`) + +## Example usage + +```js +const Discord = require('discord.js'); +const client = new Discord.Client(); + +client.on('ready', () => { + console.log(`Logged in as ${client.user.tag}!`); +}); + +client.on('message', msg => { + if (msg.content === 'ping') { + msg.reply('pong'); + } +}); + +client.login('token'); +``` + +## Links + +- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website)) +- [Documentation](https://discord.js.org/#/docs/main/master/general/welcome) +- [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide)) - this is still for stable + See also the [Update Guide](https://discordjs.guide/additional-info/changes-in-v12.html), including updated and removed items in the library. +- [Discord.js Discord server](https://discord.gg/bRCvFy9) +- [Discord API Discord server](https://discord.gg/discord-api) +- [GitHub](https://github.com/discordjs/discord.js) +- [NPM](https://www.npmjs.com/package/discord.js) +- [Related libraries](https://discordapi.com/unofficial/libs.html) + +### Extensions + +- [RPC](https://www.npmjs.com/package/discord-rpc) ([source](https://github.com/discordjs/RPC)) + +## Contributing + +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the +[documentation](https://discord.js.org/#/docs). +See [the contribution guide](https://github.com/discordjs/discord.js/blob/master/.github/CONTRIBUTING.md) if you'd like to submit a PR. + +## Help + +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle +nudge in the right direction, please don't hesitate to join our official [Discord.js Server](https://discord.gg/bRCvFy9). diff --git a/node_modules/discord.js/esm/discord.mjs b/node_modules/discord.js/esm/discord.mjs new file mode 100644 index 0000000..8ebf086 --- /dev/null +++ b/node_modules/discord.js/esm/discord.mjs @@ -0,0 +1,95 @@ +import Discord from '../src/index.js'; + +export default Discord; + +export const { + BaseClient, + Client, + Shard, + ShardClientUtil, + ShardingManager, + WebhookClient, + ActivityFlags, + BitField, + Collection, + Constants, + DataResolver, + BaseManager, + DiscordAPIError, + HTTPError, + MessageFlags, + Intents, + Permissions, + Speaking, + Snowflake, + SnowflakeUtil, + Structures, + SystemChannelFlags, + UserFlags, + Util, + version, + ChannelManager, + GuildChannelManager, + GuildEmojiManager, + GuildEmojiRoleManager, + GuildMemberManager, + GuildMemberRoleManager, + GuildManager, + ReactionManager, + ReactionUserManager, + MessageManager, + PresenceManager, + RoleManager, + UserManager, + discordSort, + escapeMarkdown, + fetchRecommendedShards, + resolveColor, + resolveString, + splitMessage, + Application, + Base, + Activity, + APIMessage, + BaseGuildEmoji, + CategoryChannel, + Channel, + ClientApplication, + ClientUser, + Collector, + DMChannel, + Emoji, + Guild, + GuildAuditLogs, + GuildChannel, + GuildEmoji, + GuildMember, + GuildPreview, + GuildTemplate, + Integration, + Invite, + Message, + MessageAttachment, + MessageCollector, + MessageEmbed, + MessageMentions, + MessageReaction, + NewsChannel, + PermissionOverwrites, + Presence, + ClientPresence, + ReactionCollector, + ReactionEmoji, + RichPresenceAssets, + Role, + StoreChannel, + Team, + TeamMember, + TextChannel, + User, + VoiceChannel, + VoiceRegion, + VoiceState, + Webhook, + WebSocket +} = Discord; diff --git a/node_modules/discord.js/jsdoc.json b/node_modules/discord.js/jsdoc.json new file mode 100644 index 0000000..3bf2d09 --- /dev/null +++ b/node_modules/discord.js/jsdoc.json @@ -0,0 +1,3 @@ +{ + "plugins": ["node_modules/jsdoc-strip-async-await"] +} diff --git a/node_modules/discord.js/package.json b/node_modules/discord.js/package.json new file mode 100644 index 0000000..c0ff9ff --- /dev/null +++ b/node_modules/discord.js/package.json @@ -0,0 +1,163 @@ +{ + "name": "discord.js", + "version": "12.5.3", + "description": "A powerful library for interacting with the Discord API", + "main": "./src/index", + "types": "./typings/index.d.ts", + "exports": { + ".": [ + { + "require": "./src/index.js", + "import": "./esm/discord.mjs" + }, + "./src/index.js" + ], + "./esm": "./esm/discord.mjs" + }, + "scripts": { + "test": "npm run lint && npm run docs:test && npm run lint:typings", + "test:typescript": "tsc", + "docs": "docgen --source src --custom docs/index.yml --output docs/docs.json", + "docs:test": "docgen --source src --custom docs/index.yml", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "lint:typings": "tslint typings/index.d.ts", + "prettier": "prettier --write src/**/*.js typings/**/*.ts", + "build:browser": "webpack", + "prepublishOnly": "npm run test && cross-env NODE_ENV=production npm run build:browser" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/discordjs/discord.js.git" + }, + "keywords": [ + "discord", + "api", + "bot", + "client", + "node", + "discordapp" + ], + "author": "Amish Shah ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/discordjs/discord.js/issues" + }, + "homepage": "https://github.com/discordjs/discord.js#readme", + "runkitExampleFilename": "./docs/examples/ping.js", + "unpkg": "./webpack/discord.min.js", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "devDependencies": { + "@commitlint/cli": "^12.0.1", + "@commitlint/config-angular": "^12.0.1", + "@types/node": "^12.12.6", + "@types/ws": "^7.4.0", + "cross-env": "^7.0.3", + "discord.js-docgen": "git+https://github.com/discordjs/docgen.git", + "dtslint": "^4.0.8", + "eslint": "^7.23.0", + "eslint-config-prettier": "^6.13.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-prettier": "^3.3.1", + "husky": "^4.3.0", + "jest": "^26.6.3", + "json-filter-loader": "^1.0.0", + "lint-staged": "^10.5.4", + "prettier": "^2.2.1", + "terser-webpack-plugin": "^4.2.3", + "tslint": "^6.1.3", + "typescript": "^4.2.3", + "webpack": "^4.44.2", + "webpack-cli": "^3.3.12" + }, + "engines": { + "node": ">=12.0.0" + }, + "browser": { + "@discordjs/opus": false, + "https": false, + "ws": false, + "erlpack": false, + "prism-media": false, + "opusscript": false, + "node-opus": false, + "tweetnacl": false, + "sodium": false, + "worker_threads": false, + "zlib-sync": false, + "src/sharding/Shard.js": false, + "src/sharding/ShardClientUtil.js": false, + "src/sharding/ShardingManager.js": false, + "src/client/voice/ClientVoiceManager.js": false, + "src/client/voice/VoiceBroadcast.js": false, + "src/client/voice/VoiceConnection.js": false, + "src/client/voice/dispatcher/BroadcastDispatcher.js": false, + "src/client/voice/dispatcher/StreamDispatcher.js": false, + "src/client/voice/networking/VoiceUDPClient.js": false, + "src/client/voice/networking/VoiceWebSocket.js": false, + "src/client/voice/player/AudioPlayer.js": false, + "src/client/voice/player/BasePlayer.js": false, + "src/client/voice/player/BroadcastAudioPlayer.js": false, + "src/client/voice/receiver/PacketHandler.js": false, + "src/client/voice/receiver/Receiver.js": false, + "src/client/voice/util/PlayInterface.js": false, + "src/client/voice/util/Secretbox.js": false, + "src/client/voice/util/Silence.js": false, + "src/client/voice/util/VolumeInterface.js": false + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged", + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" + } + }, + "lint-staged": { + "*.js": "eslint --fix", + "*.ts": "prettier --write" + }, + "commitlint": { + "extends": [ + "@commitlint/config-angular" + ], + "rules": { + "scope-case": [ + 2, + "always", + "pascal-case" + ], + "type-enum": [ + 2, + "always", + [ + "chore", + "build", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test" + ] + ] + } + }, + "prettier": { + "singleQuote": true, + "printWidth": 120, + "trailingComma": "all", + "endOfLine": "lf", + "arrowParens": "avoid" + } +} diff --git a/node_modules/discord.js/src/WebSocket.js b/node_modules/discord.js/src/WebSocket.js new file mode 100644 index 0000000..90dd51b --- /dev/null +++ b/node_modules/discord.js/src/WebSocket.js @@ -0,0 +1,49 @@ +'use strict'; + +const { browser } = require('./util/Constants'); + +let erlpack; + +try { + erlpack = require('erlpack'); + if (!erlpack.pack) erlpack = null; +} catch {} // eslint-disable-line no-empty + +let TextDecoder; + +if (browser) { + TextDecoder = window.TextDecoder; // eslint-disable-line no-undef + exports.WebSocket = window.WebSocket; // eslint-disable-line no-undef +} else { + TextDecoder = require('util').TextDecoder; + exports.WebSocket = require('ws'); +} + +const ab = new TextDecoder(); + +exports.encoding = erlpack ? 'etf' : 'json'; + +exports.pack = erlpack ? erlpack.pack : JSON.stringify; + +exports.unpack = (data, type) => { + if (exports.encoding === 'json' || type === 'json') { + if (typeof data !== 'string') { + data = ab.decode(data); + } + return JSON.parse(data); + } + if (!Buffer.isBuffer(data)) data = Buffer.from(new Uint8Array(data)); + return erlpack.unpack(data); +}; + +exports.create = (gateway, query = {}, ...args) => { + const [g, q] = gateway.split('?'); + query.encoding = exports.encoding; + query = new URLSearchParams(query); + if (q) new URLSearchParams(q).forEach((v, k) => query.set(k, v)); + const ws = new exports.WebSocket(`${g}?${query}`, ...args); + if (browser) ws.binaryType = 'arraybuffer'; + return ws; +}; + +for (const state of ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']) exports[state] = exports.WebSocket[state]; diff --git a/node_modules/discord.js/src/client/BaseClient.js b/node_modules/discord.js/src/client/BaseClient.js new file mode 100644 index 0000000..29abeca --- /dev/null +++ b/node_modules/discord.js/src/client/BaseClient.js @@ -0,0 +1,169 @@ +'use strict'; + +require('setimmediate'); +const EventEmitter = require('events'); +const RESTManager = require('../rest/RESTManager'); +const { DefaultOptions } = require('../util/Constants'); +const Util = require('../util/Util'); + +/** + * The base class for all clients. + * @extends {EventEmitter} + */ +class BaseClient extends EventEmitter { + constructor(options = {}) { + super(); + + /** + * Timeouts set by {@link BaseClient#setTimeout} that are still active + * @type {Set} + * @private + */ + this._timeouts = new Set(); + + /** + * Intervals set by {@link BaseClient#setInterval} that are still active + * @type {Set} + * @private + */ + this._intervals = new Set(); + + /** + * Intervals set by {@link BaseClient#setImmediate} that are still active + * @type {Set} + * @private + */ + this._immediates = new Set(); + + /** + * The options the client was instantiated with + * @type {ClientOptions} + */ + this.options = Util.mergeDefault(DefaultOptions, options); + + /** + * The REST manager of the client + * @type {RESTManager} + * @private + */ + this.rest = new RESTManager(this, options._tokenType); + } + + /** + * API shortcut + * @type {Object} + * @readonly + * @private + */ + get api() { + return this.rest.api; + } + + /** + * Destroys all assets used by the base client. + */ + destroy() { + for (const t of this._timeouts) this.clearTimeout(t); + for (const i of this._intervals) this.clearInterval(i); + for (const i of this._immediates) this.clearImmediate(i); + this._timeouts.clear(); + this._intervals.clear(); + this._immediates.clear(); + } + + /** + * Sets a timeout that will be automatically cancelled if the client is destroyed. + * @param {Function} fn Function to execute + * @param {number} delay Time to wait before executing (in milliseconds) + * @param {...*} args Arguments for the function + * @returns {Timeout} + */ + setTimeout(fn, delay, ...args) { + const timeout = setTimeout(() => { + fn(...args); + this._timeouts.delete(timeout); + }, delay); + this._timeouts.add(timeout); + return timeout; + } + + /** + * Clears a timeout. + * @param {Timeout} timeout Timeout to cancel + */ + clearTimeout(timeout) { + clearTimeout(timeout); + this._timeouts.delete(timeout); + } + + /** + * Sets an interval that will be automatically cancelled if the client is destroyed. + * @param {Function} fn Function to execute + * @param {number} delay Time to wait between executions (in milliseconds) + * @param {...*} args Arguments for the function + * @returns {Timeout} + */ + setInterval(fn, delay, ...args) { + const interval = setInterval(fn, delay, ...args); + this._intervals.add(interval); + return interval; + } + + /** + * Clears an interval. + * @param {Timeout} interval Interval to cancel + */ + clearInterval(interval) { + clearInterval(interval); + this._intervals.delete(interval); + } + + /** + * Sets an immediate that will be automatically cancelled if the client is destroyed. + * @param {Function} fn Function to execute + * @param {...*} args Arguments for the function + * @returns {Immediate} + */ + setImmediate(fn, ...args) { + const immediate = setImmediate(fn, ...args); + this._immediates.add(immediate); + return immediate; + } + + /** + * Clears an immediate. + * @param {Immediate} immediate Immediate to cancel + */ + clearImmediate(immediate) { + clearImmediate(immediate); + this._immediates.delete(immediate); + } + + /** + * Increments max listeners by one, if they are not zero. + * @private + */ + incrementMaxListeners() { + const maxListeners = this.getMaxListeners(); + if (maxListeners !== 0) { + this.setMaxListeners(maxListeners + 1); + } + } + + /** + * Decrements max listeners by one, if they are not zero. + * @private + */ + decrementMaxListeners() { + const maxListeners = this.getMaxListeners(); + if (maxListeners !== 0) { + this.setMaxListeners(maxListeners - 1); + } + } + + toJSON(...props) { + return Util.flatten(this, { domain: false }, ...props); + } +} + +module.exports = BaseClient; diff --git a/node_modules/discord.js/src/client/Client.js b/node_modules/discord.js/src/client/Client.js new file mode 100644 index 0000000..5847f75 --- /dev/null +++ b/node_modules/discord.js/src/client/Client.js @@ -0,0 +1,504 @@ +'use strict'; + +const BaseClient = require('./BaseClient'); +const ActionsManager = require('./actions/ActionsManager'); +const ClientVoiceManager = require('./voice/ClientVoiceManager'); +const WebSocketManager = require('./websocket/WebSocketManager'); +const { Error, TypeError, RangeError } = require('../errors'); +const ChannelManager = require('../managers/ChannelManager'); +const GuildEmojiManager = require('../managers/GuildEmojiManager'); +const GuildManager = require('../managers/GuildManager'); +const UserManager = require('../managers/UserManager'); +const ShardClientUtil = require('../sharding/ShardClientUtil'); +const ClientApplication = require('../structures/ClientApplication'); +const GuildPreview = require('../structures/GuildPreview'); +const GuildTemplate = require('../structures/GuildTemplate'); +const Invite = require('../structures/Invite'); +const VoiceRegion = require('../structures/VoiceRegion'); +const Webhook = require('../structures/Webhook'); +const Collection = require('../util/Collection'); +const { Events, browser, DefaultOptions } = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); +const Intents = require('../util/Intents'); +const Permissions = require('../util/Permissions'); +const Structures = require('../util/Structures'); + +/** + * The main hub for interacting with the Discord API, and the starting point for any bot. + * @extends {BaseClient} + */ +class Client extends BaseClient { + /** + * @param {ClientOptions} [options] Options for the client + */ + constructor(options = {}) { + super(Object.assign({ _tokenType: 'Bot' }, options)); + + // Obtain shard details from environment or if present, worker threads + let data = process.env; + try { + // Test if worker threads module is present and used + data = require('worker_threads').workerData || data; + } catch { + // Do nothing + } + + if (this.options.shards === DefaultOptions.shards) { + if ('SHARDS' in data) { + this.options.shards = JSON.parse(data.SHARDS); + } + } + + if (this.options.shardCount === DefaultOptions.shardCount) { + if ('SHARD_COUNT' in data) { + this.options.shardCount = Number(data.SHARD_COUNT); + } else if (Array.isArray(this.options.shards)) { + this.options.shardCount = this.options.shards.length; + } + } + + const typeofShards = typeof this.options.shards; + + if (typeofShards === 'undefined' && typeof this.options.shardCount === 'number') { + this.options.shards = Array.from({ length: this.options.shardCount }, (_, i) => i); + } + + if (typeofShards === 'number') this.options.shards = [this.options.shards]; + + if (Array.isArray(this.options.shards)) { + this.options.shards = [ + ...new Set( + this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)), + ), + ]; + } + + this._validateOptions(); + + /** + * The WebSocket manager of the client + * @type {WebSocketManager} + */ + this.ws = new WebSocketManager(this); + + /** + * The action manager of the client + * @type {ActionsManager} + * @private + */ + this.actions = new ActionsManager(this); + + /** + * The voice manager of the client (`null` in browsers) + * @type {?ClientVoiceManager} + */ + this.voice = !browser ? new ClientVoiceManager(this) : null; + + /** + * Shard helpers for the client (only if the process was spawned from a {@link ShardingManager}) + * @type {?ShardClientUtil} + */ + this.shard = + !browser && process.env.SHARDING_MANAGER + ? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE) + : null; + + /** + * All of the {@link User} objects that have been cached at any point, mapped by their IDs + * @type {UserManager} + */ + this.users = new UserManager(this); + + /** + * All of the guilds the client is currently handling, mapped by their IDs - + * as long as sharding isn't being used, this will be *every* guild the bot is a member of + * @type {GuildManager} + */ + this.guilds = new GuildManager(this); + + /** + * All of the {@link Channel}s that the client is currently handling, mapped by their IDs - + * as long as sharding isn't being used, this will be *every* channel in *every* guild the bot + * is a member of. Note that DM channels will not be initially cached, and thus not be present + * in the Manager without their explicit fetching or use. + * @type {ChannelManager} + */ + this.channels = new ChannelManager(this); + + const ClientPresence = Structures.get('ClientPresence'); + /** + * The presence of the Client + * @private + * @type {ClientPresence} + */ + this.presence = new ClientPresence(this); + + Object.defineProperty(this, 'token', { writable: true }); + if (!browser && !this.token && 'DISCORD_TOKEN' in process.env) { + /** + * Authorization token for the logged in bot. + * If present, this defaults to `process.env.DISCORD_TOKEN` when instantiating the client + * This should be kept private at all times. + * @type {?string} + */ + this.token = process.env.DISCORD_TOKEN; + } else { + this.token = null; + } + + /** + * User that the client is logged in as + * @type {?ClientUser} + */ + this.user = null; + + /** + * Time at which the client was last regarded as being in the `READY` state + * (each time the client disconnects and successfully reconnects, this will be overwritten) + * @type {?Date} + */ + this.readyAt = null; + + if (this.options.messageSweepInterval > 0) { + this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000); + } + } + + /** + * All custom emojis that the client has access to, mapped by their IDs + * @type {GuildEmojiManager} + * @readonly + */ + get emojis() { + const emojis = new GuildEmojiManager({ client: this }); + for (const guild of this.guilds.cache.values()) { + if (guild.available) for (const emoji of guild.emojis.cache.values()) emojis.cache.set(emoji.id, emoji); + } + return emojis; + } + + /** + * Timestamp of the time the client was last `READY` at + * @type {?number} + * @readonly + */ + get readyTimestamp() { + return this.readyAt ? this.readyAt.getTime() : null; + } + + /** + * How long it has been since the client last entered the `READY` state in milliseconds + * @type {?number} + * @readonly + */ + get uptime() { + return this.readyAt ? Date.now() - this.readyAt : null; + } + + /** + * Logs the client in, establishing a websocket connection to Discord. + * @param {string} [token=this.token] Token of the account to log in with + * @returns {Promise} Token of the account used + * @example + * client.login('my token'); + */ + async login(token = this.token) { + if (!token || typeof token !== 'string') throw new Error('TOKEN_INVALID'); + this.token = token = token.replace(/^(Bot|Bearer)\s*/i, ''); + this.emit( + Events.DEBUG, + `Provided token: ${token + .split('.') + .map((val, i) => (i > 1 ? val.replace(/./g, '*') : val)) + .join('.')}`, + ); + + if (this.options.presence) { + this.options.ws.presence = await this.presence._parse(this.options.presence); + } + + this.emit(Events.DEBUG, 'Preparing to connect to the gateway...'); + + try { + await this.ws.connect(); + return this.token; + } catch (error) { + this.destroy(); + throw error; + } + } + + /** + * Logs out, terminates the connection to Discord, and destroys the client. + * @returns {void} + */ + destroy() { + super.destroy(); + this.ws.destroy(); + this.token = null; + } + + /** + * Obtains an invite from Discord. + * @param {InviteResolvable} invite Invite code or URL + * @returns {Promise} + * @example + * client.fetchInvite('https://discord.gg/bRCvFy9') + * .then(invite => console.log(`Obtained invite with code: ${invite.code}`)) + * .catch(console.error); + */ + fetchInvite(invite) { + const code = DataResolver.resolveInviteCode(invite); + return this.api + .invites(code) + .get({ query: { with_counts: true } }) + .then(data => new Invite(this, data)); + } + + /** + * Obtains a template from Discord. + * @param {GuildTemplateResolvable} template Template code or URL + * @returns {Promise} + * @example + * client.fetchGuildTemplate('https://discord.new/FKvmczH2HyUf') + * .then(template => console.log(`Obtained template with code: ${template.code}`)) + * .catch(console.error); + */ + fetchGuildTemplate(template) { + const code = DataResolver.resolveGuildTemplateCode(template); + return this.api.guilds + .templates(code) + .get() + .then(data => new GuildTemplate(this, data)); + } + + /** + * Obtains a webhook from Discord. + * @param {Snowflake} id ID of the webhook + * @param {string} [token] Token for the webhook + * @returns {Promise} + * @example + * client.fetchWebhook('id', 'token') + * .then(webhook => console.log(`Obtained webhook with name: ${webhook.name}`)) + * .catch(console.error); + */ + fetchWebhook(id, token) { + return this.api + .webhooks(id, token) + .get() + .then(data => new Webhook(this, data)); + } + + /** + * Obtains the available voice regions from Discord. + * @returns {Promise>} + * @example + * client.fetchVoiceRegions() + * .then(regions => console.log(`Available regions are: ${regions.map(region => region.name).join(', ')}`)) + * .catch(console.error); + */ + fetchVoiceRegions() { + return this.api.voice.regions.get().then(res => { + const regions = new Collection(); + for (const region of res) regions.set(region.id, new VoiceRegion(region)); + return regions; + }); + } + + /** + * Sweeps all text-based channels' messages and removes the ones older than the max message lifetime. + * If the message has been edited, the time of the edit is used rather than the time of the original message. + * @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds) + * will be removed from the caches. The default is based on {@link ClientOptions#messageCacheLifetime} + * @returns {number} Amount of messages that were removed from the caches, + * or -1 if the message cache lifetime is unlimited + * @example + * // Remove all messages older than 1800 seconds from the messages cache + * const amount = client.sweepMessages(1800); + * console.log(`Successfully removed ${amount} messages from the cache.`); + */ + sweepMessages(lifetime = this.options.messageCacheLifetime) { + if (typeof lifetime !== 'number' || isNaN(lifetime)) { + throw new TypeError('INVALID_TYPE', 'lifetime', 'number'); + } + if (lifetime <= 0) { + this.emit(Events.DEBUG, "Didn't sweep messages - lifetime is unlimited"); + return -1; + } + + const lifetimeMs = lifetime * 1000; + const now = Date.now(); + let channels = 0; + let messages = 0; + + for (const channel of this.channels.cache.values()) { + if (!channel.messages) continue; + channels++; + + messages += channel.messages.cache.sweep( + message => now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs, + ); + } + + this.emit( + Events.DEBUG, + `Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`, + ); + return messages; + } + + /** + * Obtains the OAuth Application of this bot from Discord. + * @returns {Promise} + */ + fetchApplication() { + return this.api.oauth2 + .applications('@me') + .get() + .then(app => new ClientApplication(this, app)); + } + + /** + * Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds. + * @param {GuildResolvable} guild The guild to fetch the preview for + * @returns {Promise} + */ + fetchGuildPreview(guild) { + const id = this.guilds.resolveID(guild); + if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable'); + return this.api + .guilds(id) + .preview.get() + .then(data => new GuildPreview(this, data)); + } + + /** + * Generates a link that can be used to invite the bot to a guild. + * @param {InviteGenerationOptions|PermissionResolvable} [options] Permissions to request + * @returns {Promise} + * @example + * client.generateInvite({ + * permissions: ['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE'], + * }) + * .then(link => console.log(`Generated bot invite link: ${link}`)) + * .catch(console.error); + */ + async generateInvite(options = {}) { + if (Array.isArray(options) || ['string', 'number'].includes(typeof options) || options instanceof Permissions) { + process.emitWarning( + 'Client#generateInvite: Generate invite with an options object instead of a PermissionResolvable', + 'DeprecationWarning', + ); + options = { permissions: options }; + } + const application = await this.fetchApplication(); + const query = new URLSearchParams({ + client_id: application.id, + permissions: Permissions.resolve(options.permissions), + scope: 'bot', + }); + if (typeof options.disableGuildSelect === 'boolean') { + query.set('disable_guild_select', options.disableGuildSelect.toString()); + } + if (typeof options.guild !== 'undefined') { + const guildID = this.guilds.resolveID(options.guild); + if (!guildID) throw new TypeError('INVALID_TYPE', 'options.guild', 'GuildResolvable'); + query.set('guild_id', guildID); + } + return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; + } + + toJSON() { + return super.toJSON({ + readyAt: false, + }); + } + + /** + * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script + * with the client as `this`. + * @param {string} script Script to eval + * @returns {*} + * @private + */ + _eval(script) { + return eval(script); + } + + /** + * Validates the client options. + * @param {ClientOptions} [options=this.options] Options to validate + * @private + */ + _validateOptions(options = this.options) { + if (typeof options.ws.intents !== 'undefined') { + options.ws.intents = Intents.resolve(options.ws.intents); + } + if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) { + throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1'); + } + if (options.shards && !(options.shards === 'auto' || Array.isArray(options.shards))) { + throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers"); + } + if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS'); + if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'messageCacheMaxSize', 'a number'); + } + if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'The messageCacheLifetime', 'a number'); + } + if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'messageSweepInterval', 'a number'); + } + if ( + typeof options.messageEditHistoryMaxSize !== 'number' || + isNaN(options.messageEditHistoryMaxSize) || + options.messageEditHistoryMaxSize < -1 + ) { + throw new TypeError('CLIENT_INVALID_OPTION', 'messageEditHistoryMaxSize', 'a number greater than or equal to -1'); + } + if (typeof options.fetchAllMembers !== 'boolean') { + throw new TypeError('CLIENT_INVALID_OPTION', 'fetchAllMembers', 'a boolean'); + } + if (typeof options.disableMentions !== 'string') { + throw new TypeError('CLIENT_INVALID_OPTION', 'disableMentions', 'a string'); + } + if (!Array.isArray(options.partials)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array'); + } + if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'restWsBridgeTimeout', 'a number'); + } + if (typeof options.restRequestTimeout !== 'number' || isNaN(options.restRequestTimeout)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'restRequestTimeout', 'a number'); + } + if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number'); + } + if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number'); + } + } +} + +module.exports = Client; + +/** + * Options for {@link Client#generateInvite}. + * @typedef {Object} InviteGenerationOptions + * @property {PermissionResolvable} [permissions] Permissions to request + * @property {GuildResolvable} [guild] Guild to preselect + * @property {boolean} [disableGuildSelect] Whether to disable the guild selection + */ + +/** + * Emitted for general warnings. + * @event Client#warn + * @param {string} info The warning + */ + +/** + * Emitted for general debugging information. + * @event Client#debug + * @param {string} info The debug information + */ diff --git a/node_modules/discord.js/src/client/WebhookClient.js b/node_modules/discord.js/src/client/WebhookClient.js new file mode 100644 index 0000000..cea6631 --- /dev/null +++ b/node_modules/discord.js/src/client/WebhookClient.js @@ -0,0 +1,31 @@ +'use strict'; + +const BaseClient = require('./BaseClient'); +const Webhook = require('../structures/Webhook'); + +/** + * The webhook client. + * @implements {Webhook} + * @extends {BaseClient} + */ +class WebhookClient extends BaseClient { + /** + * @param {Snowflake} id ID of the webhook + * @param {string} token Token of the webhook + * @param {ClientOptions} [options] Options for the client + * @example + * // Create a new webhook and send a message + * const hook = new Discord.WebhookClient('1234', 'abcdef'); + * hook.send('This will send a message').catch(console.error); + */ + constructor(id, token, options) { + super(options); + Object.defineProperty(this, 'client', { value: this }); + this.id = id; + Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true }); + } +} + +Webhook.applyToClass(WebhookClient); + +module.exports = WebhookClient; diff --git a/node_modules/discord.js/src/client/actions/Action.js b/node_modules/discord.js/src/client/actions/Action.js new file mode 100644 index 0000000..69e3b63 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/Action.js @@ -0,0 +1,105 @@ +'use strict'; + +const { PartialTypes } = require('../../util/Constants'); + +/* + +ABOUT ACTIONS + +Actions are similar to WebSocket Packet Handlers, but since introducing +the REST API methods, in order to prevent rewriting code to handle data, +"actions" have been introduced. They're basically what Packet Handlers +used to be but they're strictly for manipulating data and making sure +that WebSocket events don't clash with REST methods. + +*/ + +class GenericAction { + constructor(client) { + this.client = client; + } + + handle(data) { + return data; + } + + getPayload(data, manager, id, partialType, cache) { + const existing = manager.cache.get(id); + if (!existing && this.client.options.partials.includes(partialType)) { + return manager.add(data, cache); + } + return existing; + } + + getChannel(data) { + const id = data.channel_id || data.id; + return ( + data.channel || + this.getPayload( + { + id, + guild_id: data.guild_id, + recipients: [data.author || { id: data.user_id }], + }, + this.client.channels, + id, + PartialTypes.CHANNEL, + ) + ); + } + + getMessage(data, channel, cache) { + const id = data.message_id || data.id; + return ( + data.message || + this.getPayload( + { + id, + channel_id: channel.id, + guild_id: data.guild_id || (channel.guild ? channel.guild.id : null), + }, + channel.messages, + id, + PartialTypes.MESSAGE, + cache, + ) + ); + } + + getReaction(data, message, user) { + const id = data.emoji.id || decodeURIComponent(data.emoji.name); + return this.getPayload( + { + emoji: data.emoji, + count: message.partial ? null : 0, + me: user ? user.id === this.client.user.id : false, + }, + message.reactions, + id, + PartialTypes.REACTION, + ); + } + + getMember(data, guild) { + return this.getPayload(data, guild.members, data.user.id, PartialTypes.GUILD_MEMBER); + } + + getUser(data) { + const id = data.user_id; + return data.user || this.getPayload({ id }, this.client.users, id, PartialTypes.USER); + } + + getUserFromMember(data) { + if (data.guild_id && data.member && data.member.user) { + const guild = this.client.guilds.cache.get(data.guild_id); + if (guild) { + return guild.members.add(data.member).user; + } else { + return this.client.users.add(data.member.user); + } + } + return this.getUser(data); + } +} + +module.exports = GenericAction; diff --git a/node_modules/discord.js/src/client/actions/ActionsManager.js b/node_modules/discord.js/src/client/actions/ActionsManager.js new file mode 100644 index 0000000..4055795 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/ActionsManager.js @@ -0,0 +1,47 @@ +'use strict'; + +class ActionsManager { + constructor(client) { + this.client = client; + + this.register(require('./MessageCreate')); + this.register(require('./MessageDelete')); + this.register(require('./MessageDeleteBulk')); + this.register(require('./MessageUpdate')); + this.register(require('./MessageReactionAdd')); + this.register(require('./MessageReactionRemove')); + this.register(require('./MessageReactionRemoveAll')); + this.register(require('./MessageReactionRemoveEmoji')); + this.register(require('./ChannelCreate')); + this.register(require('./ChannelDelete')); + this.register(require('./ChannelUpdate')); + this.register(require('./GuildDelete')); + this.register(require('./GuildUpdate')); + this.register(require('./InviteCreate')); + this.register(require('./InviteDelete')); + this.register(require('./GuildMemberRemove')); + this.register(require('./GuildMemberUpdate')); + this.register(require('./GuildBanRemove')); + this.register(require('./GuildRoleCreate')); + this.register(require('./GuildRoleDelete')); + this.register(require('./GuildRoleUpdate')); + this.register(require('./PresenceUpdate')); + this.register(require('./UserUpdate')); + this.register(require('./VoiceStateUpdate')); + this.register(require('./GuildEmojiCreate')); + this.register(require('./GuildEmojiDelete')); + this.register(require('./GuildEmojiUpdate')); + this.register(require('./GuildEmojisUpdate')); + this.register(require('./GuildRolesPositionUpdate')); + this.register(require('./GuildChannelsPositionUpdate')); + this.register(require('./GuildIntegrationsUpdate')); + this.register(require('./WebhooksUpdate')); + this.register(require('./TypingStart')); + } + + register(Action) { + this[Action.name.replace(/Action$/, '')] = new Action(this.client); + } +} + +module.exports = ActionsManager; diff --git a/node_modules/discord.js/src/client/actions/ChannelCreate.js b/node_modules/discord.js/src/client/actions/ChannelCreate.js new file mode 100644 index 0000000..fa60a0b --- /dev/null +++ b/node_modules/discord.js/src/client/actions/ChannelCreate.js @@ -0,0 +1,23 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class ChannelCreateAction extends Action { + handle(data) { + const client = this.client; + const existing = client.channels.cache.has(data.id); + const channel = client.channels.add(data); + if (!existing && channel) { + /** + * Emitted whenever a channel is created. + * @event Client#channelCreate + * @param {DMChannel|GuildChannel} channel The channel that was created + */ + client.emit(Events.CHANNEL_CREATE, channel); + } + return { channel }; + } +} + +module.exports = ChannelCreateAction; diff --git a/node_modules/discord.js/src/client/actions/ChannelDelete.js b/node_modules/discord.js/src/client/actions/ChannelDelete.js new file mode 100644 index 0000000..2956d72 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/ChannelDelete.js @@ -0,0 +1,37 @@ +'use strict'; + +const Action = require('./Action'); +const DMChannel = require('../../structures/DMChannel'); +const { Events } = require('../../util/Constants'); + +class ChannelDeleteAction extends Action { + constructor(client) { + super(client); + this.deleted = new Map(); + } + + handle(data) { + const client = this.client; + let channel = client.channels.cache.get(data.id); + + if (channel) { + client.channels.remove(channel.id); + channel.deleted = true; + if (channel.messages && !(channel instanceof DMChannel)) { + for (const message of channel.messages.cache.values()) { + message.deleted = true; + } + } + /** + * Emitted whenever a channel is deleted. + * @event Client#channelDelete + * @param {DMChannel|GuildChannel} channel The channel that was deleted + */ + client.emit(Events.CHANNEL_DELETE, channel); + } + + return { channel }; + } +} + +module.exports = ChannelDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/ChannelUpdate.js b/node_modules/discord.js/src/client/actions/ChannelUpdate.js new file mode 100644 index 0000000..06bb71b --- /dev/null +++ b/node_modules/discord.js/src/client/actions/ChannelUpdate.js @@ -0,0 +1,33 @@ +'use strict'; + +const Action = require('./Action'); +const Channel = require('../../structures/Channel'); +const { ChannelTypes } = require('../../util/Constants'); + +class ChannelUpdateAction extends Action { + handle(data) { + const client = this.client; + + let channel = client.channels.cache.get(data.id); + if (channel) { + const old = channel._update(data); + + if (ChannelTypes[channel.type.toUpperCase()] !== data.type) { + const newChannel = Channel.create(this.client, data, channel.guild); + for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message); + newChannel._typing = new Map(channel._typing); + channel = newChannel; + this.client.channels.cache.set(channel.id, channel); + } + + return { + old, + updated: channel, + }; + } + + return {}; + } +} + +module.exports = ChannelUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildBanRemove.js b/node_modules/discord.js/src/client/actions/GuildBanRemove.js new file mode 100644 index 0000000..fc28e11 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildBanRemove.js @@ -0,0 +1,21 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildBanRemove extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + const user = client.users.add(data.user); + /** + * Emitted whenever a member is unbanned from a guild. + * @event Client#guildBanRemove + * @param {Guild} guild The guild that the unban occurred in + * @param {User} user The user that was unbanned + */ + if (guild && user) client.emit(Events.GUILD_BAN_REMOVE, guild, user); + } +} + +module.exports = GuildBanRemove; diff --git a/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js b/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js new file mode 100644 index 0000000..a393167 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js @@ -0,0 +1,21 @@ +'use strict'; + +const Action = require('./Action'); + +class GuildChannelsPositionUpdate extends Action { + handle(data) { + const client = this.client; + + const guild = client.guilds.cache.get(data.guild_id); + if (guild) { + for (const partialChannel of data.channels) { + const channel = guild.channels.cache.get(partialChannel.id); + if (channel) channel.rawPosition = partialChannel.position; + } + } + + return { guild }; + } +} + +module.exports = GuildChannelsPositionUpdate; diff --git a/node_modules/discord.js/src/client/actions/GuildDelete.js b/node_modules/discord.js/src/client/actions/GuildDelete.js new file mode 100644 index 0000000..8bb630f --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildDelete.js @@ -0,0 +1,67 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildDeleteAction extends Action { + constructor(client) { + super(client); + this.deleted = new Map(); + } + + handle(data) { + const client = this.client; + + let guild = client.guilds.cache.get(data.id); + if (guild) { + for (const channel of guild.channels.cache.values()) { + if (channel.type === 'text') channel.stopTyping(true); + } + + if (data.unavailable) { + // Guild is unavailable + guild.available = false; + + /** + * Emitted whenever a guild becomes unavailable, likely due to a server outage. + * @event Client#guildUnavailable + * @param {Guild} guild The guild that has become unavailable + */ + client.emit(Events.GUILD_UNAVAILABLE, guild); + + // Stops the GuildDelete packet thinking a guild was actually deleted, + // handles emitting of event itself + return { + guild: null, + }; + } + + for (const channel of guild.channels.cache.values()) this.client.channels.remove(channel.id); + if (guild.voice && guild.voice.connection) guild.voice.connection.disconnect(); + + // Delete guild + client.guilds.cache.delete(guild.id); + guild.deleted = true; + + /** + * Emitted whenever a guild kicks the client or the guild is deleted/left. + * @event Client#guildDelete + * @param {Guild} guild The guild that was deleted + */ + client.emit(Events.GUILD_DELETE, guild); + + this.deleted.set(guild.id, guild); + this.scheduleForDeletion(guild.id); + } else { + guild = this.deleted.get(data.id) || null; + } + + return { guild }; + } + + scheduleForDeletion(id) { + this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout); + } +} + +module.exports = GuildDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js new file mode 100644 index 0000000..f47ddd5 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js @@ -0,0 +1,20 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildEmojiCreateAction extends Action { + handle(guild, createdEmoji) { + const already = guild.emojis.cache.has(createdEmoji.id); + const emoji = guild.emojis.add(createdEmoji); + /** + * Emitted whenever a custom emoji is created in a guild. + * @event Client#emojiCreate + * @param {GuildEmoji} emoji The emoji that was created + */ + if (!already) this.client.emit(Events.GUILD_EMOJI_CREATE, emoji); + return { emoji }; + } +} + +module.exports = GuildEmojiCreateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js b/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js new file mode 100644 index 0000000..42af70c --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js @@ -0,0 +1,20 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildEmojiDeleteAction extends Action { + handle(emoji) { + emoji.guild.emojis.cache.delete(emoji.id); + emoji.deleted = true; + /** + * Emitted whenever a custom emoji is deleted in a guild. + * @event Client#emojiDelete + * @param {GuildEmoji} emoji The emoji that was deleted + */ + this.client.emit(Events.GUILD_EMOJI_DELETE, emoji); + return { emoji }; + } +} + +module.exports = GuildEmojiDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js b/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js new file mode 100644 index 0000000..9fa59c9 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js @@ -0,0 +1,20 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildEmojiUpdateAction extends Action { + handle(current, data) { + const old = current._update(data); + /** + * Emitted whenever a custom emoji is updated in a guild. + * @event Client#emojiUpdate + * @param {GuildEmoji} oldEmoji The old emoji + * @param {GuildEmoji} newEmoji The new emoji + */ + this.client.emit(Events.GUILD_EMOJI_UPDATE, old, current); + return { emoji: current }; + } +} + +module.exports = GuildEmojiUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js new file mode 100644 index 0000000..7711933 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js @@ -0,0 +1,34 @@ +'use strict'; + +const Action = require('./Action'); + +class GuildEmojisUpdateAction extends Action { + handle(data) { + const guild = this.client.guilds.cache.get(data.guild_id); + if (!guild || !guild.emojis) return; + + const deletions = new Map(guild.emojis.cache); + + for (const emoji of data.emojis) { + // Determine type of emoji event + const cachedEmoji = guild.emojis.cache.get(emoji.id); + if (cachedEmoji) { + deletions.delete(emoji.id); + if (!cachedEmoji.equals(emoji)) { + // Emoji updated + this.client.actions.GuildEmojiUpdate.handle(cachedEmoji, emoji); + } + } else { + // Emoji added + this.client.actions.GuildEmojiCreate.handle(guild, emoji); + } + } + + for (const emoji of deletions.values()) { + // Emoji deleted + this.client.actions.GuildEmojiDelete.handle(emoji); + } + } +} + +module.exports = GuildEmojisUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js b/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js new file mode 100644 index 0000000..bbce076 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js @@ -0,0 +1,19 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildIntegrationsUpdate extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + /** + * Emitted whenever a guild integration is updated + * @event Client#guildIntegrationsUpdate + * @param {Guild} guild The guild whose integrations were updated + */ + if (guild) client.emit(Events.GUILD_INTEGRATIONS_UPDATE, guild); + } +} + +module.exports = GuildIntegrationsUpdate; diff --git a/node_modules/discord.js/src/client/actions/GuildMemberRemove.js b/node_modules/discord.js/src/client/actions/GuildMemberRemove.js new file mode 100644 index 0000000..b690446 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildMemberRemove.js @@ -0,0 +1,30 @@ +'use strict'; + +const Action = require('./Action'); +const { Events, Status } = require('../../util/Constants'); + +class GuildMemberRemoveAction extends Action { + handle(data, shard) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + let member = null; + if (guild) { + member = this.getMember({ user: data.user }, guild); + guild.memberCount--; + if (member) { + member.deleted = true; + guild.members.cache.delete(member.id); + /** + * Emitted whenever a member leaves a guild, or is kicked. + * @event Client#guildMemberRemove + * @param {GuildMember} member The member that has left/been kicked from the guild + */ + if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_REMOVE, member); + } + guild.voiceStates.cache.delete(data.user.id); + } + return { guild, member }; + } +} + +module.exports = GuildMemberRemoveAction; diff --git a/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js b/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js new file mode 100644 index 0000000..53ca481 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js @@ -0,0 +1,44 @@ +'use strict'; + +const Action = require('./Action'); +const { Status, Events } = require('../../util/Constants'); + +class GuildMemberUpdateAction extends Action { + handle(data, shard) { + const { client } = this; + if (data.user.username) { + const user = client.users.cache.get(data.user.id); + if (!user) { + client.users.add(data.user); + } else if (!user.equals(data.user)) { + client.actions.UserUpdate.handle(data.user); + } + } + + const guild = client.guilds.cache.get(data.guild_id); + if (guild) { + const member = this.getMember({ user: data.user }, guild); + if (member) { + const old = member._update(data); + /** + * Emitted whenever a guild member changes - i.e. new role, removed role, nickname. + * Also emitted when the user's details (e.g. username) change. + * @event Client#guildMemberUpdate + * @param {GuildMember} oldMember The member before the update + * @param {GuildMember} newMember The member after the update + */ + if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_UPDATE, old, member); + } else { + const newMember = guild.members.add(data); + /** + * Emitted whenever a member becomes available in a large guild. + * @event Client#guildMemberAvailable + * @param {GuildMember} member The member that became available + */ + this.client.emit(Events.GUILD_MEMBER_AVAILABLE, newMember); + } + } + } +} + +module.exports = GuildMemberUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildRoleCreate.js b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js new file mode 100644 index 0000000..d7d5214 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js @@ -0,0 +1,25 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildRoleCreate extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + let role; + if (guild) { + const already = guild.roles.cache.has(data.role.id); + role = guild.roles.add(data.role); + /** + * Emitted whenever a role is created. + * @event Client#roleCreate + * @param {Role} role The role that was created + */ + if (!already) client.emit(Events.GUILD_ROLE_CREATE, role); + } + return { role }; + } +} + +module.exports = GuildRoleCreate; diff --git a/node_modules/discord.js/src/client/actions/GuildRoleDelete.js b/node_modules/discord.js/src/client/actions/GuildRoleDelete.js new file mode 100644 index 0000000..51754b3 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildRoleDelete.js @@ -0,0 +1,30 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildRoleDeleteAction extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + let role; + + if (guild) { + role = guild.roles.cache.get(data.role_id); + if (role) { + guild.roles.cache.delete(data.role_id); + role.deleted = true; + /** + * Emitted whenever a guild role is deleted. + * @event Client#roleDelete + * @param {Role} role The role that was deleted + */ + client.emit(Events.GUILD_ROLE_DELETE, role); + } + } + + return { role }; + } +} + +module.exports = GuildRoleDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js b/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js new file mode 100644 index 0000000..faea120 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js @@ -0,0 +1,39 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildRoleUpdateAction extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + + if (guild) { + let old = null; + + const role = guild.roles.cache.get(data.role.id); + if (role) { + old = role._update(data.role); + /** + * Emitted whenever a guild role is updated. + * @event Client#roleUpdate + * @param {Role} oldRole The role before the update + * @param {Role} newRole The role after the update + */ + client.emit(Events.GUILD_ROLE_UPDATE, old, role); + } + + return { + old, + updated: role, + }; + } + + return { + old: null, + updated: null, + }; + } +} + +module.exports = GuildRoleUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js b/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js new file mode 100644 index 0000000..d7abca9 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js @@ -0,0 +1,21 @@ +'use strict'; + +const Action = require('./Action'); + +class GuildRolesPositionUpdate extends Action { + handle(data) { + const client = this.client; + + const guild = client.guilds.cache.get(data.guild_id); + if (guild) { + for (const partialRole of data.roles) { + const role = guild.roles.cache.get(partialRole.id); + if (role) role.rawPosition = partialRole.position; + } + } + + return { guild }; + } +} + +module.exports = GuildRolesPositionUpdate; diff --git a/node_modules/discord.js/src/client/actions/GuildUpdate.js b/node_modules/discord.js/src/client/actions/GuildUpdate.js new file mode 100644 index 0000000..78a8afb --- /dev/null +++ b/node_modules/discord.js/src/client/actions/GuildUpdate.js @@ -0,0 +1,33 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class GuildUpdateAction extends Action { + handle(data) { + const client = this.client; + + const guild = client.guilds.cache.get(data.id); + if (guild) { + const old = guild._update(data); + /** + * Emitted whenever a guild is updated - e.g. name change. + * @event Client#guildUpdate + * @param {Guild} oldGuild The guild before the update + * @param {Guild} newGuild The guild after the update + */ + client.emit(Events.GUILD_UPDATE, old, guild); + return { + old, + updated: guild, + }; + } + + return { + old: null, + updated: null, + }; + } +} + +module.exports = GuildUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/InviteCreate.js b/node_modules/discord.js/src/client/actions/InviteCreate.js new file mode 100644 index 0000000..34cfa84 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/InviteCreate.js @@ -0,0 +1,28 @@ +'use strict'; + +const Action = require('./Action'); +const Invite = require('../../structures/Invite'); +const { Events } = require('../../util/Constants'); + +class InviteCreateAction extends Action { + handle(data) { + const client = this.client; + const channel = client.channels.cache.get(data.channel_id); + const guild = client.guilds.cache.get(data.guild_id); + if (!channel) return false; + + const inviteData = Object.assign(data, { channel, guild }); + const invite = new Invite(client, inviteData); + /** + * Emitted when an invite is created. + * This event only triggers if the client has `MANAGE_GUILD` permissions for the guild, + * or `MANAGE_CHANNEL` permissions for the channel. + * @event Client#inviteCreate + * @param {Invite} invite The invite that was created + */ + client.emit(Events.INVITE_CREATE, invite); + return { invite }; + } +} + +module.exports = InviteCreateAction; diff --git a/node_modules/discord.js/src/client/actions/InviteDelete.js b/node_modules/discord.js/src/client/actions/InviteDelete.js new file mode 100644 index 0000000..96e22aa --- /dev/null +++ b/node_modules/discord.js/src/client/actions/InviteDelete.js @@ -0,0 +1,29 @@ +'use strict'; + +const Action = require('./Action'); +const Invite = require('../../structures/Invite'); +const { Events } = require('../../util/Constants'); + +class InviteDeleteAction extends Action { + handle(data) { + const client = this.client; + const channel = client.channels.cache.get(data.channel_id); + const guild = client.guilds.cache.get(data.guild_id); + if (!channel) return false; + + const inviteData = Object.assign(data, { channel, guild }); + const invite = new Invite(client, inviteData); + + /** + * Emitted when an invite is deleted. + * This event only triggers if the client has `MANAGE_GUILD` permissions for the guild, + * or `MANAGE_CHANNEL` permissions for the channel. + * @event Client#inviteDelete + * @param {Invite} invite The invite that was deleted + */ + client.emit(Events.INVITE_DELETE, invite); + return { invite }; + } +} + +module.exports = InviteDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/MessageCreate.js b/node_modules/discord.js/src/client/actions/MessageCreate.js new file mode 100644 index 0000000..7138707 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageCreate.js @@ -0,0 +1,39 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class MessageCreateAction extends Action { + handle(data) { + const client = this.client; + const channel = client.channels.cache.get(data.channel_id); + if (channel) { + const existing = channel.messages.cache.get(data.id); + if (existing) return { message: existing }; + const message = channel.messages.add(data); + const user = message.author; + let member = message.member; + channel.lastMessageID = data.id; + if (user) { + user.lastMessageID = data.id; + user.lastMessageChannelID = channel.id; + } + if (member) { + member.lastMessageID = data.id; + member.lastMessageChannelID = channel.id; + } + + /** + * Emitted whenever a message is created. + * @event Client#message + * @param {Message} message The created message + */ + client.emit(Events.MESSAGE_CREATE, message); + return { message }; + } + + return {}; + } +} + +module.exports = MessageCreateAction; diff --git a/node_modules/discord.js/src/client/actions/MessageDelete.js b/node_modules/discord.js/src/client/actions/MessageDelete.js new file mode 100644 index 0000000..0210625 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageDelete.js @@ -0,0 +1,29 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class MessageDeleteAction extends Action { + handle(data) { + const client = this.client; + const channel = this.getChannel(data); + let message; + if (channel) { + message = this.getMessage(data, channel); + if (message) { + channel.messages.cache.delete(message.id); + message.deleted = true; + /** + * Emitted whenever a message is deleted. + * @event Client#messageDelete + * @param {Message} message The deleted message + */ + client.emit(Events.MESSAGE_DELETE, message); + } + } + + return { message }; + } +} + +module.exports = MessageDeleteAction; diff --git a/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js new file mode 100644 index 0000000..8686b1d --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js @@ -0,0 +1,43 @@ +'use strict'; + +const Action = require('./Action'); +const Collection = require('../../util/Collection'); +const { Events } = require('../../util/Constants'); + +class MessageDeleteBulkAction extends Action { + handle(data) { + const client = this.client; + const channel = client.channels.cache.get(data.channel_id); + + if (channel) { + const ids = data.ids; + const messages = new Collection(); + for (const id of ids) { + const message = this.getMessage( + { + id, + guild_id: data.guild_id, + }, + channel, + false, + ); + if (message) { + message.deleted = true; + messages.set(message.id, message); + channel.messages.cache.delete(id); + } + } + + /** + * Emitted whenever messages are deleted in bulk. + * @event Client#messageDeleteBulk + * @param {Collection} messages The deleted messages, mapped by their ID + */ + if (messages.size > 0) client.emit(Events.MESSAGE_BULK_DELETE, messages); + return { messages }; + } + return {}; + } +} + +module.exports = MessageDeleteBulkAction; diff --git a/node_modules/discord.js/src/client/actions/MessageReactionAdd.js b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js new file mode 100644 index 0000000..c7b0151 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js @@ -0,0 +1,55 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); +const { PartialTypes } = require('../../util/Constants'); + +/* +{ user_id: 'id', + message_id: 'id', + emoji: { name: '�', id: null }, + channel_id: 'id', + // If originating from a guild + guild_id: 'id', + member: { ..., user: { ... } } } +*/ + +class MessageReactionAdd extends Action { + handle(data) { + if (!data.emoji) return false; + + const user = this.getUserFromMember(data); + if (!user) return false; + + // Verify channel + const channel = this.getChannel(data); + if (!channel || channel.type === 'voice') return false; + + // Verify message + const message = this.getMessage(data, channel); + if (!message) return false; + + // Verify reaction + if (message.partial && !this.client.options.partials.includes(PartialTypes.REACTION)) return false; + const existing = message.reactions.cache.get(data.emoji.id || data.emoji.name); + if (existing && existing.users.cache.has(user.id)) return { message, reaction: existing, user }; + const reaction = message.reactions.add({ + emoji: data.emoji, + count: message.partial ? null : 0, + me: user.id === this.client.user.id, + }); + if (!reaction) return false; + reaction._add(user); + /** + * Emitted whenever a reaction is added to a cached message. + * @event Client#messageReactionAdd + * @param {MessageReaction} messageReaction The reaction object + * @param {User} user The user that applied the guild or reaction emoji + */ + this.client.emit(Events.MESSAGE_REACTION_ADD, reaction, user); + + return { message, reaction, user }; + } +} + +module.exports = MessageReactionAdd; diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemove.js b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js new file mode 100644 index 0000000..8740246 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js @@ -0,0 +1,45 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +/* +{ user_id: 'id', + message_id: 'id', + emoji: { name: '�', id: null }, + channel_id: 'id', + guild_id: 'id' } +*/ + +class MessageReactionRemove extends Action { + handle(data) { + if (!data.emoji) return false; + + const user = this.getUser(data); + if (!user) return false; + + // Verify channel + const channel = this.getChannel(data); + if (!channel || channel.type === 'voice') return false; + + // Verify message + const message = this.getMessage(data, channel); + if (!message) return false; + + // Verify reaction + const reaction = this.getReaction(data, message, user); + if (!reaction) return false; + reaction._remove(user); + /** + * Emitted whenever a reaction is removed from a cached message. + * @event Client#messageReactionRemove + * @param {MessageReaction} messageReaction The reaction object + * @param {User} user The user whose emoji or reaction emoji was removed + */ + this.client.emit(Events.MESSAGE_REACTION_REMOVE, reaction, user); + + return { message, reaction, user }; + } +} + +module.exports = MessageReactionRemove; diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js new file mode 100644 index 0000000..14b79bf --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js @@ -0,0 +1,29 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class MessageReactionRemoveAll extends Action { + handle(data) { + // Verify channel + const channel = this.getChannel(data); + if (!channel || channel.type === 'voice') return false; + + // Verify message + const message = this.getMessage(data, channel); + if (!message) return false; + + message.reactions.cache.clear(); + this.client.emit(Events.MESSAGE_REACTION_REMOVE_ALL, message); + + return { message }; + } +} + +/** + * Emitted whenever all reactions are removed from a cached message. + * @event Client#messageReactionRemoveAll + * @param {Message} message The message the reactions were removed from + */ + +module.exports = MessageReactionRemoveAll; diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js new file mode 100644 index 0000000..143702c --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js @@ -0,0 +1,28 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class MessageReactionRemoveEmoji extends Action { + handle(data) { + const channel = this.getChannel(data); + if (!channel || channel.type === 'voice') return false; + + const message = this.getMessage(data, channel); + if (!message) return false; + + const reaction = this.getReaction(data, message); + if (!reaction) return false; + if (!message.partial) message.reactions.cache.delete(reaction.emoji.id || reaction.emoji.name); + + /** + * Emitted when a bot removes an emoji reaction from a cached message. + * @event Client#messageReactionRemoveEmoji + * @param {MessageReaction} reaction The reaction that was removed + */ + this.client.emit(Events.MESSAGE_REACTION_REMOVE_EMOJI, reaction); + return { reaction }; + } +} + +module.exports = MessageReactionRemoveEmoji; diff --git a/node_modules/discord.js/src/client/actions/MessageUpdate.js b/node_modules/discord.js/src/client/actions/MessageUpdate.js new file mode 100644 index 0000000..7667dea --- /dev/null +++ b/node_modules/discord.js/src/client/actions/MessageUpdate.js @@ -0,0 +1,24 @@ +'use strict'; + +const Action = require('./Action'); + +class MessageUpdateAction extends Action { + handle(data) { + const channel = this.getChannel(data); + if (channel) { + const { id, channel_id, guild_id, author, timestamp, type } = data; + const message = this.getMessage({ id, channel_id, guild_id, author, timestamp, type }, channel); + if (message) { + const old = message.patch(data); + return { + old, + updated: message, + }; + } + } + + return {}; + } +} + +module.exports = MessageUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/PresenceUpdate.js b/node_modules/discord.js/src/client/actions/PresenceUpdate.js new file mode 100644 index 0000000..f74fbeb --- /dev/null +++ b/node_modules/discord.js/src/client/actions/PresenceUpdate.js @@ -0,0 +1,44 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class PresenceUpdateAction extends Action { + handle(data) { + let user = this.client.users.cache.get(data.user.id); + if (!user && data.user.username) user = this.client.users.add(data.user); + if (!user) return; + + if (data.user && data.user.username) { + if (!user.equals(data.user)) this.client.actions.UserUpdate.handle(data.user); + } + + const guild = this.client.guilds.cache.get(data.guild_id); + if (!guild) return; + + let oldPresence = guild.presences.cache.get(user.id); + if (oldPresence) oldPresence = oldPresence._clone(); + let member = guild.members.cache.get(user.id); + if (!member && data.status !== 'offline') { + member = guild.members.add({ + user, + roles: data.roles, + deaf: false, + mute: false, + }); + this.client.emit(Events.GUILD_MEMBER_AVAILABLE, member); + } + guild.presences.add(Object.assign(data, { guild })); + if (member && this.client.listenerCount(Events.PRESENCE_UPDATE)) { + /** + * Emitted whenever a guild member's presence (e.g. status, activity) is changed. + * @event Client#presenceUpdate + * @param {?Presence} oldPresence The presence before the update, if one at all + * @param {Presence} newPresence The presence after the update + */ + this.client.emit(Events.PRESENCE_UPDATE, oldPresence, member.presence); + } + } +} + +module.exports = PresenceUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/TypingStart.js b/node_modules/discord.js/src/client/actions/TypingStart.js new file mode 100644 index 0000000..7a35bc3 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/TypingStart.js @@ -0,0 +1,58 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); +const textBasedChannelTypes = ['dm', 'text', 'news']; + +class TypingStart extends Action { + handle(data) { + const channel = this.getChannel(data); + if (!channel) { + return; + } + if (!textBasedChannelTypes.includes(channel.type)) { + this.client.emit(Events.WARN, `Discord sent a typing packet to a ${channel.type} channel ${channel.id}`); + return; + } + + const user = this.getUserFromMember(data); + const timestamp = new Date(data.timestamp * 1000); + + if (channel && user) { + if (channel._typing.has(user.id)) { + const typing = channel._typing.get(user.id); + + typing.lastTimestamp = timestamp; + typing.elapsedTime = Date.now() - typing.since; + this.client.clearTimeout(typing.timeout); + typing.timeout = this.tooLate(channel, user); + } else { + const since = new Date(); + const lastTimestamp = new Date(); + channel._typing.set(user.id, { + user, + since, + lastTimestamp, + elapsedTime: Date.now() - since, + timeout: this.tooLate(channel, user), + }); + + /** + * Emitted whenever a user starts typing in a channel. + * @event Client#typingStart + * @param {Channel} channel The channel the user started typing in + * @param {User} user The user that started typing + */ + this.client.emit(Events.TYPING_START, channel, user); + } + } + } + + tooLate(channel, user) { + return channel.client.setTimeout(() => { + channel._typing.delete(user.id); + }, 10000); + } +} + +module.exports = TypingStart; diff --git a/node_modules/discord.js/src/client/actions/UserUpdate.js b/node_modules/discord.js/src/client/actions/UserUpdate.js new file mode 100644 index 0000000..0033aaa --- /dev/null +++ b/node_modules/discord.js/src/client/actions/UserUpdate.js @@ -0,0 +1,35 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class UserUpdateAction extends Action { + handle(data) { + const client = this.client; + + const newUser = client.users.cache.get(data.id); + const oldUser = newUser._update(data); + + if (!oldUser.equals(newUser)) { + /** + * Emitted whenever a user's details (e.g. username) are changed. + * Triggered by the Discord gateway events USER_UPDATE, GUILD_MEMBER_UPDATE, and PRESENCE_UPDATE. + * @event Client#userUpdate + * @param {User} oldUser The user before the update + * @param {User} newUser The user after the update + */ + client.emit(Events.USER_UPDATE, oldUser, newUser); + return { + old: oldUser, + updated: newUser, + }; + } + + return { + old: null, + updated: null, + }; + } +} + +module.exports = UserUpdateAction; diff --git a/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js new file mode 100644 index 0000000..406bd2f --- /dev/null +++ b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js @@ -0,0 +1,45 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); +const Structures = require('../../util/Structures'); + +class VoiceStateUpdate extends Action { + handle(data) { + const client = this.client; + const guild = client.guilds.cache.get(data.guild_id); + if (guild) { + const VoiceState = Structures.get('VoiceState'); + // Update the state + const oldState = guild.voiceStates.cache.has(data.user_id) + ? guild.voiceStates.cache.get(data.user_id)._clone() + : new VoiceState(guild, { user_id: data.user_id }); + + const newState = guild.voiceStates.add(data); + + // Get the member + let member = guild.members.cache.get(data.user_id); + if (member && data.member) { + member._patch(data.member); + } else if (data.member && data.member.user && data.member.joined_at) { + member = guild.members.add(data.member); + } + + // Emit event + if (member && member.user.id === client.user.id) { + client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`); + client.voice.onVoiceStateUpdate(data); + } + + /** + * Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes. + * @event Client#voiceStateUpdate + * @param {VoiceState} oldState The voice state before the update + * @param {VoiceState} newState The voice state after the update + */ + client.emit(Events.VOICE_STATE_UPDATE, oldState, newState); + } + } +} + +module.exports = VoiceStateUpdate; diff --git a/node_modules/discord.js/src/client/actions/WebhooksUpdate.js b/node_modules/discord.js/src/client/actions/WebhooksUpdate.js new file mode 100644 index 0000000..fdf9c56 --- /dev/null +++ b/node_modules/discord.js/src/client/actions/WebhooksUpdate.js @@ -0,0 +1,19 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class WebhooksUpdate extends Action { + handle(data) { + const client = this.client; + const channel = client.channels.cache.get(data.channel_id); + /** + * Emitted whenever a guild text channel has its webhooks changed. + * @event Client#webhookUpdate + * @param {TextChannel} channel The channel that had a webhook update + */ + if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel); + } +} + +module.exports = WebhooksUpdate; diff --git a/node_modules/discord.js/src/client/voice/ClientVoiceManager.js b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js new file mode 100644 index 0000000..38c9f1d --- /dev/null +++ b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js @@ -0,0 +1,116 @@ +'use strict'; + +const VoiceBroadcast = require('./VoiceBroadcast'); +const VoiceConnection = require('./VoiceConnection'); +const { Error } = require('../../errors'); +const Collection = require('../../util/Collection'); + +/** + * Manages voice connections for the client + */ +class ClientVoiceManager { + constructor(client) { + /** + * The client that instantiated this voice manager + * @type {Client} + * @readonly + * @name ClientVoiceManager#client + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * A collection mapping connection IDs to the Connection objects + * @type {Collection} + */ + this.connections = new Collection(); + + /** + * Active voice broadcasts that have been created + * @type {VoiceBroadcast[]} + */ + this.broadcasts = []; + } + + /** + * Creates a voice broadcast. + * @returns {VoiceBroadcast} + */ + createBroadcast() { + const broadcast = new VoiceBroadcast(this.client); + this.broadcasts.push(broadcast); + return broadcast; + } + + onVoiceServer({ guild_id, token, endpoint }) { + this.client.emit('debug', `[VOICE] voiceServer guild: ${guild_id} token: ${token} endpoint: ${endpoint}`); + const connection = this.connections.get(guild_id); + if (connection) connection.setTokenAndEndpoint(token, endpoint); + } + + onVoiceStateUpdate({ guild_id, session_id, channel_id }) { + const connection = this.connections.get(guild_id); + this.client.emit('debug', `[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`); + if (!connection) return; + if (!channel_id) { + connection._disconnect(); + this.connections.delete(guild_id); + return; + } + const channel = this.client.channels.cache.get(channel_id); + if (channel) { + connection.channel = channel; + connection.setSessionID(session_id); + } else { + this.client.emit('debug', `[VOICE] disconnecting from guild ${guild_id} as channel ${channel_id} is uncached`); + connection.disconnect(); + } + } + + /** + * Sets up a request to join a voice channel. + * @param {VoiceChannel} channel The voice channel to join + * @returns {Promise} + * @private + */ + joinChannel(channel) { + return new Promise((resolve, reject) => { + if (!channel.joinable) { + throw new Error('VOICE_JOIN_CHANNEL', channel.full); + } + + let connection = this.connections.get(channel.guild.id); + + if (connection) { + if (connection.channel.id !== channel.id) { + this.connections.get(channel.guild.id).updateChannel(channel); + } + resolve(connection); + return; + } else { + connection = new VoiceConnection(this, channel); + connection.on('debug', msg => + this.client.emit('debug', `[VOICE (${channel.guild.id}:${connection.status})]: ${msg}`), + ); + connection.authenticate(); + this.connections.set(channel.guild.id, connection); + } + + connection.once('failed', reason => { + this.connections.delete(channel.guild.id); + reject(reason); + }); + + connection.on('error', reject); + + connection.once('authenticated', () => { + connection.once('ready', () => { + resolve(connection); + connection.removeListener('error', reject); + }); + connection.once('disconnect', () => this.connections.delete(channel.guild.id)); + }); + }); + } +} + +module.exports = ClientVoiceManager; diff --git a/node_modules/discord.js/src/client/voice/VoiceBroadcast.js b/node_modules/discord.js/src/client/voice/VoiceBroadcast.js new file mode 100644 index 0000000..5755b52 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/VoiceBroadcast.js @@ -0,0 +1,111 @@ +'use strict'; + +const EventEmitter = require('events'); +const BroadcastAudioPlayer = require('./player/BroadcastAudioPlayer'); +const PlayInterface = require('./util/PlayInterface'); +const { Events } = require('../../util/Constants'); + +/** + * A voice broadcast can be played across multiple voice connections for improved shared-stream efficiency. + * + * Example usage: + * ```js + * const broadcast = client.voice.createBroadcast(); + * broadcast.play('./music.mp3'); + * // Play "music.mp3" in all voice connections that the client is in + * for (const connection of client.voice.connections.values()) { + * connection.play(broadcast); + * } + * ``` + * @implements {PlayInterface} + * @extends {EventEmitter} + */ +class VoiceBroadcast extends EventEmitter { + constructor(client) { + super(); + /** + * The client that created the broadcast + * @type {Client} + */ + this.client = client; + /** + * The subscribed StreamDispatchers of this broadcast + * @type {StreamDispatcher[]} + */ + this.subscribers = []; + this.player = new BroadcastAudioPlayer(this); + } + + /** + * The current master dispatcher, if any. This dispatcher controls all that is played by subscribed dispatchers. + * @type {?BroadcastDispatcher} + * @readonly + */ + get dispatcher() { + return this.player.dispatcher; + } + + /** + * Play an audio resource. + * @param {ReadableStream|string} resource The resource to play. + * @param {StreamOptions} [options] The options to play. + * @example + * // Play a local audio file + * broadcast.play('/home/hydrabolt/audio.mp3', { volume: 0.5 }); + * @example + * // Play a ReadableStream + * broadcast.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { filter: 'audioonly' })); + * @example + * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html + * broadcast.play('http://www.sample-videos.com/audio/mp3/wave.mp3'); + * @returns {BroadcastDispatcher} + */ + play() { + return null; + } + + /** + * Ends the broadcast, unsubscribing all subscribed channels and deleting the broadcast + */ + end() { + for (const dispatcher of this.subscribers) this.delete(dispatcher); + const index = this.client.voice.broadcasts.indexOf(this); + if (index !== -1) this.client.voice.broadcasts.splice(index, 1); + } + + add(dispatcher) { + const index = this.subscribers.indexOf(dispatcher); + if (index === -1) { + this.subscribers.push(dispatcher); + /** + * Emitted whenever a stream dispatcher subscribes to the broadcast. + * @event VoiceBroadcast#subscribe + * @param {StreamDispatcher} subscriber The subscribed dispatcher + */ + this.emit(Events.VOICE_BROADCAST_SUBSCRIBE, dispatcher); + return true; + } else { + return false; + } + } + + delete(dispatcher) { + const index = this.subscribers.indexOf(dispatcher); + if (index !== -1) { + this.subscribers.splice(index, 1); + dispatcher.destroy(); + /** + * Emitted whenever a stream dispatcher unsubscribes to the broadcast. + * @event VoiceBroadcast#unsubscribe + * @param {StreamDispatcher} dispatcher The unsubscribed dispatcher + */ + this.emit(Events.VOICE_BROADCAST_UNSUBSCRIBE, dispatcher); + return true; + } + return false; + } +} + +PlayInterface.applyToClass(VoiceBroadcast); + +module.exports = VoiceBroadcast; diff --git a/node_modules/discord.js/src/client/voice/VoiceConnection.js b/node_modules/discord.js/src/client/voice/VoiceConnection.js new file mode 100644 index 0000000..c8942b4 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/VoiceConnection.js @@ -0,0 +1,526 @@ +'use strict'; + +const EventEmitter = require('events'); +const VoiceUDP = require('./networking/VoiceUDPClient'); +const VoiceWebSocket = require('./networking/VoiceWebSocket'); +const AudioPlayer = require('./player/AudioPlayer'); +const VoiceReceiver = require('./receiver/Receiver'); +const PlayInterface = require('./util/PlayInterface'); +const Silence = require('./util/Silence'); +const { Error } = require('../../errors'); +const { OPCodes, VoiceOPCodes, VoiceStatus, Events } = require('../../util/Constants'); +const Speaking = require('../../util/Speaking'); +const Util = require('../../util/Util'); + +// Workaround for Discord now requiring silence to be sent before being able to receive audio +class SingleSilence extends Silence { + _read() { + super._read(); + this.push(null); + } +} + +const SUPPORTED_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305']; + +/** + * Represents a connection to a guild's voice server. + * ```js + * // Obtained using: + * voiceChannel.join() + * .then(connection => { + * + * }); + * ``` + * @extends {EventEmitter} + * @implements {PlayInterface} + */ +class VoiceConnection extends EventEmitter { + constructor(voiceManager, channel) { + super(); + + /** + * The voice manager that instantiated this connection + * @type {ClientVoiceManager} + */ + this.voiceManager = voiceManager; + + /** + * The voice channel this connection is currently serving + * @type {VoiceChannel} + */ + this.channel = channel; + + /** + * The current status of the voice connection + * @type {VoiceStatus} + */ + this.status = VoiceStatus.AUTHENTICATING; + + /** + * Our current speaking state + * @type {Readonly} + */ + this.speaking = new Speaking().freeze(); + + /** + * The authentication data needed to connect to the voice server + * @type {Object} + * @private + */ + this.authentication = {}; + + /** + * The audio player for this voice connection + * @type {AudioPlayer} + */ + this.player = new AudioPlayer(this); + + this.player.on('debug', m => { + /** + * Debug info from the connection. + * @event VoiceConnection#debug + * @param {string} message The debug message + */ + this.emit('debug', `audio player - ${m}`); + }); + + this.player.on('error', e => { + /** + * Warning info from the connection. + * @event VoiceConnection#warn + * @param {string|Error} warning The warning + */ + this.emit('warn', e); + }); + + this.once('closing', () => this.player.destroy()); + + /** + * Map SSRC values to user IDs + * @type {Map} + * @private + */ + this.ssrcMap = new Map(); + + /** + * Tracks which users are talking + * @type {Map>} + * @private + */ + this._speaking = new Map(); + + /** + * Object that wraps contains the `ws` and `udp` sockets of this voice connection + * @type {Object} + * @private + */ + this.sockets = {}; + + /** + * The voice receiver of this connection + * @type {VoiceReceiver} + */ + this.receiver = new VoiceReceiver(this); + } + + /** + * The client that instantiated this connection + * @type {Client} + * @readonly + */ + get client() { + return this.voiceManager.client; + } + + /** + * The current stream dispatcher (if any) + * @type {?StreamDispatcher} + * @readonly + */ + get dispatcher() { + return this.player.dispatcher; + } + + /** + * Sets whether the voice connection should display as "speaking", "soundshare" or "none". + * @param {BitFieldResolvable} value The new speaking state + */ + setSpeaking(value) { + if (this.speaking.equals(value)) return; + if (this.status !== VoiceStatus.CONNECTED) return; + this.speaking = new Speaking(value).freeze(); + this.sockets.ws + .sendPacket({ + op: VoiceOPCodes.SPEAKING, + d: { + speaking: this.speaking.bitfield, + delay: 0, + ssrc: this.authentication.ssrc, + }, + }) + .catch(e => { + this.emit('debug', e); + }); + } + + /** + * The voice state of this connection + * @type {?VoiceState} + */ + get voice() { + return this.channel.guild.voice; + } + + /** + * Sends a request to the main gateway to join a voice channel. + * @param {Object} [options] The options to provide + * @returns {Promise} + * @private + */ + sendVoiceStateUpdate(options = {}) { + options = Util.mergeDefault( + { + guild_id: this.channel.guild.id, + channel_id: this.channel.id, + self_mute: this.voice ? this.voice.selfMute : false, + self_deaf: this.voice ? this.voice.selfDeaf : false, + }, + options, + ); + + this.emit('debug', `Sending voice state update: ${JSON.stringify(options)}`); + + return this.channel.guild.shard.send( + { + op: OPCodes.VOICE_STATE_UPDATE, + d: options, + }, + true, + ); + } + + /** + * Set the token and endpoint required to connect to the voice servers. + * @param {string} token The voice token + * @param {string} endpoint The voice endpoint + * @returns {void} + * @private + */ + setTokenAndEndpoint(token, endpoint) { + this.emit('debug', `Token "${token}" and endpoint "${endpoint}"`); + if (!endpoint) { + // Signifies awaiting endpoint stage + return; + } + + if (!token) { + this.authenticateFailed('VOICE_TOKEN_ABSENT'); + return; + } + + endpoint = endpoint.match(/([^:]*)/)[0]; + this.emit('debug', `Endpoint resolved as ${endpoint}`); + + if (!endpoint) { + this.authenticateFailed('VOICE_INVALID_ENDPOINT'); + return; + } + + if (this.status === VoiceStatus.AUTHENTICATING) { + this.authentication.token = token; + this.authentication.endpoint = endpoint; + this.checkAuthenticated(); + } else if (token !== this.authentication.token || endpoint !== this.authentication.endpoint) { + this.reconnect(token, endpoint); + } + } + + /** + * Sets the Session ID for the connection. + * @param {string} sessionID The voice session ID + * @private + */ + setSessionID(sessionID) { + this.emit('debug', `Setting sessionID ${sessionID} (stored as "${this.authentication.sessionID}")`); + if (!sessionID) { + this.authenticateFailed('VOICE_SESSION_ABSENT'); + return; + } + + if (this.status === VoiceStatus.AUTHENTICATING) { + this.authentication.sessionID = sessionID; + this.checkAuthenticated(); + } else if (sessionID !== this.authentication.sessionID) { + this.authentication.sessionID = sessionID; + /** + * Emitted when a new session ID is received. + * @event VoiceConnection#newSession + * @private + */ + this.emit('newSession', sessionID); + } + } + + /** + * Checks whether the voice connection is authenticated. + * @private + */ + checkAuthenticated() { + const { token, endpoint, sessionID } = this.authentication; + this.emit('debug', `Authenticated with sessionID ${sessionID}`); + if (token && endpoint && sessionID) { + this.status = VoiceStatus.CONNECTING; + /** + * Emitted when we successfully initiate a voice connection. + * @event VoiceConnection#authenticated + */ + this.emit('authenticated'); + this.connect(); + } + } + + /** + * Invoked when we fail to initiate a voice connection. + * @param {string} reason The reason for failure + * @private + */ + authenticateFailed(reason) { + this.client.clearTimeout(this.connectTimeout); + this.emit('debug', `Authenticate failed - ${reason}`); + if (this.status === VoiceStatus.AUTHENTICATING) { + /** + * Emitted when we fail to initiate a voice connection. + * @event VoiceConnection#failed + * @param {Error} error The encountered error + */ + this.emit('failed', new Error(reason)); + } else { + /** + * Emitted whenever the connection encounters an error. + * @event VoiceConnection#error + * @param {Error} error The encountered error + */ + this.emit('error', new Error(reason)); + } + this.status = VoiceStatus.DISCONNECTED; + } + + /** + * Move to a different voice channel in the same guild. + * @param {VoiceChannel} channel The channel to move to + * @private + */ + updateChannel(channel) { + this.channel = channel; + this.sendVoiceStateUpdate(); + } + + /** + * Attempts to authenticate to the voice server. + * @private + */ + authenticate() { + this.sendVoiceStateUpdate(); + this.connectTimeout = this.client.setTimeout(() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15000); + } + + /** + * Attempts to reconnect to the voice server (typically after a region change). + * @param {string} token The voice token + * @param {string} endpoint The voice endpoint + * @private + */ + reconnect(token, endpoint) { + this.authentication.token = token; + this.authentication.endpoint = endpoint; + this.speaking = new Speaking().freeze(); + this.status = VoiceStatus.RECONNECTING; + this.emit('debug', `Reconnecting to ${endpoint}`); + /** + * Emitted when the voice connection is reconnecting (typically after a region change). + * @event VoiceConnection#reconnecting + */ + this.emit('reconnecting'); + this.connect(); + } + + /** + * Disconnects the voice connection, causing a disconnect and closing event to be emitted. + */ + disconnect() { + this.emit('closing'); + this.emit('debug', 'disconnect() triggered'); + this.client.clearTimeout(this.connectTimeout); + const conn = this.voiceManager.connections.get(this.channel.guild.id); + if (conn === this) this.voiceManager.connections.delete(this.channel.guild.id); + this.sendVoiceStateUpdate({ + channel_id: null, + }); + this._disconnect(); + } + + /** + * Internally disconnects (doesn't send disconnect packet). + * @private + */ + _disconnect() { + this.cleanup(); + this.status = VoiceStatus.DISCONNECTED; + /** + * Emitted when the voice connection disconnects. + * @event VoiceConnection#disconnect + */ + this.emit('disconnect'); + } + + /** + * Cleans up after disconnect. + * @private + */ + cleanup() { + this.player.destroy(); + this.speaking = new Speaking().freeze(); + const { ws, udp } = this.sockets; + + this.emit('debug', 'Connection clean up'); + + if (ws) { + ws.removeAllListeners('error'); + ws.removeAllListeners('ready'); + ws.removeAllListeners('sessionDescription'); + ws.removeAllListeners('speaking'); + ws.shutdown(); + } + + if (udp) udp.removeAllListeners('error'); + + this.sockets.ws = null; + this.sockets.udp = null; + } + + /** + * Connect the voice connection. + * @private + */ + connect() { + this.emit('debug', `Connect triggered`); + if (this.status !== VoiceStatus.RECONNECTING) { + if (this.sockets.ws) throw new Error('WS_CONNECTION_EXISTS'); + if (this.sockets.udp) throw new Error('UDP_CONNECTION_EXISTS'); + } + + if (this.sockets.ws) this.sockets.ws.shutdown(); + if (this.sockets.udp) this.sockets.udp.shutdown(); + + this.sockets.ws = new VoiceWebSocket(this); + this.sockets.udp = new VoiceUDP(this); + + const { ws, udp } = this.sockets; + + ws.on('debug', msg => this.emit('debug', msg)); + udp.on('debug', msg => this.emit('debug', msg)); + ws.on('error', err => this.emit('error', err)); + udp.on('error', err => this.emit('error', err)); + ws.on('ready', this.onReady.bind(this)); + ws.on('sessionDescription', this.onSessionDescription.bind(this)); + ws.on('startSpeaking', this.onStartSpeaking.bind(this)); + + this.sockets.ws.connect(); + } + + /** + * Invoked when the voice websocket is ready. + * @param {Object} data The received data + * @private + */ + onReady(data) { + Object.assign(this.authentication, data); + for (let mode of data.modes) { + if (SUPPORTED_MODES.includes(mode)) { + this.authentication.mode = mode; + this.emit('debug', `Selecting the ${mode} mode`); + break; + } + } + this.sockets.udp.createUDPSocket(data.ip); + } + + /** + * Invoked when a session description is received. + * @param {Object} data The received data + * @private + */ + onSessionDescription(data) { + Object.assign(this.authentication, data); + this.status = VoiceStatus.CONNECTED; + const ready = () => { + this.client.clearTimeout(this.connectTimeout); + this.emit('debug', `Ready with authentication details: ${JSON.stringify(this.authentication)}`); + /** + * Emitted once the connection is ready, when a promise to join a voice channel resolves, + * the connection will already be ready. + * @event VoiceConnection#ready + */ + this.emit('ready'); + }; + if (this.dispatcher) { + ready(); + } else { + // This serves to provide support for voice receive, sending audio is required to receive it. + const dispatcher = this.play(new SingleSilence(), { type: 'opus', volume: false }); + dispatcher.once('finish', ready); + } + } + + onStartSpeaking({ user_id, ssrc, speaking }) { + this.ssrcMap.set(+ssrc, { + ...(this.ssrcMap.get(+ssrc) || {}), + userID: user_id, + speaking: speaking, + }); + } + + /** + * Invoked when a speaking event is received. + * @param {Object} data The received data + * @private + */ + onSpeaking({ user_id, speaking }) { + speaking = new Speaking(speaking).freeze(); + const guild = this.channel.guild; + const user = this.client.users.cache.get(user_id); + const old = this._speaking.get(user_id); + this._speaking.set(user_id, speaking); + /** + * Emitted whenever a user changes speaking state. + * @event VoiceConnection#speaking + * @param {User} user The user that has changed speaking state + * @param {Readonly} speaking The speaking state of the user + */ + if (this.status === VoiceStatus.CONNECTED) { + this.emit('speaking', user, speaking); + if (!speaking.has(Speaking.FLAGS.SPEAKING)) { + this.receiver.packets._stoppedSpeaking(user_id); + } + } + + if (guild && user && !speaking.equals(old)) { + const member = guild.member(user); + if (member) { + /** + * Emitted once a guild member changes speaking state. + * @event Client#guildMemberSpeaking + * @param {GuildMember} member The member that started/stopped speaking + * @param {Readonly} speaking The speaking state of the member + */ + this.client.emit(Events.GUILD_MEMBER_SPEAKING, member, speaking); + } + } + } + + play() {} // eslint-disable-line no-empty-function +} + +PlayInterface.applyToClass(VoiceConnection); + +module.exports = VoiceConnection; diff --git a/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js new file mode 100644 index 0000000..ae8d412 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js @@ -0,0 +1,46 @@ +'use strict'; + +const StreamDispatcher = require('./StreamDispatcher'); + +/** + * The class that sends voice packet data to the voice connection. + * @implements {VolumeInterface} + * @extends {StreamDispatcher} + */ +class BroadcastDispatcher extends StreamDispatcher { + constructor(player, options, streams) { + super(player, options, streams); + this.broadcast = player.broadcast; + } + + _write(chunk, enc, done) { + if (!this.startTime) this.startTime = Date.now(); + for (const dispatcher of this.broadcast.subscribers) { + dispatcher._write(chunk, enc); + } + this._step(done); + } + + _destroy(err, cb) { + if (this.player.dispatcher === this) this.player.dispatcher = null; + const { streams } = this; + if (streams.opus) streams.opus.unpipe(this); + if (streams.ffmpeg) streams.ffmpeg.destroy(); + super._destroy(err, cb); + } + + /** + * Set the bitrate of the current Opus encoder if using a compatible Opus stream. + * @param {number} value New bitrate, in kbps + * If set to 'auto', 48kbps will be used + * @returns {boolean} true if the bitrate has been successfully changed. + */ + setBitrate(value) { + if (!value || !this.streams.opus || !this.streams.opus.setBitrate) return false; + const bitrate = value === 'auto' ? 48 : value; + this.streams.opus.setBitrate(bitrate * 1000); + return true; + } +} + +module.exports = BroadcastDispatcher; diff --git a/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js new file mode 100644 index 0000000..bb1c7bb --- /dev/null +++ b/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js @@ -0,0 +1,354 @@ +'use strict'; + +const { Writable } = require('stream'); +const secretbox = require('../util/Secretbox'); +const Silence = require('../util/Silence'); +const VolumeInterface = require('../util/VolumeInterface'); + +const FRAME_LENGTH = 20; +const CHANNELS = 2; +const TIMESTAMP_INC = (48000 / 100) * CHANNELS; + +const MAX_NONCE_SIZE = 2 ** 32 - 1; +const nonce = Buffer.alloc(24); + +/** + * @external WritableStream + * @see {@link https://nodejs.org/api/stream.html#stream_class_stream_writable} + */ + +/** + * The class that sends voice packet data to the voice connection. + * ```js + * // Obtained using: + * voiceChannel.join().then(connection => { + * // You can play a file or a stream here: + * const dispatcher = connection.play('/home/hydrabolt/audio.mp3'); + * }); + * ``` + * @implements {VolumeInterface} + * @extends {WritableStream} + */ +class StreamDispatcher extends Writable { + constructor(player, { seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {}, streams) { + const streamOptions = { seek, volume, fec, plp, bitrate, highWaterMark }; + super(streamOptions); + /** + * The Audio Player that controls this dispatcher + * @type {AudioPlayer} + */ + this.player = player; + this.streamOptions = streamOptions; + this.streams = streams; + this.streams.silence = new Silence(); + + this._nonce = 0; + this._nonceBuffer = Buffer.alloc(24); + + /** + * The time that the stream was paused at (null if not paused) + * @type {?number} + */ + this.pausedSince = null; + this._writeCallback = null; + + /** + * The broadcast controlling this dispatcher, if any + * @type {?VoiceBroadcast} + */ + this.broadcast = this.streams.broadcast || null; + + this._pausedTime = 0; + this._silentPausedTime = 0; + this.count = 0; + + this.on('finish', () => { + this._cleanup(); + this._setSpeaking(0); + }); + + this.setVolume(volume); + this.setBitrate(bitrate); + if (typeof fec !== 'undefined') this.setFEC(fec); + if (typeof plp !== 'undefined') this.setPLP(plp); + + const streamError = (type, err) => { + /** + * Emitted when the dispatcher encounters an error. + * @event StreamDispatcher#error + */ + if (type && err) { + err.message = `${type} stream: ${err.message}`; + this.emit(this.player.dispatcher === this ? 'error' : 'debug', err); + } + this.destroy(); + }; + + this.on('error', () => streamError()); + if (this.streams.input) this.streams.input.on('error', err => streamError('input', err)); + if (this.streams.ffmpeg) this.streams.ffmpeg.on('error', err => streamError('ffmpeg', err)); + if (this.streams.opus) this.streams.opus.on('error', err => streamError('opus', err)); + if (this.streams.volume) this.streams.volume.on('error', err => streamError('volume', err)); + } + + get _sdata() { + return this.player.streamingData; + } + + _write(chunk, enc, done) { + if (!this.startTime) { + /** + * Emitted once the stream has started to play. + * @event StreamDispatcher#start + */ + this.emit('start'); + this.startTime = Date.now(); + } + this._playChunk(chunk); + this._step(done); + } + + _destroy(err, cb) { + this._cleanup(); + super._destroy(err, cb); + } + + _cleanup() { + if (this.player.dispatcher === this) this.player.dispatcher = null; + const { streams } = this; + if (streams.broadcast) streams.broadcast.delete(this); + if (streams.opus) streams.opus.destroy(); + if (streams.ffmpeg) streams.ffmpeg.destroy(); + } + + /** + * Pauses playback + * @param {boolean} [silence=false] Whether to play silence while paused to prevent audio glitches + */ + pause(silence = false) { + if (this.paused) return; + if (this.streams.opus) this.streams.opus.unpipe(this); + if (silence) { + this.streams.silence.pipe(this); + this._silence = true; + } else { + this._setSpeaking(0); + } + this.pausedSince = Date.now(); + } + + /** + * Whether or not playback is paused + * @type {boolean} + * @readonly + */ + get paused() { + return Boolean(this.pausedSince); + } + + /** + * Total time that this dispatcher has been paused in milliseconds + * @type {number} + * @readonly + */ + get pausedTime() { + return this._silentPausedTime + this._pausedTime + (this.paused ? Date.now() - this.pausedSince : 0); + } + + /** + * Resumes playback + */ + resume() { + if (!this.pausedSince) return; + this.streams.silence.unpipe(this); + if (this.streams.opus) this.streams.opus.pipe(this); + if (this._silence) { + this._silentPausedTime += Date.now() - this.pausedSince; + this._silence = false; + } else { + this._pausedTime += Date.now() - this.pausedSince; + } + this.pausedSince = null; + if (typeof this._writeCallback === 'function') this._writeCallback(); + } + + /** + * The time (in milliseconds) that the dispatcher has actually been playing audio for + * @type {number} + * @readonly + */ + get streamTime() { + return this.count * FRAME_LENGTH; + } + + /** + * The time (in milliseconds) that the dispatcher has been playing audio for, taking into account skips and pauses + * @type {number} + * @readonly + */ + get totalStreamTime() { + return Date.now() - this.startTime; + } + + /** + * Set the bitrate of the current Opus encoder if using a compatible Opus stream. + * @param {number} value New bitrate, in kbps + * If set to 'auto', the voice channel's bitrate will be used + * @returns {boolean} true if the bitrate has been successfully changed. + */ + setBitrate(value) { + if (!value || !this.bitrateEditable) return false; + const bitrate = value === 'auto' ? this.player.voiceConnection.channel.bitrate : value; + this.streams.opus.setBitrate(bitrate * 1000); + return true; + } + + /** + * Sets the expected packet loss percentage if using a compatible Opus stream. + * @param {number} value between 0 and 1 + * @returns {boolean} Returns true if it was successfully set. + */ + setPLP(value) { + if (!this.bitrateEditable) return false; + this.streams.opus.setPLP(value); + return true; + } + + /** + * Enables or disables forward error correction if using a compatible Opus stream. + * @param {boolean} enabled true to enable + * @returns {boolean} Returns true if it was successfully set. + */ + setFEC(enabled) { + if (!this.bitrateEditable) return false; + this.streams.opus.setFEC(enabled); + return true; + } + + _step(done) { + this._writeCallback = () => { + this._writeCallback = null; + done(); + }; + if (!this.streams.broadcast) { + const next = FRAME_LENGTH + this.count * FRAME_LENGTH - (Date.now() - this.startTime - this._pausedTime); + setTimeout(() => { + if ((!this.pausedSince || this._silence) && this._writeCallback) this._writeCallback(); + }, next); + } + this._sdata.sequence++; + this._sdata.timestamp += TIMESTAMP_INC; + if (this._sdata.sequence >= 2 ** 16) this._sdata.sequence = 0; + if (this._sdata.timestamp >= 2 ** 32) this._sdata.timestamp = 0; + this.count++; + } + + _final(callback) { + this._writeCallback = null; + callback(); + } + + _playChunk(chunk) { + if (this.player.dispatcher !== this || !this.player.voiceConnection.authentication.secret_key) return; + this._sendPacket(this._createPacket(this._sdata.sequence, this._sdata.timestamp, chunk)); + } + + _encrypt(buffer) { + const { secret_key, mode } = this.player.voiceConnection.authentication; + if (mode === 'xsalsa20_poly1305_lite') { + this._nonce++; + if (this._nonce > MAX_NONCE_SIZE) this._nonce = 0; + this._nonceBuffer.writeUInt32BE(this._nonce, 0); + return [secretbox.methods.close(buffer, this._nonceBuffer, secret_key), this._nonceBuffer.slice(0, 4)]; + } else if (mode === 'xsalsa20_poly1305_suffix') { + const random = secretbox.methods.random(24); + return [secretbox.methods.close(buffer, random, secret_key), random]; + } else { + return [secretbox.methods.close(buffer, nonce, secret_key)]; + } + } + + _createPacket(sequence, timestamp, buffer) { + const packetBuffer = Buffer.alloc(12); + packetBuffer[0] = 0x80; + packetBuffer[1] = 0x78; + + packetBuffer.writeUIntBE(sequence, 2, 2); + packetBuffer.writeUIntBE(timestamp, 4, 4); + packetBuffer.writeUIntBE(this.player.voiceConnection.authentication.ssrc, 8, 4); + + packetBuffer.copy(nonce, 0, 0, 12); + return Buffer.concat([packetBuffer, ...this._encrypt(buffer)]); + } + + _sendPacket(packet) { + /** + * Emitted whenever the dispatcher has debug information. + * @event StreamDispatcher#debug + * @param {string} info The debug info + */ + this._setSpeaking(1); + if (!this.player.voiceConnection.sockets.udp) { + this.emit('debug', 'Failed to send a packet - no UDP socket'); + return; + } + this.player.voiceConnection.sockets.udp.send(packet).catch(e => { + this._setSpeaking(0); + this.emit('debug', `Failed to send a packet - ${e}`); + }); + } + + _setSpeaking(value) { + if (typeof this.player.voiceConnection !== 'undefined') { + this.player.voiceConnection.setSpeaking(value); + } + /** + * Emitted when the dispatcher starts/stops speaking. + * @event StreamDispatcher#speaking + * @param {boolean} value Whether or not the dispatcher is speaking + */ + this.emit('speaking', value); + } + + get volumeEditable() { + return Boolean(this.streams.volume); + } + + /** + * Whether or not the Opus bitrate of this stream is editable + * @type {boolean} + * @readonly + */ + get bitrateEditable() { + return this.streams.opus && this.streams.opus.setBitrate; + } + + // Volume + get volume() { + return this.streams.volume ? this.streams.volume.volume : 1; + } + + setVolume(value) { + if (!this.streams.volume) return false; + /** + * Emitted when the volume of this dispatcher changes. + * @event StreamDispatcher#volumeChange + * @param {number} oldVolume The old volume of this dispatcher + * @param {number} newVolume The new volume of this dispatcher + */ + this.emit('volumeChange', this.volume, value); + this.streams.volume.setVolume(value); + return true; + } + + // Volume stubs for docs + /* eslint-disable no-empty-function*/ + get volumeDecibels() {} + get volumeLogarithmic() {} + setVolumeDecibels() {} + setVolumeLogarithmic() {} +} + +VolumeInterface.applyToClass(StreamDispatcher); + +module.exports = StreamDispatcher; diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js b/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js new file mode 100644 index 0000000..b86428a --- /dev/null +++ b/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js @@ -0,0 +1,154 @@ +'use strict'; + +const udp = require('dgram'); +const EventEmitter = require('events'); +const { Error } = require('../../../errors'); +const { VoiceOPCodes } = require('../../../util/Constants'); + +/** + * Represents a UDP client for a Voice Connection. + * @extends {EventEmitter} + * @private + */ +class VoiceConnectionUDPClient extends EventEmitter { + constructor(voiceConnection) { + super(); + + /** + * The voice connection that this UDP client serves + * @type {VoiceConnection} + */ + this.voiceConnection = voiceConnection; + + /** + * The UDP socket + * @type {?Socket} + */ + this.socket = null; + + /** + * The address of the Discord voice server + * @type {?string} + */ + this.discordAddress = null; + + /** + * The local IP address + * @type {?string} + */ + this.localAddress = null; + + /** + * The local port + * @type {?string} + */ + this.localPort = null; + + this.voiceConnection.on('closing', this.shutdown.bind(this)); + } + + shutdown() { + this.emit('debug', `[UDP] shutdown requested`); + if (this.socket) { + this.socket.removeAllListeners('message'); + try { + this.socket.close(); + } finally { + this.socket = null; + } + } + } + + /** + * The port of the Discord voice server + * @type {number} + * @readonly + */ + get discordPort() { + return this.voiceConnection.authentication.port; + } + + /** + * Send a packet to the UDP client. + * @param {Object} packet The packet to send + * @returns {Promise} + */ + send(packet) { + return new Promise((resolve, reject) => { + if (!this.socket) throw new Error('UDP_SEND_FAIL'); + if (!this.discordAddress || !this.discordPort) throw new Error('UDP_ADDRESS_MALFORMED'); + this.socket.send(packet, 0, packet.length, this.discordPort, this.discordAddress, error => { + if (error) { + this.emit('debug', `[UDP] >> ERROR: ${error}`); + reject(error); + } else { + resolve(packet); + } + }); + }); + } + + async createUDPSocket(address) { + this.discordAddress = address; + const socket = (this.socket = udp.createSocket('udp4')); + socket.on('error', e => { + this.emit('debug', `[UDP] Error: ${e}`); + this.emit('error', e); + }); + socket.on('close', () => { + this.emit('debug', '[UDP] socket closed'); + }); + this.emit('debug', `[UDP] created socket`); + socket.once('message', message => { + this.emit('debug', `[UDP] message: [${[...message]}] (${message})`); + // Stop if the sockets have been deleted because the connection has been closed already + if (!this.voiceConnection.sockets.ws) return; + + const packet = parseLocalPacket(message); + if (packet.error) { + this.emit('debug', `[UDP] ERROR: ${packet.error}`); + this.emit('error', packet.error); + return; + } + + this.localAddress = packet.address; + this.localPort = packet.port; + + this.voiceConnection.sockets.ws.sendPacket({ + op: VoiceOPCodes.SELECT_PROTOCOL, + d: { + protocol: 'udp', + data: { + address: packet.address, + port: packet.port, + mode: this.voiceConnection.authentication.mode, + }, + }, + }); + + this.emit('debug', `[UDP] << ${JSON.stringify(packet)}`); + + socket.on('message', buffer => this.voiceConnection.receiver.packets.push(buffer)); + }); + + const blankMessage = Buffer.alloc(70); + blankMessage.writeUIntBE(this.voiceConnection.authentication.ssrc, 0, 4); + this.emit('debug', `Sending IP discovery packet: [${[...blankMessage]}]`); + await this.send(blankMessage); + this.emit('debug', `Successfully sent IP discovery packet`); + } +} + +function parseLocalPacket(message) { + try { + const packet = Buffer.from(message); + let address = ''; + for (let i = 4; i < packet.indexOf(0, i); i++) address += String.fromCharCode(packet[i]); + const port = parseInt(packet.readUIntLE(packet.length - 2, 2).toString(10), 10); + return { address, port }; + } catch (error) { + return { error }; + } +} + +module.exports = VoiceConnectionUDPClient; diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js b/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js new file mode 100644 index 0000000..db34401 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js @@ -0,0 +1,268 @@ +'use strict'; + +const EventEmitter = require('events'); +const WebSocket = require('../../../WebSocket'); +const { Error } = require('../../../errors'); +const { OPCodes, VoiceOPCodes } = require('../../../util/Constants'); + +/** + * Represents a Voice Connection's WebSocket. + * @extends {EventEmitter} + * @private + */ +class VoiceWebSocket extends EventEmitter { + constructor(connection) { + super(); + /** + * The Voice Connection that this WebSocket serves + * @type {VoiceConnection} + */ + this.connection = connection; + + /** + * How many connection attempts have been made + * @type {number} + */ + this.attempts = 0; + + this.dead = false; + this.connection.on('closing', this.shutdown.bind(this)); + } + + /** + * The client of this voice WebSocket + * @type {Client} + * @readonly + */ + get client() { + return this.connection.client; + } + + shutdown() { + this.emit('debug', `[WS] shutdown requested`); + this.dead = true; + this.reset(); + } + + /** + * Resets the current WebSocket. + */ + reset() { + this.emit('debug', `[WS] reset requested`); + if (this.ws) { + if (this.ws.readyState !== WebSocket.CLOSED) this.ws.close(); + this.ws = null; + } + this.clearHeartbeat(); + } + + /** + * Starts connecting to the Voice WebSocket Server. + */ + connect() { + this.emit('debug', `[WS] connect requested`); + if (this.dead) return; + if (this.ws) this.reset(); + if (this.attempts >= 5) { + this.emit('debug', new Error('VOICE_CONNECTION_ATTEMPTS_EXCEEDED', this.attempts)); + return; + } + + this.attempts++; + + /** + * The actual WebSocket used to connect to the Voice WebSocket Server. + * @type {WebSocket} + */ + this.ws = WebSocket.create(`wss://${this.connection.authentication.endpoint}/`, { v: 4 }); + this.emit('debug', `[WS] connecting, ${this.attempts} attempts, ${this.ws.url}`); + this.ws.onopen = this.onOpen.bind(this); + this.ws.onmessage = this.onMessage.bind(this); + this.ws.onclose = this.onClose.bind(this); + this.ws.onerror = this.onError.bind(this); + } + + /** + * Sends data to the WebSocket if it is open. + * @param {string} data The data to send to the WebSocket + * @returns {Promise} + */ + send(data) { + this.emit('debug', `[WS] >> ${data}`); + return new Promise((resolve, reject) => { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error('WS_NOT_OPEN', data); + this.ws.send(data, null, error => { + if (error) reject(error); + else resolve(data); + }); + }); + } + + /** + * JSON.stringify's a packet and then sends it to the WebSocket Server. + * @param {Object} packet The packet to send + * @returns {Promise} + */ + sendPacket(packet) { + try { + packet = JSON.stringify(packet); + } catch (error) { + return Promise.reject(error); + } + return this.send(packet); + } + + /** + * Called whenever the WebSocket opens. + */ + onOpen() { + this.emit('debug', `[WS] opened at gateway ${this.connection.authentication.endpoint}`); + this.sendPacket({ + op: OPCodes.DISPATCH, + d: { + server_id: this.connection.channel.guild.id, + user_id: this.client.user.id, + token: this.connection.authentication.token, + session_id: this.connection.authentication.sessionID, + }, + }).catch(() => { + this.emit('error', new Error('VOICE_JOIN_SOCKET_CLOSED')); + }); + } + + /** + * Called whenever a message is received from the WebSocket. + * @param {MessageEvent} event The message event that was received + * @returns {void} + */ + onMessage(event) { + try { + return this.onPacket(WebSocket.unpack(event.data, 'json')); + } catch (error) { + return this.onError(error); + } + } + + /** + * Called whenever the connection to the WebSocket server is lost. + */ + onClose() { + this.emit('debug', `[WS] closed`); + if (!this.dead) this.client.setTimeout(this.connect.bind(this), this.attempts * 1000); + } + + /** + * Called whenever an error occurs with the WebSocket. + * @param {Error} error The error that occurred + */ + onError(error) { + this.emit('debug', `[WS] Error: ${error}`); + this.emit('error', error); + } + + /** + * Called whenever a valid packet is received from the WebSocket. + * @param {Object} packet The received packet + */ + onPacket(packet) { + this.emit('debug', `[WS] << ${JSON.stringify(packet)}`); + switch (packet.op) { + case VoiceOPCodes.HELLO: + this.setHeartbeat(packet.d.heartbeat_interval); + break; + case VoiceOPCodes.READY: + /** + * Emitted once the voice WebSocket receives the ready packet. + * @param {Object} packet The received packet + * @event VoiceWebSocket#ready + */ + this.emit('ready', packet.d); + break; + /* eslint-disable no-case-declarations */ + case VoiceOPCodes.SESSION_DESCRIPTION: + packet.d.secret_key = new Uint8Array(packet.d.secret_key); + /** + * Emitted once the Voice Websocket receives a description of this voice session. + * @param {Object} packet The received packet + * @event VoiceWebSocket#sessionDescription + */ + this.emit('sessionDescription', packet.d); + break; + case VoiceOPCodes.CLIENT_CONNECT: + this.connection.ssrcMap.set(+packet.d.audio_ssrc, { + userID: packet.d.user_id, + speaking: 0, + hasVideo: Boolean(packet.d.video_ssrc), + }); + break; + case VoiceOPCodes.CLIENT_DISCONNECT: + const streamInfo = this.connection.receiver && this.connection.receiver.packets.streams.get(packet.d.user_id); + if (streamInfo) { + this.connection.receiver.packets.streams.delete(packet.d.user_id); + streamInfo.stream.push(null); + } + break; + case VoiceOPCodes.SPEAKING: + /** + * Emitted whenever a speaking packet is received. + * @param {Object} data + * @event VoiceWebSocket#startSpeaking + */ + this.emit('startSpeaking', packet.d); + break; + default: + /** + * Emitted when an unhandled packet is received. + * @param {Object} packet + * @event VoiceWebSocket#unknownPacket + */ + this.emit('unknownPacket', packet); + break; + } + } + + /** + * Sets an interval at which to send a heartbeat packet to the WebSocket. + * @param {number} interval The interval at which to send a heartbeat packet + */ + setHeartbeat(interval) { + if (!interval || isNaN(interval)) { + this.onError(new Error('VOICE_INVALID_HEARTBEAT')); + return; + } + if (this.heartbeatInterval) { + /** + * Emitted whenever the voice WebSocket encounters a non-fatal error. + * @param {string} warn The warning + * @event VoiceWebSocket#warn + */ + this.emit('warn', 'A voice heartbeat interval is being overwritten'); + this.client.clearInterval(this.heartbeatInterval); + } + this.heartbeatInterval = this.client.setInterval(this.sendHeartbeat.bind(this), interval); + } + + /** + * Clears a heartbeat interval, if one exists. + */ + clearHeartbeat() { + if (!this.heartbeatInterval) { + this.emit('warn', 'Tried to clear a heartbeat interval that does not exist'); + return; + } + this.client.clearInterval(this.heartbeatInterval); + this.heartbeatInterval = null; + } + + /** + * Sends a heartbeat packet. + */ + sendHeartbeat() { + this.sendPacket({ op: VoiceOPCodes.HEARTBEAT, d: Math.floor(Math.random() * 10e10) }).catch(() => { + this.emit('warn', 'Tried to send heartbeat, but connection is not open'); + this.clearHeartbeat(); + }); + } +} + +module.exports = VoiceWebSocket; diff --git a/node_modules/discord.js/src/client/voice/player/AudioPlayer.js b/node_modules/discord.js/src/client/voice/player/AudioPlayer.js new file mode 100644 index 0000000..6f719a7 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/player/AudioPlayer.js @@ -0,0 +1,27 @@ +'use strict'; + +const BasePlayer = require('./BasePlayer'); + +/** + * An Audio Player for a Voice Connection. + * @private + * @extends {BasePlayer} + */ +class AudioPlayer extends BasePlayer { + constructor(voiceConnection) { + super(); + /** + * The voice connection that the player serves + * @type {VoiceConnection} + */ + this.voiceConnection = voiceConnection; + } + + playBroadcast(broadcast, options) { + const dispatcher = this.createDispatcher(options, { broadcast }); + broadcast.add(dispatcher); + return dispatcher; + } +} + +module.exports = AudioPlayer; diff --git a/node_modules/discord.js/src/client/voice/player/BasePlayer.js b/node_modules/discord.js/src/client/voice/player/BasePlayer.js new file mode 100644 index 0000000..b968f82 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/player/BasePlayer.js @@ -0,0 +1,92 @@ +'use strict'; + +const EventEmitter = require('events'); +const { Readable: ReadableStream } = require('stream'); +const prism = require('prism-media'); +const StreamDispatcher = require('../dispatcher/StreamDispatcher'); + +const FFMPEG_ARGUMENTS = ['-analyzeduration', '0', '-loglevel', '0', '-f', 's16le', '-ar', '48000', '-ac', '2']; + +/** + * An Audio Player for a Voice Connection. + * @private + * @extends {EventEmitter} + */ +class BasePlayer extends EventEmitter { + constructor() { + super(); + + this.dispatcher = null; + + this.streamingData = { + channels: 2, + sequence: 0, + timestamp: 0, + }; + } + + destroy() { + this.destroyDispatcher(); + } + + destroyDispatcher() { + if (this.dispatcher) { + this.dispatcher.destroy(); + this.dispatcher = null; + } + } + + playUnknown(input, options) { + this.destroyDispatcher(); + + const isStream = input instanceof ReadableStream; + + const args = isStream ? FFMPEG_ARGUMENTS.slice() : ['-i', input, ...FFMPEG_ARGUMENTS]; + if (options.seek) args.unshift('-ss', String(options.seek)); + + const ffmpeg = new prism.FFmpeg({ args }); + const streams = { ffmpeg }; + if (isStream) { + streams.input = input; + input.pipe(ffmpeg); + } + return this.playPCMStream(ffmpeg, options, streams); + } + + playPCMStream(stream, options, streams = {}) { + this.destroyDispatcher(); + const opus = (streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); + if (options && options.volume === false) { + stream.pipe(opus); + return this.playOpusStream(opus, options, streams); + } + streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); + stream.pipe(streams.volume).pipe(opus); + return this.playOpusStream(opus, options, streams); + } + + playOpusStream(stream, options, streams = {}) { + this.destroyDispatcher(); + streams.opus = stream; + if (options.volume !== false && !streams.input) { + streams.input = stream; + const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 }); + streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); + streams.opus = stream + .pipe(decoder) + .pipe(streams.volume) + .pipe(new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); + } + const dispatcher = this.createDispatcher(options, streams); + streams.opus.pipe(dispatcher); + return dispatcher; + } + + createDispatcher(options, streams, broadcast) { + this.destroyDispatcher(); + const dispatcher = (this.dispatcher = new StreamDispatcher(this, options, streams, broadcast)); + return dispatcher; + } +} + +module.exports = BasePlayer; diff --git a/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js b/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js new file mode 100644 index 0000000..05197a4 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js @@ -0,0 +1,28 @@ +'use strict'; + +const BasePlayer = require('./BasePlayer'); +const BroadcastDispatcher = require('../dispatcher/BroadcastDispatcher'); + +/** + * An Audio Player for a Voice Connection. + * @private + * @extends {BasePlayer} + */ +class AudioPlayer extends BasePlayer { + constructor(broadcast) { + super(); + /** + * The broadcast that the player serves + * @type {VoiceBroadcast} + */ + this.broadcast = broadcast; + } + + createDispatcher(options, streams) { + this.destroyDispatcher(); + const dispatcher = (this.dispatcher = new BroadcastDispatcher(this, options, streams)); + return dispatcher; + } +} + +module.exports = AudioPlayer; diff --git a/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js b/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js new file mode 100644 index 0000000..bf1a220 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js @@ -0,0 +1,143 @@ +'use strict'; + +const EventEmitter = require('events'); +const Speaking = require('../../../util/Speaking'); +const secretbox = require('../util/Secretbox'); +const { SILENCE_FRAME } = require('../util/Silence'); + +// The delay between packets when a user is considered to have stopped speaking +// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200 +const DISCORD_SPEAKING_DELAY = 250; + +class Readable extends require('stream').Readable { + _read() {} // eslint-disable-line no-empty-function +} + +class PacketHandler extends EventEmitter { + constructor(receiver) { + super(); + this.nonce = Buffer.alloc(24); + this.receiver = receiver; + this.streams = new Map(); + this.speakingTimeouts = new Map(); + } + + get connection() { + return this.receiver.connection; + } + + _stoppedSpeaking(userID) { + const streamInfo = this.streams.get(userID); + if (streamInfo && streamInfo.end === 'silence') { + this.streams.delete(userID); + streamInfo.stream.push(null); + } + } + + makeStream(user, end) { + if (this.streams.has(user)) return this.streams.get(user).stream; + const stream = new Readable(); + stream.on('end', () => this.streams.delete(user)); + this.streams.set(user, { stream, end }); + return stream; + } + + parseBuffer(buffer) { + const { secret_key, mode } = this.receiver.connection.authentication; + + // Choose correct nonce depending on encryption + let end; + if (mode === 'xsalsa20_poly1305_lite') { + buffer.copy(this.nonce, 0, buffer.length - 4); + end = buffer.length - 4; + } else if (mode === 'xsalsa20_poly1305_suffix') { + buffer.copy(this.nonce, 0, buffer.length - 24); + end = buffer.length - 24; + } else { + buffer.copy(this.nonce, 0, 0, 12); + } + + // Open packet + let packet = secretbox.methods.open(buffer.slice(12, end), this.nonce, secret_key); + if (!packet) return new Error('Failed to decrypt voice packet'); + packet = Buffer.from(packet); + + // Strip RTP Header Extensions (one-byte only) + if (packet[0] === 0xbe && packet[1] === 0xde && packet.length > 4) { + const headerExtensionLength = packet.readUInt16BE(2); + let offset = 4; + for (let i = 0; i < headerExtensionLength; i++) { + const byte = packet[offset]; + offset++; + if (byte === 0) continue; + offset += 1 + (0b1111 & (byte >> 4)); + } + // Skip over undocumented Discord byte + offset++; + + packet = packet.slice(offset); + } + + return packet; + } + + push(buffer) { + const ssrc = buffer.readUInt32BE(8); + const userStat = this.connection.ssrcMap.get(ssrc); + if (!userStat) return; + + let opusPacket; + const streamInfo = this.streams.get(userStat.userID); + // If the user is in video, we need to check if the packet is just silence + if (userStat.hasVideo) { + opusPacket = this.parseBuffer(buffer); + if (opusPacket instanceof Error) { + // Only emit an error if we were actively receiving packets from this user + if (streamInfo) { + this.emit('error', opusPacket); + return; + } + } + if (SILENCE_FRAME.equals(opusPacket)) { + // If this is a silence frame, pretend we never received it + return; + } + } + + let speakingTimeout = this.speakingTimeouts.get(ssrc); + if (typeof speakingTimeout === 'undefined') { + // Ensure at least the speaking bit is set. + // As the object is by reference, it's only needed once per client re-connect. + if (userStat.speaking === 0) { + userStat.speaking = Speaking.FLAGS.SPEAKING; + } + this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: userStat.speaking }); + speakingTimeout = this.receiver.connection.client.setTimeout(() => { + try { + this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: 0 }); + this.receiver.connection.client.clearTimeout(speakingTimeout); + this.speakingTimeouts.delete(ssrc); + } catch { + // Connection already closed, ignore + } + }, DISCORD_SPEAKING_DELAY); + this.speakingTimeouts.set(ssrc, speakingTimeout); + } else { + speakingTimeout.refresh(); + } + + if (streamInfo) { + const { stream } = streamInfo; + if (!opusPacket) { + opusPacket = this.parseBuffer(buffer); + if (opusPacket instanceof Error) { + this.emit('error', opusPacket); + return; + } + } + stream.push(opusPacket); + } + } +} + +module.exports = PacketHandler; diff --git a/node_modules/discord.js/src/client/voice/receiver/Receiver.js b/node_modules/discord.js/src/client/voice/receiver/Receiver.js new file mode 100644 index 0000000..605d992 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/receiver/Receiver.js @@ -0,0 +1,58 @@ +'use strict'; + +const EventEmitter = require('events'); +const prism = require('prism-media'); +const PacketHandler = require('./PacketHandler'); +const { Error } = require('../../../errors'); + +/** + * Receives audio packets from a voice connection. + * @example + * const receiver = connection.createReceiver(); + * // opusStream is a ReadableStream - that means you could play it back to a voice channel if you wanted to! + * const opusStream = receiver.createStream(user); + */ +class VoiceReceiver extends EventEmitter { + constructor(connection) { + super(); + this.connection = connection; + this.packets = new PacketHandler(this); + /** + * Emitted whenever there is a warning + * @event VoiceReceiver#debug + * @param {Error|string} error The error or message to debug + */ + this.packets.on('error', err => this.emit('debug', err)); + } + + /** + * Options passed to `VoiceReceiver#createStream`. + * @typedef {Object} ReceiveStreamOptions + * @property {string} [mode='opus'] The mode for audio output. This defaults to opus, meaning discord.js won't decode + * the packets for you. You can set this to 'pcm' so that the stream's output will be 16-bit little-endian stereo + * audio + * @property {string} [end='silence'] When the stream should be destroyed. If `silence`, this will be when the user + * stops talking. Otherwise, if `manual`, this should be handled by you. + */ + + /** + * Creates a new audio receiving stream. If a stream already exists for a user, then that stream will be returned + * rather than generating a new one. + * @param {UserResolvable} user The user to start listening to. + * @param {ReceiveStreamOptions} options Options. + * @returns {ReadableStream} + */ + createStream(user, { mode = 'opus', end = 'silence' } = {}) { + user = this.connection.client.users.resolve(user); + if (!user) throw new Error('VOICE_USER_MISSING'); + const stream = this.packets.makeStream(user.id, end); + if (mode === 'pcm') { + const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 }); + stream.pipe(decoder); + return decoder; + } + return stream; + } +} + +module.exports = VoiceReceiver; diff --git a/node_modules/discord.js/src/client/voice/util/PlayInterface.js b/node_modules/discord.js/src/client/voice/util/PlayInterface.js new file mode 100644 index 0000000..9478ee8 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/util/PlayInterface.js @@ -0,0 +1,94 @@ +'use strict'; + +const { Readable } = require('stream'); +const prism = require('prism-media'); +const { Error } = require('../../../errors'); + +/** + * Options that can be passed to stream-playing methods: + * @typedef {Object} StreamOptions + * @property {StreamType} [type='unknown'] The type of stream. + * @property {number} [seek=0] The time to seek to, will be ignored when playing `ogg/opus` or `webm/opus` streams + * @property {number|boolean} [volume=1] The volume to play at. Set this to false to disable volume transforms for + * this stream to improve performance. + * @property {number} [plp] Expected packet loss percentage + * @property {boolean} [fec] Enabled forward error correction + * @property {number|string} [bitrate=96] The bitrate (quality) of the audio in kbps. + * If set to 'auto', the voice channel's bitrate will be used + * @property {number} [highWaterMark=12] The maximum number of opus packets to make and store before they are + * actually needed. See https://nodejs.org/en/docs/guides/backpressuring-in-streams/. Setting this value to + * 1 means that changes in volume will be more instant. + */ + +/** + * An option passed as part of `StreamOptions` specifying the type of the stream. + * * `unknown`: The default type, streams/input will be passed through to ffmpeg before encoding. + * Will play most streams. + * * `converted`: Play a stream of 16bit signed stereo PCM data, skipping ffmpeg. + * * `opus`: Play a stream of opus packets, skipping ffmpeg. You lose the ability to alter volume. + * * `ogg/opus`: Play an ogg file with the opus encoding, skipping ffmpeg. You lose the ability to alter volume. + * * `webm/opus`: Play a webm file with opus audio, skipping ffmpeg. You lose the ability to alter volume. + * @typedef {string} StreamType + */ + +/** + * An interface class to allow you to play audio over VoiceConnections and VoiceBroadcasts. + */ +class PlayInterface { + constructor(player) { + this.player = player; + } + + /** + * Play an audio resource. + * @param {VoiceBroadcast|ReadableStream|string} resource The resource to play. + * @param {StreamOptions} [options] The options to play. + * @example + * // Play a local audio file + * connection.play('/home/hydrabolt/audio.mp3', { volume: 0.5 }); + * @example + * // Play a ReadableStream + * connection.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { quality: 'highestaudio' })); + * @example + * // Play a voice broadcast + * const broadcast = client.voice.createBroadcast(); + * broadcast.play('/home/hydrabolt/audio.mp3'); + * connection.play(broadcast); + * @example + * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html + * connection.play('http://www.sample-videos.com/audio/mp3/wave.mp3'); + * @returns {StreamDispatcher} + */ + play(resource, options = {}) { + const VoiceBroadcast = require('../VoiceBroadcast'); + if (resource instanceof VoiceBroadcast) { + if (!this.player.playBroadcast) throw new Error('VOICE_PLAY_INTERFACE_NO_BROADCAST'); + return this.player.playBroadcast(resource, options); + } + if (resource instanceof Readable || typeof resource === 'string') { + const type = options.type || 'unknown'; + if (type === 'unknown') { + return this.player.playUnknown(resource, options); + } else if (type === 'converted') { + return this.player.playPCMStream(resource, options); + } else if (type === 'opus') { + return this.player.playOpusStream(resource, options); + } else if (type === 'ogg/opus') { + if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM'); + return this.player.playOpusStream(resource.pipe(new prism.opus.OggDemuxer()), options); + } else if (type === 'webm/opus') { + if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM'); + return this.player.playOpusStream(resource.pipe(new prism.opus.WebmDemuxer()), options); + } + } + throw new Error('VOICE_PLAY_INTERFACE_BAD_TYPE'); + } + + static applyToClass(structure) { + for (const prop of ['play']) { + Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(PlayInterface.prototype, prop)); + } + } +} + +module.exports = PlayInterface; diff --git a/node_modules/discord.js/src/client/voice/util/Secretbox.js b/node_modules/discord.js/src/client/voice/util/Secretbox.js new file mode 100644 index 0000000..c16a435 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/util/Secretbox.js @@ -0,0 +1,32 @@ +'use strict'; + +const libs = { + sodium: sodium => ({ + open: sodium.api.crypto_secretbox_open_easy, + close: sodium.api.crypto_secretbox_easy, + random: n => sodium.randombytes_buf(n), + }), + 'libsodium-wrappers': sodium => ({ + open: sodium.crypto_secretbox_open_easy, + close: sodium.crypto_secretbox_easy, + random: n => sodium.randombytes_buf(n), + }), + tweetnacl: tweetnacl => ({ + open: tweetnacl.secretbox.open, + close: tweetnacl.secretbox, + random: n => tweetnacl.randomBytes(n), + }), +}; + +exports.methods = {}; + +(async () => { + for (const libName of Object.keys(libs)) { + try { + const lib = require(libName); + if (libName === 'libsodium-wrappers' && lib.ready) await lib.ready; // eslint-disable-line no-await-in-loop + exports.methods = libs[libName](lib); + break; + } catch {} // eslint-disable-line no-empty + } +})(); diff --git a/node_modules/discord.js/src/client/voice/util/Silence.js b/node_modules/discord.js/src/client/voice/util/Silence.js new file mode 100644 index 0000000..7930ae6 --- /dev/null +++ b/node_modules/discord.js/src/client/voice/util/Silence.js @@ -0,0 +1,15 @@ +'use strict'; + +const { Readable } = require('stream'); + +const SILENCE_FRAME = Buffer.from([0xf8, 0xff, 0xfe]); + +class Silence extends Readable { + _read() { + this.push(SILENCE_FRAME); + } +} + +Silence.SILENCE_FRAME = SILENCE_FRAME; + +module.exports = Silence; diff --git a/node_modules/discord.js/src/client/voice/util/VolumeInterface.js b/node_modules/discord.js/src/client/voice/util/VolumeInterface.js new file mode 100644 index 0000000..0dca04f --- /dev/null +++ b/node_modules/discord.js/src/client/voice/util/VolumeInterface.js @@ -0,0 +1,103 @@ +'use strict'; + +const EventEmitter = require('events'); + +/** + * An interface class for volume transformation. + * @extends {EventEmitter} + */ +class VolumeInterface extends EventEmitter { + constructor({ volume = 1 } = {}) { + super(); + this.setVolume(volume); + } + + /** + * Whether or not the volume of this stream is editable + * @type {boolean} + * @readonly + */ + get volumeEditable() { + return true; + } + + /** + * The current volume of the stream + * @type {number} + * @readonly + */ + get volume() { + return this._volume; + } + + /** + * The current volume of the stream in decibels + * @type {number} + * @readonly + */ + get volumeDecibels() { + return Math.log10(this.volume) * 20; + } + + /** + * The current volume of the stream from a logarithmic scale + * @type {number} + * @readonly + */ + get volumeLogarithmic() { + return Math.pow(this.volume, 1 / 1.660964); + } + + applyVolume(buffer, volume) { + volume = volume || this._volume; + if (volume === 1) return buffer; + + const out = Buffer.alloc(buffer.length); + for (let i = 0; i < buffer.length; i += 2) { + if (i >= buffer.length - 1) break; + const uint = Math.min(32767, Math.max(-32767, Math.floor(volume * buffer.readInt16LE(i)))); + out.writeInt16LE(uint, i); + } + + return out; + } + + /** + * Sets the volume relative to the input stream - i.e. 1 is normal, 0.5 is half, 2 is double. + * @param {number} volume The volume that you want to set + */ + setVolume(volume) { + /** + * Emitted when the volume of this interface changes. + * @event VolumeInterface#volumeChange + * @param {number} oldVolume The old volume of this interface + * @param {number} newVolume The new volume of this interface + */ + this.emit('volumeChange', this._volume, volume); + this._volume = volume; + } + + /** + * Sets the volume in decibels. + * @param {number} db The decibels + */ + setVolumeDecibels(db) { + this.setVolume(Math.pow(10, db / 20)); + } + + /** + * Sets the volume so that a perceived value of 0.5 is half the perceived volume etc. + * @param {number} value The value for the volume + */ + setVolumeLogarithmic(value) { + this.setVolume(Math.pow(value, 1.660964)); + } +} + +const props = ['volumeDecibels', 'volumeLogarithmic', 'setVolumeDecibels', 'setVolumeLogarithmic']; + +exports.applyToClass = function applyToClass(structure) { + for (const prop of props) { + Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(VolumeInterface.prototype, prop)); + } +}; diff --git a/node_modules/discord.js/src/client/websocket/WebSocketManager.js b/node_modules/discord.js/src/client/websocket/WebSocketManager.js new file mode 100644 index 0000000..f892985 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/WebSocketManager.js @@ -0,0 +1,437 @@ +'use strict'; + +const EventEmitter = require('events'); +const WebSocketShard = require('./WebSocketShard'); +const PacketHandlers = require('./handlers'); +const { Error: DJSError } = require('../../errors'); +const Collection = require('../../util/Collection'); +const { Events, ShardEvents, Status, WSCodes, WSEvents } = require('../../util/Constants'); +const Util = require('../../util/Util'); + +const BeforeReadyWhitelist = [ + WSEvents.READY, + WSEvents.RESUMED, + WSEvents.GUILD_CREATE, + WSEvents.GUILD_DELETE, + WSEvents.GUILD_MEMBERS_CHUNK, + WSEvents.GUILD_MEMBER_ADD, + WSEvents.GUILD_MEMBER_REMOVE, +]; + +const UNRECOVERABLE_CLOSE_CODES = Object.keys(WSCodes).slice(1).map(Number); +const UNRESUMABLE_CLOSE_CODES = [1000, 4006, 4007]; + +/** + * The WebSocket manager for this client. + * This class forwards raw dispatch events, + * read more about it here {@link https://discord.com/developers/docs/topics/gateway} + * @extends EventEmitter + */ +class WebSocketManager extends EventEmitter { + constructor(client) { + super(); + + /** + * The client that instantiated this WebSocketManager + * @type {Client} + * @readonly + * @name WebSocketManager#client + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The gateway this manager uses + * @type {?string} + */ + this.gateway = null; + + /** + * The amount of shards this manager handles + * @private + * @type {number} + */ + this.totalShards = this.client.options.shards.length; + + /** + * A collection of all shards this manager handles + * @type {Collection} + */ + this.shards = new Collection(); + + /** + * An array of shards to be connected or that need to reconnect + * @type {Set} + * @private + * @name WebSocketManager#shardQueue + */ + Object.defineProperty(this, 'shardQueue', { value: new Set(), writable: true }); + + /** + * An array of queued events before this WebSocketManager became ready + * @type {object[]} + * @private + * @name WebSocketManager#packetQueue + */ + Object.defineProperty(this, 'packetQueue', { value: [] }); + + /** + * The current status of this WebSocketManager + * @type {number} + */ + this.status = Status.IDLE; + + /** + * If this manager was destroyed. It will prevent shards from reconnecting + * @type {boolean} + * @private + */ + this.destroyed = false; + + /** + * If this manager is currently reconnecting one or multiple shards + * @type {boolean} + * @private + */ + this.reconnecting = false; + + /** + * The current session limit of the client + * @private + * @type {?Object} + * @property {number} total Total number of identifies available + * @property {number} remaining Number of identifies remaining + * @property {number} reset_after Number of milliseconds after which the limit resets + */ + this.sessionStartLimit = null; + } + + /** + * The average ping of all WebSocketShards + * @type {number} + * @readonly + */ + get ping() { + const sum = this.shards.reduce((a, b) => a + b.ping, 0); + return sum / this.shards.size; + } + + /** + * Emits a debug message. + * @param {string} message The debug message + * @param {?WebSocketShard} [shard] The shard that emitted this message, if any + * @private + */ + debug(message, shard) { + this.client.emit(Events.DEBUG, `[WS => ${shard ? `Shard ${shard.id}` : 'Manager'}] ${message}`); + } + + /** + * Connects this manager to the gateway. + * @private + */ + async connect() { + const invalidToken = new DJSError(WSCodes[4004]); + const { + url: gatewayURL, + shards: recommendedShards, + session_start_limit: sessionStartLimit, + } = await this.client.api.gateway.bot.get().catch(error => { + throw error.httpStatus === 401 ? invalidToken : error; + }); + + this.sessionStartLimit = sessionStartLimit; + + const { total, remaining, reset_after } = sessionStartLimit; + + this.debug(`Fetched Gateway Information + URL: ${gatewayURL} + Recommended Shards: ${recommendedShards}`); + + this.debug(`Session Limit Information + Total: ${total} + Remaining: ${remaining}`); + + this.gateway = `${gatewayURL}/`; + + let { shards } = this.client.options; + + if (shards === 'auto') { + this.debug(`Using the recommended shard count provided by Discord: ${recommendedShards}`); + this.totalShards = this.client.options.shardCount = recommendedShards; + shards = this.client.options.shards = Array.from({ length: recommendedShards }, (_, i) => i); + } + + this.totalShards = shards.length; + this.debug(`Spawning shards: ${shards.join(', ')}`); + this.shardQueue = new Set(shards.map(id => new WebSocketShard(this, id))); + + await this._handleSessionLimit(remaining, reset_after); + + return this.createShards(); + } + + /** + * Handles the creation of a shard. + * @returns {Promise} + * @private + */ + async createShards() { + // If we don't have any shards to handle, return + if (!this.shardQueue.size) return false; + + const [shard] = this.shardQueue; + + this.shardQueue.delete(shard); + + if (!shard.eventsAttached) { + shard.on(ShardEvents.ALL_READY, unavailableGuilds => { + /** + * Emitted when a shard turns ready. + * @event Client#shardReady + * @param {number} id The shard ID that turned ready + * @param {?Set} unavailableGuilds Set of unavailable guild IDs, if any + */ + this.client.emit(Events.SHARD_READY, shard.id, unavailableGuilds); + + if (!this.shardQueue.size) this.reconnecting = false; + this.checkShardsReady(); + }); + + shard.on(ShardEvents.CLOSE, event => { + if (event.code === 1000 ? this.destroyed : UNRECOVERABLE_CLOSE_CODES.includes(event.code)) { + /** + * Emitted when a shard's WebSocket disconnects and will no longer reconnect. + * @event Client#shardDisconnect + * @param {CloseEvent} event The WebSocket close event + * @param {number} id The shard ID that disconnected + */ + this.client.emit(Events.SHARD_DISCONNECT, event, shard.id); + this.debug(WSCodes[event.code], shard); + return; + } + + if (UNRESUMABLE_CLOSE_CODES.includes(event.code)) { + // These event codes cannot be resumed + shard.sessionID = null; + } + + /** + * Emitted when a shard is attempting to reconnect or re-identify. + * @event Client#shardReconnecting + * @param {number} id The shard ID that is attempting to reconnect + */ + this.client.emit(Events.SHARD_RECONNECTING, shard.id); + + this.shardQueue.add(shard); + + if (shard.sessionID) { + this.debug(`Session ID is present, attempting an immediate reconnect...`, shard); + this.reconnect(true); + } else { + shard.destroy({ reset: true, emit: false, log: false }); + this.reconnect(); + } + }); + + shard.on(ShardEvents.INVALID_SESSION, () => { + this.client.emit(Events.SHARD_RECONNECTING, shard.id); + }); + + shard.on(ShardEvents.DESTROYED, () => { + this.debug('Shard was destroyed but no WebSocket connection was present! Reconnecting...', shard); + + this.client.emit(Events.SHARD_RECONNECTING, shard.id); + + this.shardQueue.add(shard); + this.reconnect(); + }); + + shard.eventsAttached = true; + } + + this.shards.set(shard.id, shard); + + try { + await shard.connect(); + } catch (error) { + if (error && error.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) { + throw new DJSError(WSCodes[error.code]); + // Undefined if session is invalid, error event for regular closes + } else if (!error || error.code) { + this.debug('Failed to connect to the gateway, requeueing...', shard); + this.shardQueue.add(shard); + } else { + throw error; + } + } + // If we have more shards, add a 5s delay + if (this.shardQueue.size) { + this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`); + await Util.delayFor(5000); + await this._handleSessionLimit(); + return this.createShards(); + } + + return true; + } + + /** + * Handles reconnects for this manager. + * @param {boolean} [skipLimit=false] IF this reconnect should skip checking the session limit + * @private + * @returns {Promise} + */ + async reconnect(skipLimit = false) { + if (this.reconnecting || this.status !== Status.READY) return false; + this.reconnecting = true; + try { + if (!skipLimit) await this._handleSessionLimit(); + await this.createShards(); + } catch (error) { + this.debug(`Couldn't reconnect or fetch information about the gateway. ${error}`); + if (error.httpStatus !== 401) { + this.debug(`Possible network error occurred. Retrying in 5s...`); + await Util.delayFor(5000); + this.reconnecting = false; + return this.reconnect(); + } + // If we get an error at this point, it means we cannot reconnect anymore + if (this.client.listenerCount(Events.INVALIDATED)) { + /** + * Emitted when the client's session becomes invalidated. + * You are expected to handle closing the process gracefully and preventing a boot loop + * if you are listening to this event. + * @event Client#invalidated + */ + this.client.emit(Events.INVALIDATED); + // Destroy just the shards. This means you have to handle the cleanup yourself + this.destroy(); + } else { + this.client.destroy(); + } + } finally { + this.reconnecting = false; + } + return true; + } + + /** + * Broadcasts a packet to every shard this manager handles. + * @param {Object} packet The packet to send + * @private + */ + broadcast(packet) { + for (const shard of this.shards.values()) shard.send(packet); + } + + /** + * Destroys this manager and all its shards. + * @private + */ + destroy() { + if (this.destroyed) return; + this.debug(`Manager was destroyed. Called by:\n${new Error('MANAGER_DESTROYED').stack}`); + this.destroyed = true; + this.shardQueue.clear(); + for (const shard of this.shards.values()) shard.destroy({ closeCode: 1000, reset: true, emit: false, log: false }); + } + + /** + * Handles the timeout required if we cannot identify anymore. + * @param {number} [remaining] The amount of remaining identify sessions that can be done today + * @param {number} [resetAfter] The amount of time in which the identify counter resets + * @private + */ + async _handleSessionLimit(remaining, resetAfter) { + if (typeof remaining === 'undefined' && typeof resetAfter === 'undefined') { + const { session_start_limit } = await this.client.api.gateway.bot.get(); + this.sessionStartLimit = session_start_limit; + remaining = session_start_limit.remaining; + resetAfter = session_start_limit.reset_after; + this.debug(`Session Limit Information + Total: ${session_start_limit.total} + Remaining: ${remaining}`); + } + if (!remaining) { + this.debug(`Exceeded identify threshold. Will attempt a connection in ${resetAfter}ms`); + await Util.delayFor(resetAfter); + } + } + + /** + * Processes a packet and queues it if this WebSocketManager is not ready. + * @param {Object} [packet] The packet to be handled + * @param {WebSocketShard} [shard] The shard that will handle this packet + * @returns {boolean} + * @private + */ + handlePacket(packet, shard) { + if (packet && this.status !== Status.READY) { + if (!BeforeReadyWhitelist.includes(packet.t)) { + this.packetQueue.push({ packet, shard }); + return false; + } + } + + if (this.packetQueue.length) { + const item = this.packetQueue.shift(); + this.client.setImmediate(() => { + this.handlePacket(item.packet, item.shard); + }); + } + + if (packet && PacketHandlers[packet.t]) { + PacketHandlers[packet.t](this.client, packet, shard); + } + + return true; + } + + /** + * Checks whether the client is ready to be marked as ready. + * @private + */ + async checkShardsReady() { + if (this.status === Status.READY) return; + if (this.shards.size !== this.totalShards || this.shards.some(s => s.status !== Status.READY)) { + return; + } + + this.status = Status.NEARLY; + + if (this.client.options.fetchAllMembers) { + try { + const promises = this.client.guilds.cache.map(guild => { + if (guild.available) return guild.members.fetch(); + // Return empty promise if guild is unavailable + return Promise.resolve(); + }); + await Promise.all(promises); + } catch (err) { + this.debug(`Failed to fetch all members before ready! ${err}\n${err.stack}`); + } + } + + this.triggerClientReady(); + } + + /** + * Causes the client to be marked as ready and emits the ready event. + * @private + */ + triggerClientReady() { + this.status = Status.READY; + + this.client.readyAt = new Date(); + + /** + * Emitted when the client becomes ready to start working. + * @event Client#ready + */ + this.client.emit(Events.CLIENT_READY); + + this.handlePacket(); + } +} + +module.exports = WebSocketManager; diff --git a/node_modules/discord.js/src/client/websocket/WebSocketShard.js b/node_modules/discord.js/src/client/websocket/WebSocketShard.js new file mode 100644 index 0000000..f99c83f --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/WebSocketShard.js @@ -0,0 +1,771 @@ +'use strict'; + +const EventEmitter = require('events'); +const WebSocket = require('../../WebSocket'); +const { browser, Status, Events, ShardEvents, OPCodes, WSEvents } = require('../../util/Constants'); + +const STATUS_KEYS = Object.keys(Status); +const CONNECTION_STATE = Object.keys(WebSocket.WebSocket); + +let zlib; + +if (!browser) { + try { + zlib = require('zlib-sync'); + } catch {} // eslint-disable-line no-empty +} + +/** + * Represents a Shard's WebSocket connection + */ +class WebSocketShard extends EventEmitter { + constructor(manager, id) { + super(); + + /** + * The WebSocketManager of the shard + * @type {WebSocketManager} + */ + this.manager = manager; + + /** + * The ID of the shard + * @type {number} + */ + this.id = id; + + /** + * The current status of the shard + * @type {Status} + */ + this.status = Status.IDLE; + + /** + * The current sequence of the shard + * @type {number} + * @private + */ + this.sequence = -1; + + /** + * The sequence of the shard after close + * @type {number} + * @private + */ + this.closeSequence = 0; + + /** + * The current session ID of the shard + * @type {?string} + * @private + */ + this.sessionID = null; + + /** + * The previous heartbeat ping of the shard + * @type {number} + */ + this.ping = -1; + + /** + * The last time a ping was sent (a timestamp) + * @type {number} + * @private + */ + this.lastPingTimestamp = -1; + + /** + * If we received a heartbeat ack back. Used to identify zombie connections + * @type {boolean} + * @private + */ + this.lastHeartbeatAcked = true; + + /** + * Contains the rate limit queue and metadata + * @name WebSocketShard#ratelimit + * @type {Object} + * @private + */ + Object.defineProperty(this, 'ratelimit', { + value: { + queue: [], + total: 120, + remaining: 120, + time: 60e3, + timer: null, + }, + }); + + /** + * The WebSocket connection for the current shard + * @name WebSocketShard#connection + * @type {?WebSocket} + * @private + */ + Object.defineProperty(this, 'connection', { value: null, writable: true }); + + /** + * @external Inflate + * @see {@link https://www.npmjs.com/package/zlib-sync} + */ + + /** + * The compression to use + * @name WebSocketShard#inflate + * @type {?Inflate} + * @private + */ + Object.defineProperty(this, 'inflate', { value: null, writable: true }); + + /** + * The HELLO timeout + * @name WebSocketShard#helloTimeout + * @type {?NodeJS.Timeout} + * @private + */ + Object.defineProperty(this, 'helloTimeout', { value: null, writable: true }); + + /** + * If the manager attached its event handlers on the shard + * @name WebSocketShard#eventsAttached + * @type {boolean} + * @private + */ + Object.defineProperty(this, 'eventsAttached', { value: false, writable: true }); + + /** + * A set of guild IDs this shard expects to receive + * @name WebSocketShard#expectedGuilds + * @type {?Set} + * @private + */ + Object.defineProperty(this, 'expectedGuilds', { value: null, writable: true }); + + /** + * The ready timeout + * @name WebSocketShard#readyTimeout + * @type {?NodeJS.Timeout} + * @private + */ + Object.defineProperty(this, 'readyTimeout', { value: null, writable: true }); + + /** + * Time when the WebSocket connection was opened + * @name WebSocketShard#connectedAt + * @type {number} + * @private + */ + Object.defineProperty(this, 'connectedAt', { value: 0, writable: true }); + } + + /** + * Emits a debug event. + * @param {string} message The debug message + * @private + */ + debug(message) { + this.manager.debug(message, this); + } + + /** + * Connects the shard to the gateway. + * @private + * @returns {Promise} A promise that will resolve if the shard turns ready successfully, + * or reject if we couldn't connect + */ + connect() { + const { gateway, client } = this.manager; + + if (this.connection && this.connection.readyState === WebSocket.OPEN && this.status === Status.READY) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + const cleanup = () => { + this.removeListener(ShardEvents.CLOSE, onClose); + this.removeListener(ShardEvents.READY, onReady); + this.removeListener(ShardEvents.RESUMED, onResumed); + this.removeListener(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed); + this.removeListener(ShardEvents.DESTROYED, onInvalidOrDestroyed); + }; + + const onReady = () => { + cleanup(); + resolve(); + }; + + const onResumed = () => { + cleanup(); + resolve(); + }; + + const onClose = event => { + cleanup(); + reject(event); + }; + + const onInvalidOrDestroyed = () => { + cleanup(); + // eslint-disable-next-line prefer-promise-reject-errors + reject(); + }; + + this.once(ShardEvents.READY, onReady); + this.once(ShardEvents.RESUMED, onResumed); + this.once(ShardEvents.CLOSE, onClose); + this.once(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed); + this.once(ShardEvents.DESTROYED, onInvalidOrDestroyed); + + if (this.connection && this.connection.readyState === WebSocket.OPEN) { + this.debug('An open connection was found, attempting an immediate identify.'); + this.identify(); + return; + } + + if (this.connection) { + this.debug(`A connection object was found. Cleaning up before continuing. + State: ${CONNECTION_STATE[this.connection.readyState]}`); + this.destroy({ emit: false }); + } + + const wsQuery = { v: client.options.ws.version }; + + if (zlib) { + this.inflate = new zlib.Inflate({ + chunkSize: 65535, + flush: zlib.Z_SYNC_FLUSH, + to: WebSocket.encoding === 'json' ? 'string' : '', + }); + wsQuery.compress = 'zlib-stream'; + } + + this.debug( + `[CONNECT] + Gateway : ${gateway} + Version : ${client.options.ws.version} + Encoding : ${WebSocket.encoding} + Compression: ${zlib ? 'zlib-stream' : 'none'}`, + ); + + this.status = this.status === Status.DISCONNECTED ? Status.RECONNECTING : Status.CONNECTING; + this.setHelloTimeout(); + + this.connectedAt = Date.now(); + + const ws = (this.connection = WebSocket.create(gateway, wsQuery)); + ws.onopen = this.onOpen.bind(this); + ws.onmessage = this.onMessage.bind(this); + ws.onerror = this.onError.bind(this); + ws.onclose = this.onClose.bind(this); + }); + } + + /** + * Called whenever a connection is opened to the gateway. + * @private + */ + onOpen() { + this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now() - this.connectedAt}ms`); + this.status = Status.NEARLY; + } + + /** + * Called whenever a message is received. + * @param {MessageEvent} event Event received + * @private + */ + onMessage({ data }) { + let raw; + if (data instanceof ArrayBuffer) data = new Uint8Array(data); + if (zlib) { + const l = data.length; + const flush = + l >= 4 && data[l - 4] === 0x00 && data[l - 3] === 0x00 && data[l - 2] === 0xff && data[l - 1] === 0xff; + + this.inflate.push(data, flush && zlib.Z_SYNC_FLUSH); + if (!flush) return; + raw = this.inflate.result; + } else { + raw = data; + } + let packet; + try { + packet = WebSocket.unpack(raw); + this.manager.client.emit(Events.RAW, packet, this.id); + if (packet.op === OPCodes.DISPATCH) this.manager.emit(packet.t, packet.d, this.id); + } catch (err) { + this.manager.client.emit(Events.SHARD_ERROR, err, this.id); + return; + } + this.onPacket(packet); + } + + /** + * Called whenever an error occurs with the WebSocket. + * @param {ErrorEvent} event The error that occurred + * @private + */ + onError(event) { + const error = event && event.error ? event.error : event; + if (!error) return; + + /** + * Emitted whenever a shard's WebSocket encounters a connection error. + * @event Client#shardError + * @param {Error} error The encountered error + * @param {number} shardID The shard that encountered this error + */ + this.manager.client.emit(Events.SHARD_ERROR, error, this.id); + } + + /** + * @external CloseEvent + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent} + */ + + /** + * @external ErrorEvent + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent} + */ + + /** + * @external MessageEvent + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent} + */ + + /** + * Called whenever a connection to the gateway is closed. + * @param {CloseEvent} event Close event that was received + * @private + */ + onClose(event) { + if (this.sequence !== -1) this.closeSequence = this.sequence; + this.sequence = -1; + + this.debug(`[CLOSE] + Event Code: ${event.code} + Clean : ${event.wasClean} + Reason : ${event.reason || 'No reason received'}`); + + this.setHeartbeatTimer(-1); + this.setHelloTimeout(-1); + // If we still have a connection object, clean up its listeners + if (this.connection) this._cleanupConnection(); + + this.status = Status.DISCONNECTED; + + /** + * Emitted when a shard's WebSocket closes. + * @private + * @event WebSocketShard#close + * @param {CloseEvent} event The received event + */ + this.emit(ShardEvents.CLOSE, event); + } + + /** + * Called whenever a packet is received. + * @param {Object} packet The received packet + * @private + */ + onPacket(packet) { + if (!packet) { + this.debug(`Received broken packet: '${packet}'.`); + return; + } + + switch (packet.t) { + case WSEvents.READY: + /** + * Emitted when the shard receives the READY payload and is now waiting for guilds + * @event WebSocketShard#ready + */ + this.emit(ShardEvents.READY); + + this.sessionID = packet.d.session_id; + this.expectedGuilds = new Set(packet.d.guilds.map(d => d.id)); + this.status = Status.WAITING_FOR_GUILDS; + this.debug(`[READY] Session ${this.sessionID}.`); + this.lastHeartbeatAcked = true; + this.sendHeartbeat('ReadyHeartbeat'); + break; + case WSEvents.RESUMED: { + /** + * Emitted when the shard resumes successfully + * @event WebSocketShard#resumed + */ + this.emit(ShardEvents.RESUMED); + + this.status = Status.READY; + const replayed = packet.s - this.closeSequence; + this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${replayed} events.`); + this.lastHeartbeatAcked = true; + this.sendHeartbeat('ResumeHeartbeat'); + break; + } + } + + if (packet.s > this.sequence) this.sequence = packet.s; + + switch (packet.op) { + case OPCodes.HELLO: + this.setHelloTimeout(-1); + this.setHeartbeatTimer(packet.d.heartbeat_interval); + this.identify(); + break; + case OPCodes.RECONNECT: + this.debug('[RECONNECT] Discord asked us to reconnect'); + this.destroy({ closeCode: 4000 }); + break; + case OPCodes.INVALID_SESSION: + this.debug(`[INVALID SESSION] Resumable: ${packet.d}.`); + // If we can resume the session, do so immediately + if (packet.d) { + this.identifyResume(); + return; + } + // Reset the sequence + this.sequence = -1; + // Reset the session ID as it's invalid + this.sessionID = null; + // Set the status to reconnecting + this.status = Status.RECONNECTING; + // Finally, emit the INVALID_SESSION event + this.emit(ShardEvents.INVALID_SESSION); + break; + case OPCodes.HEARTBEAT_ACK: + this.ackHeartbeat(); + break; + case OPCodes.HEARTBEAT: + this.sendHeartbeat('HeartbeatRequest', true); + break; + default: + this.manager.handlePacket(packet, this); + if (this.status === Status.WAITING_FOR_GUILDS && packet.t === WSEvents.GUILD_CREATE) { + this.expectedGuilds.delete(packet.d.id); + this.checkReady(); + } + } + } + + /** + * Checks if the shard can be marked as ready + * @private + */ + checkReady() { + // Step 0. Clear the ready timeout, if it exists + if (this.readyTimeout) { + this.manager.client.clearTimeout(this.readyTimeout); + this.readyTimeout = null; + } + // Step 1. If we don't have any other guilds pending, we are ready + if (!this.expectedGuilds.size) { + this.debug('Shard received all its guilds. Marking as fully ready.'); + this.status = Status.READY; + + /** + * Emitted when the shard is fully ready. + * This event is emitted if: + * * all guilds were received by this shard + * * the ready timeout expired, and some guilds are unavailable + * @event WebSocketShard#allReady + * @param {?Set} unavailableGuilds Set of unavailable guilds, if any + */ + this.emit(ShardEvents.ALL_READY); + return; + } + // Step 2. Create a 15s timeout that will mark the shard as ready if there are still unavailable guilds + this.readyTimeout = this.manager.client.setTimeout(() => { + this.debug(`Shard did not receive any more guild packets in 15 seconds. + Unavailable guild count: ${this.expectedGuilds.size}`); + + this.readyTimeout = null; + + this.status = Status.READY; + + this.emit(ShardEvents.ALL_READY, this.expectedGuilds); + }, 15000); + } + + /** + * Sets the HELLO packet timeout. + * @param {number} [time] If set to -1, it will clear the hello timeout timeout + * @private + */ + setHelloTimeout(time) { + if (time === -1) { + if (this.helloTimeout) { + this.debug('Clearing the HELLO timeout.'); + this.manager.client.clearTimeout(this.helloTimeout); + this.helloTimeout = null; + } + return; + } + this.debug('Setting a HELLO timeout for 20s.'); + this.helloTimeout = this.manager.client.setTimeout(() => { + this.debug('Did not receive HELLO in time. Destroying and connecting again.'); + this.destroy({ reset: true, closeCode: 4009 }); + }, 20000); + } + + /** + * Sets the heartbeat timer for this shard. + * @param {number} time If -1, clears the interval, any other number sets an interval + * @private + */ + setHeartbeatTimer(time) { + if (time === -1) { + if (this.heartbeatInterval) { + this.debug('Clearing the heartbeat interval.'); + this.manager.client.clearInterval(this.heartbeatInterval); + this.heartbeatInterval = null; + } + return; + } + this.debug(`Setting a heartbeat interval for ${time}ms.`); + // Sanity checks + if (this.heartbeatInterval) this.manager.client.clearInterval(this.heartbeatInterval); + this.heartbeatInterval = this.manager.client.setInterval(() => this.sendHeartbeat(), time); + } + + /** + * Sends a heartbeat to the WebSocket. + * If this shard didn't receive a heartbeat last time, it will destroy it and reconnect + * @param {string} [tag='HeartbeatTimer'] What caused this heartbeat to be sent + * @param {boolean} [ignoreHeartbeatAck] If we should send the heartbeat forcefully. + * @private + */ + sendHeartbeat( + tag = 'HeartbeatTimer', + ignoreHeartbeatAck = [Status.WAITING_FOR_GUILDS, Status.IDENTIFYING, Status.RESUMING].includes(this.status), + ) { + if (ignoreHeartbeatAck && !this.lastHeartbeatAcked) { + this.debug(`[${tag}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`); + } else if (!this.lastHeartbeatAcked) { + this.debug( + `[${tag}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting. + Status : ${STATUS_KEYS[this.status]} + Sequence : ${this.sequence} + Connection State: ${this.connection ? CONNECTION_STATE[this.connection.readyState] : 'No Connection??'}`, + ); + + this.destroy({ closeCode: 4009, reset: true }); + return; + } + + this.debug(`[${tag}] Sending a heartbeat.`); + this.lastHeartbeatAcked = false; + this.lastPingTimestamp = Date.now(); + this.send({ op: OPCodes.HEARTBEAT, d: this.sequence }, true); + } + + /** + * Acknowledges a heartbeat. + * @private + */ + ackHeartbeat() { + this.lastHeartbeatAcked = true; + const latency = Date.now() - this.lastPingTimestamp; + this.debug(`Heartbeat acknowledged, latency of ${latency}ms.`); + this.ping = latency; + } + + /** + * Identifies the client on the connection. + * @private + * @returns {void} + */ + identify() { + return this.sessionID ? this.identifyResume() : this.identifyNew(); + } + + /** + * Identifies as a new connection on the gateway. + * @private + */ + identifyNew() { + const { client } = this.manager; + if (!client.token) { + this.debug('[IDENTIFY] No token available to identify a new session.'); + return; + } + + this.status = Status.IDENTIFYING; + + // Clone the identify payload and assign the token and shard info + const d = { + ...client.options.ws, + token: client.token, + shard: [this.id, Number(client.options.shardCount)], + }; + + this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount}`); + this.send({ op: OPCodes.IDENTIFY, d }, true); + } + + /** + * Resumes a session on the gateway. + * @private + */ + identifyResume() { + if (!this.sessionID) { + this.debug('[RESUME] No session ID was present; identifying as a new session.'); + this.identifyNew(); + return; + } + + this.status = Status.RESUMING; + + this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`); + + const d = { + token: this.manager.client.token, + session_id: this.sessionID, + seq: this.closeSequence, + }; + + this.send({ op: OPCodes.RESUME, d }, true); + } + + /** + * Adds a packet to the queue to be sent to the gateway. + * If you use this method, make sure you understand that you need to provide + * a full [Payload](https://discord.com/developers/docs/topics/gateway#commands-and-events-gateway-commands). + * Do not use this method if you don't know what you're doing. + * @param {Object} data The full packet to send + * @param {boolean} [important=false] If this packet should be added first in queue + */ + send(data, important = false) { + this.ratelimit.queue[important ? 'unshift' : 'push'](data); + this.processQueue(); + } + + /** + * Sends data, bypassing the queue. + * @param {Object} data Packet to send + * @returns {void} + * @private + */ + _send(data) { + if (!this.connection || this.connection.readyState !== WebSocket.OPEN) { + this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`); + this.destroy({ close: 4000 }); + return; + } + + this.connection.send(WebSocket.pack(data), err => { + if (err) this.manager.client.emit(Events.SHARD_ERROR, err, this.id); + }); + } + + /** + * Processes the current WebSocket queue. + * @returns {void} + * @private + */ + processQueue() { + if (this.ratelimit.remaining === 0) return; + if (this.ratelimit.queue.length === 0) return; + if (this.ratelimit.remaining === this.ratelimit.total) { + this.ratelimit.timer = this.manager.client.setTimeout(() => { + this.ratelimit.remaining = this.ratelimit.total; + this.processQueue(); + }, this.ratelimit.time); + } + while (this.ratelimit.remaining > 0) { + const item = this.ratelimit.queue.shift(); + if (!item) return; + this._send(item); + this.ratelimit.remaining--; + } + } + + /** + * Destroys this shard and closes its WebSocket connection. + * @param {Object} [options={ closeCode: 1000, reset: false, emit: true, log: true }] Options for destroying the shard + * @private + */ + destroy({ closeCode = 1000, reset = false, emit = true, log = true } = {}) { + if (log) { + this.debug(`[DESTROY] + Close Code : ${closeCode} + Reset : ${reset} + Emit DESTROYED: ${emit}`); + } + + // Step 0: Remove all timers + this.setHeartbeatTimer(-1); + this.setHelloTimeout(-1); + + // Step 1: Close the WebSocket connection, if any, otherwise, emit DESTROYED + if (this.connection) { + // If the connection is currently opened, we will (hopefully) receive close + if (this.connection.readyState === WebSocket.OPEN) { + this.connection.close(closeCode); + } else { + // Connection is not OPEN + this.debug(`WS State: ${CONNECTION_STATE[this.connection.readyState]}`); + // Remove listeners from the connection + this._cleanupConnection(); + // Attempt to close the connection just in case + try { + this.connection.close(closeCode); + } catch { + // No-op + } + // Emit the destroyed event if needed + if (emit) this._emitDestroyed(); + } + } else if (emit) { + // We requested a destroy, but we had no connection. Emit destroyed + this._emitDestroyed(); + } + + // Step 2: Null the connection object + this.connection = null; + + // Step 3: Set the shard status to DISCONNECTED + this.status = Status.DISCONNECTED; + + // Step 4: Cache the old sequence (use to attempt a resume) + if (this.sequence !== -1) this.closeSequence = this.sequence; + + // Step 5: Reset the sequence and session ID if requested + if (reset) { + this.sequence = -1; + this.sessionID = null; + } + + // Step 6: reset the ratelimit data + this.ratelimit.remaining = this.ratelimit.total; + this.ratelimit.queue.length = 0; + if (this.ratelimit.timer) { + this.manager.client.clearTimeout(this.ratelimit.timer); + this.ratelimit.timer = null; + } + } + + /** + * Cleans up the WebSocket connection listeners. + * @private + */ + _cleanupConnection() { + this.connection.onopen = this.connection.onclose = this.connection.onerror = this.connection.onmessage = null; + } + + /** + * Emits the DESTROYED event on the shard + * @private + */ + _emitDestroyed() { + /** + * Emitted when a shard is destroyed, but no WebSocket connection was present. + * @private + * @event WebSocketShard#destroyed + */ + this.emit(ShardEvents.DESTROYED); + } +} + +module.exports = WebSocketShard; diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js new file mode 100644 index 0000000..d6d560d --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.ChannelCreate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js new file mode 100644 index 0000000..cb9f3d8 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.ChannelDelete.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js new file mode 100644 index 0000000..13e6f0f --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js @@ -0,0 +1,22 @@ +'use strict'; + +const { Events } = require('../../../util/Constants'); + +module.exports = (client, { d: data }) => { + const channel = client.channels.cache.get(data.channel_id); + const time = new Date(data.last_pin_timestamp); + + if (channel && !Number.isNaN(time.getTime())) { + // Discord sends null for last_pin_timestamp if the last pinned message was removed + channel.lastPinTimestamp = time.getTime() || null; + + /** + * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event, + * not much information can be provided easily here - you need to manually check the pins yourself. + * @event Client#channelPinsUpdate + * @param {DMChannel|TextChannel} channel The channel that the pins update occurred in + * @param {Date} time The time of the pins update + */ + client.emit(Events.CHANNEL_PINS_UPDATE, channel, time); + } +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js new file mode 100644 index 0000000..d441478 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js @@ -0,0 +1,16 @@ +'use strict'; + +const { Events } = require('../../../util/Constants'); + +module.exports = (client, packet) => { + const { old, updated } = client.actions.ChannelUpdate.handle(packet.d); + if (old && updated) { + /** + * Emitted whenever a channel is updated - e.g. name change, topic change, channel type change. + * @event Client#channelUpdate + * @param {DMChannel|GuildChannel} oldChannel The channel before the update + * @param {DMChannel|GuildChannel} newChannel The channel after the update + */ + client.emit(Events.CHANNEL_UPDATE, old, updated); + } +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js new file mode 100644 index 0000000..5d4a096 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js @@ -0,0 +1,16 @@ +'use strict'; + +const { Events } = require('../../../util/Constants'); + +module.exports = (client, { d: data }) => { + const guild = client.guilds.cache.get(data.guild_id); + const user = client.users.add(data.user); + + /** + * Emitted whenever a member is banned from a guild. + * @event Client#guildBanAdd + * @param {Guild} guild The guild that the ban occurred in + * @param {User} user The user that was banned + */ + if (guild && user) client.emit(Events.GUILD_BAN_ADD, guild, user); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js new file mode 100644 index 0000000..8389e46 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildBanRemove.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js new file mode 100644 index 0000000..6743204 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js @@ -0,0 +1,36 @@ +'use strict'; + +const { Events, Status } = require('../../../util/Constants'); + +module.exports = async (client, { d: data }, shard) => { + let guild = client.guilds.cache.get(data.id); + if (guild) { + if (!guild.available && !data.unavailable) { + // A newly available guild + guild._patch(data); + // If the client was ready before and we had unavailable guilds, fetch them + if (client.ws.status === Status.READY && client.options.fetchAllMembers) { + await guild.members + .fetch() + .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`)); + } + } + } else { + // A new guild + data.shardID = shard.id; + guild = client.guilds.add(data); + if (client.ws.status === Status.READY) { + /** + * Emitted whenever the client joins a guild. + * @event Client#guildCreate + * @param {Guild} guild The created guild + */ + if (client.options.fetchAllMembers) { + await guild.members + .fetch() + .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`)); + } + client.emit(Events.GUILD_CREATE, guild); + } + } +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js new file mode 100644 index 0000000..27a3256 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildDelete.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js new file mode 100644 index 0000000..e23b671 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildEmojisUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js new file mode 100644 index 0000000..e90a72c --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildIntegrationsUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js new file mode 100644 index 0000000..2a04c68 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js @@ -0,0 +1,30 @@ +'use strict'; + +const Collection = require('../../../util/Collection'); +const { Events } = require('../../../util/Constants'); + +module.exports = (client, { d: data }) => { + const guild = client.guilds.cache.get(data.guild_id); + if (!guild) return; + const members = new Collection(); + + for (const member of data.members) members.set(member.user.id, guild.members.add(member)); + if (data.presences) { + for (const presence of data.presences) guild.presences.add(Object.assign(presence, { guild })); + } + /** + * Emitted whenever a chunk of guild members is received (all members come from the same guild). + * @event Client#guildMembersChunk + * @param {Collection} members The members in the chunk + * @param {Guild} guild The guild related to the member chunk + * @param {Object} chunk Properties of the received chunk + * @param {number} chunk.index Index of the received chunk + * @param {number} chunk.count Number of chunks the client should receive + * @param {?string} chunk.nonce Nonce for this chunk + */ + client.emit(Events.GUILD_MEMBERS_CHUNK, members, guild, { + count: data.chunk_count, + index: data.chunk_index, + nonce: data.nonce, + }); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js new file mode 100644 index 0000000..5128756 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js @@ -0,0 +1,19 @@ +'use strict'; + +const { Events, Status } = require('../../../util/Constants'); + +module.exports = (client, { d: data }, shard) => { + const guild = client.guilds.cache.get(data.guild_id); + if (guild) { + guild.memberCount++; + const member = guild.members.add(data); + if (shard.status === Status.READY) { + /** + * Emitted whenever a user joins a guild. + * @event Client#guildMemberAdd + * @param {GuildMember} member The member that has joined a guild + */ + client.emit(Events.GUILD_MEMBER_ADD, member); + } + } +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js new file mode 100644 index 0000000..72432af --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet, shard) => { + client.actions.GuildMemberRemove.handle(packet.d, shard); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js new file mode 100644 index 0000000..cafc6bd --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet, shard) => { + client.actions.GuildMemberUpdate.handle(packet.d, shard); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js new file mode 100644 index 0000000..da9e7bc --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildRoleCreate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js new file mode 100644 index 0000000..cdc6353 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildRoleDelete.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js new file mode 100644 index 0000000..3a9b62e --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildRoleUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js new file mode 100644 index 0000000..fd0012a --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js new file mode 100644 index 0000000..50a2e72 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.InviteCreate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js new file mode 100644 index 0000000..5971852 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.InviteDelete.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js new file mode 100644 index 0000000..c9b79a8 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageCreate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js new file mode 100644 index 0000000..85ae2bc --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageDelete.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js new file mode 100644 index 0000000..fbcf80f --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageDeleteBulk.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js new file mode 100644 index 0000000..e219b4a --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageReactionAdd.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js new file mode 100644 index 0000000..2980e69 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageReactionRemove.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js new file mode 100644 index 0000000..ead80f7 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageReactionRemoveAll.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js new file mode 100644 index 0000000..579444c --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageReactionRemoveEmoji.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js new file mode 100644 index 0000000..7428e90 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js @@ -0,0 +1,16 @@ +'use strict'; + +const { Events } = require('../../../util/Constants'); + +module.exports = (client, packet) => { + const { old, updated } = client.actions.MessageUpdate.handle(packet.d); + if (old && updated) { + /** + * Emitted whenever a message is updated - e.g. embed or content change. + * @event Client#messageUpdate + * @param {Message} oldMessage The message before the update + * @param {Message} newMessage The message after the update + */ + client.emit(Events.MESSAGE_UPDATE, old, updated); + } +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js new file mode 100644 index 0000000..bde3629 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.PresenceUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/READY.js b/node_modules/discord.js/src/client/websocket/handlers/READY.js new file mode 100644 index 0000000..c38b681 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/READY.js @@ -0,0 +1,21 @@ +'use strict'; + +let ClientUser; + +module.exports = (client, { d: data }, shard) => { + if (client.user) { + client.user._patch(data.user); + } else { + if (!ClientUser) ClientUser = require('../../../structures/ClientUser'); + const clientUser = new ClientUser(client, data.user); + client.user = clientUser; + client.users.cache.set(clientUser.id, clientUser); + } + + for (const guild of data.guilds) { + guild.shardID = shard.id; + client.guilds.add(guild); + } + + shard.checkReady(); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js new file mode 100644 index 0000000..5e5f403 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js @@ -0,0 +1,14 @@ +'use strict'; + +const { Events } = require('../../../util/Constants'); + +module.exports = (client, packet, shard) => { + const replayed = shard.sequence - shard.closeSequence; + /** + * Emitted when a shard resumes successfully. + * @event Client#shardResume + * @param {number} id The shard ID that resumed + * @param {number} replayedEvents The amount of replayed events + */ + client.emit(Events.SHARD_RESUME, shard.id, replayed); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js b/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js new file mode 100644 index 0000000..9a56a54 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.TypingStart.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js new file mode 100644 index 0000000..a02bf58 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.UserUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js new file mode 100644 index 0000000..f9cf534 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = (client, packet) => { + client.emit('debug', `[VOICE] received voice server: ${JSON.stringify(packet)}`); + client.voice.onVoiceServer(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js new file mode 100644 index 0000000..dbff6ea --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.VoiceStateUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js new file mode 100644 index 0000000..46cacee --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.WebhooksUpdate.handle(packet.d); +}; diff --git a/node_modules/discord.js/src/client/websocket/handlers/index.js b/node_modules/discord.js/src/client/websocket/handlers/index.js new file mode 100644 index 0000000..d69c105 --- /dev/null +++ b/node_modules/discord.js/src/client/websocket/handlers/index.js @@ -0,0 +1,13 @@ +'use strict'; + +const { WSEvents } = require('../../../util/Constants'); + +const handlers = {}; + +for (const name of Object.keys(WSEvents)) { + try { + handlers[name] = require(`./${name}.js`); + } catch {} // eslint-disable-line no-empty +} + +module.exports = handlers; diff --git a/node_modules/discord.js/src/errors/DJSError.js b/node_modules/discord.js/src/errors/DJSError.js new file mode 100644 index 0000000..157ca66 --- /dev/null +++ b/node_modules/discord.js/src/errors/DJSError.js @@ -0,0 +1,61 @@ +'use strict'; + +// Heavily inspired by node's `internal/errors` module + +const kCode = Symbol('code'); +const messages = new Map(); + +/** + * Extend an error of some sort into a DiscordjsError. + * @param {Error} Base Base error to extend + * @returns {DiscordjsError} + */ +function makeDiscordjsError(Base) { + return class DiscordjsError extends Base { + constructor(key, ...args) { + super(message(key, args)); + this[kCode] = key; + if (Error.captureStackTrace) Error.captureStackTrace(this, DiscordjsError); + } + + get name() { + return `${super.name} [${this[kCode]}]`; + } + + get code() { + return this[kCode]; + } + }; +} + +/** + * Format the message for an error. + * @param {string} key Error key + * @param {Array<*>} args Arguments to pass for util format or as function args + * @returns {string} Formatted string + */ +function message(key, args) { + if (typeof key !== 'string') throw new Error('Error message key must be a string'); + const msg = messages.get(key); + if (!msg) throw new Error(`An invalid error message key was used: ${key}.`); + if (typeof msg === 'function') return msg(...args); + if (args === undefined || args.length === 0) return msg; + args.unshift(msg); + return String(...args); +} + +/** + * Register an error code and message. + * @param {string} sym Unique name for the error + * @param {*} val Value of the error + */ +function register(sym, val) { + messages.set(sym, typeof val === 'function' ? val : String(val)); +} + +module.exports = { + register, + Error: makeDiscordjsError(Error), + TypeError: makeDiscordjsError(TypeError), + RangeError: makeDiscordjsError(RangeError), +}; diff --git a/node_modules/discord.js/src/errors/Messages.js b/node_modules/discord.js/src/errors/Messages.js new file mode 100644 index 0000000..a68cd2d --- /dev/null +++ b/node_modules/discord.js/src/errors/Messages.js @@ -0,0 +1,111 @@ +'use strict'; + +const { register } = require('./DJSError'); + +const Messages = { + CLIENT_INVALID_OPTION: (prop, must) => `The ${prop} option must be ${must}`, + CLIENT_INVALID_PROVIDED_SHARDS: 'None of the provided shards were valid.', + + TOKEN_INVALID: 'An invalid token was provided.', + TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.', + + WS_CLOSE_REQUESTED: 'WebSocket closed due to user request.', + WS_CONNECTION_EXISTS: 'There is already an existing WebSocket connection.', + WS_NOT_OPEN: (data = 'data') => `Websocket not open to send ${data}`, + + BITFIELD_INVALID: 'Invalid bitfield flag or number.', + + SHARDING_INVALID: 'Invalid shard settings were provided.', + SHARDING_REQUIRED: 'This session would have handled too many guilds - Sharding is required.', + INVALID_INTENTS: 'Invalid intent provided for WebSocket intents.', + DISALLOWED_INTENTS: 'Privileged intent provided is not enabled or whitelisted.', + SHARDING_NO_SHARDS: 'No shards have been spawned.', + SHARDING_IN_PROCESS: 'Shards are still being spawned.', + SHARDING_SHARD_NOT_FOUND: id => `Shard ${id} could not be found.`, + SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`, + SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`, + SHARDING_WORKER_EXISTS: id => `Shard ${id} already has an active worker.`, + SHARDING_READY_TIMEOUT: id => `Shard ${id}'s Client took too long to become ready.`, + SHARDING_READY_DISCONNECTED: id => `Shard ${id}'s Client disconnected before becoming ready.`, + SHARDING_READY_DIED: id => `Shard ${id}'s process exited before its Client became ready.`, + SHARDING_NO_CHILD_EXISTS: id => `Shard ${id} has no active process or worker.`, + SHARDING_SHARD_MISCALCULATION: (shard, guild, count) => + `Calculated invalid shard ${shard} for guild ${guild} with ${count} shards.`, + + COLOR_RANGE: 'Color must be within the range 0 - 16777215 (0xFFFFFF).', + COLOR_CONVERT: 'Unable to convert color to a number.', + + EMBED_FIELD_NAME: 'MessageEmbed field names may not be empty.', + EMBED_FIELD_VALUE: 'MessageEmbed field values may not be empty.', + + FILE_NOT_FOUND: file => `File could not be found: ${file}`, + + USER_NO_DMCHANNEL: 'No DM Channel exists!', + + VOICE_INVALID_HEARTBEAT: 'Tried to set voice heartbeat but no valid interval was specified.', + VOICE_USER_MISSING: "Couldn't resolve the user to create stream.", + VOICE_JOIN_CHANNEL: (full = false) => + `You do not have permission to join this voice channel${full ? '; it is full.' : '.'}`, + VOICE_CONNECTION_TIMEOUT: 'Connection not established within 15 seconds.', + VOICE_TOKEN_ABSENT: 'Token not provided from voice server packet.', + VOICE_SESSION_ABSENT: 'Session ID not supplied.', + VOICE_INVALID_ENDPOINT: 'Invalid endpoint received.', + VOICE_NO_BROWSER: 'Voice connections are not available in browsers.', + VOICE_CONNECTION_ATTEMPTS_EXCEEDED: attempts => `Too many connection attempts (${attempts}).`, + VOICE_JOIN_SOCKET_CLOSED: 'Tried to send join packet, but the WebSocket is not open.', + VOICE_PLAY_INTERFACE_NO_BROADCAST: 'A broadcast cannot be played in this context.', + VOICE_PLAY_INTERFACE_BAD_TYPE: 'Unknown stream type', + VOICE_PRISM_DEMUXERS_NEED_STREAM: 'To play a webm/ogg stream, you need to pass a ReadableStream.', + + VOICE_STATE_UNCACHED_MEMBER: 'The member of this voice state is uncached.', + VOICE_STATE_NOT_OWN: 'You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.', + VOICE_STATE_INVALID_TYPE: name => `${name} must be a boolean.`, + + UDP_SEND_FAIL: 'Tried to send a UDP packet, but there is no socket available.', + UDP_ADDRESS_MALFORMED: 'Malformed UDP address or port.', + UDP_CONNECTION_EXISTS: 'There is already an existing UDP connection.', + + REQ_RESOURCE_TYPE: 'The resource must be a string, Buffer or a valid file stream.', + + IMAGE_FORMAT: format => `Invalid image format: ${format}`, + IMAGE_SIZE: size => `Invalid image size: ${size}`, + + MESSAGE_BULK_DELETE_TYPE: 'The messages must be an Array, Collection, or number.', + MESSAGE_NONCE_TYPE: 'Message nonce must fit in an unsigned 64-bit integer.', + + TYPING_COUNT: 'Count must be at least 1', + + SPLIT_MAX_LEN: 'Chunk exceeds the max length and contains no split characters.', + + BAN_RESOLVE_ID: (ban = false) => `Couldn't resolve the user ID to ${ban ? 'ban' : 'unban'}.`, + FETCH_BAN_RESOLVE_ID: "Couldn't resolve the user ID to fetch the ban.", + + PRUNE_DAYS_TYPE: 'Days must be a number', + + GUILD_CHANNEL_RESOLVE: 'Could not resolve channel to a guild channel.', + GUILD_VOICE_CHANNEL_RESOLVE: 'Could not resolve channel to a guild voice channel.', + GUILD_CHANNEL_ORPHAN: 'Could not find a parent to this guild channel.', + GUILD_OWNED: 'Guild is owned by the client.', + GUILD_MEMBERS_TIMEOUT: "Members didn't arrive in time.", + GUILD_UNCACHED_ME: 'The client user as a member of this guild is uncached.', + + INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, + + WEBHOOK_MESSAGE: 'The message was not sent by a webhook.', + + EMOJI_TYPE: 'Emoji must be a string or GuildEmoji/ReactionEmoji', + EMOJI_MANAGED: 'Emoji is managed and has no Author.', + MISSING_MANAGE_EMOJIS_PERMISSION: guild => + `Client must have Manage Emoji permission in guild ${guild} to see emoji authors.`, + + REACTION_RESOLVE_USER: "Couldn't resolve the user ID to remove from the reaction.", + + VANITY_URL: 'This guild does not have the VANITY_URL feature enabled.', + + DELETE_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot delete them", + FETCH_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot fetch them", + + MEMBER_FETCH_NONCE_LENGTH: 'Nonce length must not exceed 32 characters.', +}; + +for (const [name, message] of Object.entries(Messages)) register(name, message); diff --git a/node_modules/discord.js/src/errors/index.js b/node_modules/discord.js/src/errors/index.js new file mode 100644 index 0000000..c94ddc7 --- /dev/null +++ b/node_modules/discord.js/src/errors/index.js @@ -0,0 +1,4 @@ +'use strict'; + +module.exports = require('./DJSError'); +module.exports.Messages = require('./Messages'); diff --git a/node_modules/discord.js/src/index.js b/node_modules/discord.js/src/index.js new file mode 100644 index 0000000..7319115 --- /dev/null +++ b/node_modules/discord.js/src/index.js @@ -0,0 +1,108 @@ +'use strict'; + +const Util = require('./util/Util'); + +module.exports = { + // "Root" classes (starting points) + BaseClient: require('./client/BaseClient'), + Client: require('./client/Client'), + Shard: require('./sharding/Shard'), + ShardClientUtil: require('./sharding/ShardClientUtil'), + ShardingManager: require('./sharding/ShardingManager'), + WebhookClient: require('./client/WebhookClient'), + + // Utilities + ActivityFlags: require('./util/ActivityFlags'), + BitField: require('./util/BitField'), + Collection: require('./util/Collection'), + Constants: require('./util/Constants'), + DataResolver: require('./util/DataResolver'), + BaseManager: require('./managers/BaseManager'), + DiscordAPIError: require('./rest/DiscordAPIError'), + HTTPError: require('./rest/HTTPError'), + MessageFlags: require('./util/MessageFlags'), + Intents: require('./util/Intents'), + Permissions: require('./util/Permissions'), + Speaking: require('./util/Speaking'), + Snowflake: require('./util/Snowflake'), + SnowflakeUtil: require('./util/Snowflake'), + Structures: require('./util/Structures'), + SystemChannelFlags: require('./util/SystemChannelFlags'), + UserFlags: require('./util/UserFlags'), + Util: Util, + version: require('../package.json').version, + + // Managers + ChannelManager: require('./managers/ChannelManager'), + GuildChannelManager: require('./managers/GuildChannelManager'), + GuildEmojiManager: require('./managers/GuildEmojiManager'), + GuildEmojiRoleManager: require('./managers/GuildEmojiRoleManager'), + GuildMemberManager: require('./managers/GuildMemberManager'), + GuildMemberRoleManager: require('./managers/GuildMemberRoleManager'), + GuildManager: require('./managers/GuildManager'), + ReactionManager: require('./managers/ReactionManager'), + ReactionUserManager: require('./managers/ReactionUserManager'), + MessageManager: require('./managers/MessageManager'), + PresenceManager: require('./managers/PresenceManager'), + RoleManager: require('./managers/RoleManager'), + UserManager: require('./managers/UserManager'), + + // Shortcuts to Util methods + discordSort: Util.discordSort, + escapeMarkdown: Util.escapeMarkdown, + fetchRecommendedShards: Util.fetchRecommendedShards, + resolveColor: Util.resolveColor, + resolveString: Util.resolveString, + splitMessage: Util.splitMessage, + + // Structures + Application: require('./structures/interfaces/Application'), + Base: require('./structures/Base'), + Activity: require('./structures/Presence').Activity, + APIMessage: require('./structures/APIMessage'), + BaseGuildEmoji: require('./structures/BaseGuildEmoji'), + CategoryChannel: require('./structures/CategoryChannel'), + Channel: require('./structures/Channel'), + ClientApplication: require('./structures/ClientApplication'), + get ClientUser() { + // This is a getter so that it properly extends any custom User class + return require('./structures/ClientUser'); + }, + Collector: require('./structures/interfaces/Collector'), + DMChannel: require('./structures/DMChannel'), + Emoji: require('./structures/Emoji'), + Guild: require('./structures/Guild'), + GuildAuditLogs: require('./structures/GuildAuditLogs'), + GuildChannel: require('./structures/GuildChannel'), + GuildEmoji: require('./structures/GuildEmoji'), + GuildMember: require('./structures/GuildMember'), + GuildPreview: require('./structures/GuildPreview'), + GuildTemplate: require('./structures/GuildTemplate'), + Integration: require('./structures/Integration'), + Invite: require('./structures/Invite'), + Message: require('./structures/Message'), + MessageAttachment: require('./structures/MessageAttachment'), + MessageCollector: require('./structures/MessageCollector'), + MessageEmbed: require('./structures/MessageEmbed'), + MessageMentions: require('./structures/MessageMentions'), + MessageReaction: require('./structures/MessageReaction'), + NewsChannel: require('./structures/NewsChannel'), + PermissionOverwrites: require('./structures/PermissionOverwrites'), + Presence: require('./structures/Presence').Presence, + ClientPresence: require('./structures/ClientPresence'), + ReactionCollector: require('./structures/ReactionCollector'), + ReactionEmoji: require('./structures/ReactionEmoji'), + RichPresenceAssets: require('./structures/Presence').RichPresenceAssets, + Role: require('./structures/Role'), + StoreChannel: require('./structures/StoreChannel'), + Team: require('./structures/Team'), + TeamMember: require('./structures/TeamMember'), + TextChannel: require('./structures/TextChannel'), + User: require('./structures/User'), + VoiceChannel: require('./structures/VoiceChannel'), + VoiceRegion: require('./structures/VoiceRegion'), + VoiceState: require('./structures/VoiceState'), + Webhook: require('./structures/Webhook'), + + WebSocket: require('./WebSocket'), +}; diff --git a/node_modules/discord.js/src/managers/BaseManager.js b/node_modules/discord.js/src/managers/BaseManager.js new file mode 100644 index 0000000..c11d191 --- /dev/null +++ b/node_modules/discord.js/src/managers/BaseManager.js @@ -0,0 +1,81 @@ +'use strict'; + +const Collection = require('../util/Collection'); +let Structures; + +/** + * Manages the API methods of a data model and holds its cache. + * @abstract + */ +class BaseManager { + constructor(client, iterable, holds, cacheType = Collection, ...cacheOptions) { + if (!Structures) Structures = require('../util/Structures'); + /** + * The data structure belonging to this manager + * @name BaseManager#holds + * @type {Function} + * @private + * @readonly + */ + Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) || holds }); + + /** + * The client that instantiated this Manager + * @name BaseManager#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The type of Collection of the Manager + * @type {Collection} + */ + this.cacheType = cacheType; + + /** + * Holds the cache for the data model + * @type {Collection} + */ + this.cache = new cacheType(...cacheOptions); + if (iterable) for (const i of iterable) this.add(i); + } + + add(data, cache = true, { id, extras = [] } = {}) { + const existing = this.cache.get(id || data.id); + if (existing && existing._patch && cache) existing._patch(data); + if (existing) return existing; + + const entry = this.holds ? new this.holds(this.client, data, ...extras) : data; + if (cache) this.cache.set(id || entry.id, entry); + return entry; + } + + /** + * Resolves a data entry to a data Object. + * @param {string|Object} idOrInstance The id or instance of something in this Manager + * @returns {?Object} An instance from this Manager + */ + resolve(idOrInstance) { + if (idOrInstance instanceof this.holds) return idOrInstance; + if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) || null; + return null; + } + + /** + * Resolves a data entry to a instance ID. + * @param {string|Object} idOrInstance The id or instance of something in this Manager + * @returns {?Snowflake} + */ + resolveID(idOrInstance) { + if (idOrInstance instanceof this.holds) return idOrInstance.id; + if (typeof idOrInstance === 'string') return idOrInstance; + return null; + } + + valueOf() { + return this.cache; + } +} + +module.exports = BaseManager; diff --git a/node_modules/discord.js/src/managers/ChannelManager.js b/node_modules/discord.js/src/managers/ChannelManager.js new file mode 100644 index 0000000..8d7d71e --- /dev/null +++ b/node_modules/discord.js/src/managers/ChannelManager.js @@ -0,0 +1,96 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const Channel = require('../structures/Channel'); +const { Events } = require('../util/Constants'); + +/** + * A manager of channels belonging to a client + * @extends {BaseManager} + */ +class ChannelManager extends BaseManager { + constructor(client, iterable) { + super(client, iterable, Channel); + } + + /** + * The cache of Channels + * @type {Collection} + * @name ChannelManager#cache + */ + + add(data, guild, cache = true) { + const existing = this.cache.get(data.id); + if (existing) { + if (existing._patch && cache) existing._patch(data); + if (guild) guild.channels.add(existing); + return existing; + } + + const channel = Channel.create(this.client, data, guild); + + if (!channel) { + this.client.emit(Events.DEBUG, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`); + return null; + } + + if (cache) this.cache.set(channel.id, channel); + + return channel; + } + + remove(id) { + const channel = this.cache.get(id); + if (channel.guild) channel.guild.channels.cache.delete(id); + this.cache.delete(id); + } + + /** + * Data that can be resolved to give a Channel object. This can be: + * * A Channel object + * * A Snowflake + * @typedef {Channel|Snowflake} ChannelResolvable + */ + + /** + * Resolves a ChannelResolvable to a Channel object. + * @method resolve + * @memberof ChannelManager + * @instance + * @param {ChannelResolvable} channel The channel resolvable to resolve + * @returns {?Channel} + */ + + /** + * Resolves a ChannelResolvable to a channel ID string. + * @method resolveID + * @memberof ChannelManager + * @instance + * @param {ChannelResolvable} channel The channel resolvable to resolve + * @returns {?Snowflake} + */ + + /** + * Obtains a channel from Discord, or the channel cache if it's already available. + * @param {Snowflake} id ID of the channel + * @param {boolean} [cache=true] Whether to cache the new channel object if it isn't already + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + * @example + * // Fetch a channel by its id + * client.channels.fetch('222109930545610754') + * .then(channel => console.log(channel.name)) + * .catch(console.error); + */ + async fetch(id, cache = true, force = false) { + if (!force) { + const existing = this.cache.get(id); + if (existing && !existing.partial) return existing; + } + + const data = await this.client.api.channels(id).get(); + return this.add(data, null, cache); + } +} + +module.exports = ChannelManager; diff --git a/node_modules/discord.js/src/managers/GuildChannelManager.js b/node_modules/discord.js/src/managers/GuildChannelManager.js new file mode 100644 index 0000000..ab4f1f2 --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildChannelManager.js @@ -0,0 +1,131 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const GuildChannel = require('../structures/GuildChannel'); +const PermissionOverwrites = require('../structures/PermissionOverwrites'); +const { ChannelTypes } = require('../util/Constants'); + +/** + * Manages API methods for GuildChannels and stores their cache. + * @extends {BaseManager} + */ +class GuildChannelManager extends BaseManager { + constructor(guild, iterable) { + super(guild.client, iterable, GuildChannel); + + /** + * The guild this Manager belongs to + * @type {Guild} + */ + this.guild = guild; + } + + /** + * The cache of this Manager + * @type {Collection} + * @name GuildChannelManager#cache + */ + + add(channel) { + const existing = this.cache.get(channel.id); + if (existing) return existing; + this.cache.set(channel.id, channel); + return channel; + } + + /** + * Data that can be resolved to give a Guild Channel object. This can be: + * * A GuildChannel object + * * A Snowflake + * @typedef {GuildChannel|Snowflake} GuildChannelResolvable + */ + + /** + * Resolves a GuildChannelResolvable to a Channel object. + * @method resolve + * @memberof GuildChannelManager + * @instance + * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve + * @returns {?GuildChannel} + */ + + /** + * Resolves a GuildChannelResolvable to a channel ID string. + * @method resolveID + * @memberof GuildChannelManager + * @instance + * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve + * @returns {?Snowflake} + */ + + /** + * Creates a new channel in the guild. + * @param {string} name The name of the new channel + * @param {Object} [options] Options + * @param {string} [options.type='text'] The type of the new channel, either `text`, `voice`, or `category` + * @param {string} [options.topic] The topic for the new channel + * @param {boolean} [options.nsfw] Whether the new channel is nsfw + * @param {number} [options.bitrate] Bitrate of the new channel in bits (only voice) + * @param {number} [options.userLimit] Maximum amount of users allowed in the new channel (only voice) + * @param {ChannelResolvable} [options.parent] Parent of the new channel + * @param {OverwriteResolvable[]|Collection} [options.permissionOverwrites] + * Permission overwrites of the new channel + * @param {number} [options.position] Position of the new channel + * @param {number} [options.rateLimitPerUser] The ratelimit per user for the channel + * @param {string} [options.reason] Reason for creating the channel + * @returns {Promise} + * @example + * // Create a new text channel + * guild.channels.create('new-general', { reason: 'Needed a cool new channel' }) + * .then(console.log) + * .catch(console.error); + * @example + * // Create a new channel with permission overwrites + * guild.channels.create('new-voice', { + * type: 'voice', + * permissionOverwrites: [ + * { + * id: message.author.id, + * deny: ['VIEW_CHANNEL'], + * }, + * ], + * }) + */ + async create(name, options = {}) { + let { + type, + topic, + nsfw, + bitrate, + userLimit, + parent, + permissionOverwrites, + position, + rateLimitPerUser, + reason, + } = options; + if (parent) parent = this.client.channels.resolveID(parent); + if (permissionOverwrites) { + permissionOverwrites = permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + } + + const data = await this.client.api.guilds(this.guild.id).channels.post({ + data: { + name, + topic, + type: type ? ChannelTypes[type.toUpperCase()] : ChannelTypes.TEXT, + nsfw, + bitrate, + user_limit: userLimit, + parent_id: parent, + position, + permission_overwrites: permissionOverwrites, + rate_limit_per_user: rateLimitPerUser, + }, + reason, + }); + return this.client.actions.ChannelCreate.handle(data).channel; + } +} + +module.exports = GuildChannelManager; diff --git a/node_modules/discord.js/src/managers/GuildEmojiManager.js b/node_modules/discord.js/src/managers/GuildEmojiManager.js new file mode 100644 index 0000000..acf3576 --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildEmojiManager.js @@ -0,0 +1,135 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { TypeError } = require('../errors'); +const GuildEmoji = require('../structures/GuildEmoji'); +const ReactionEmoji = require('../structures/ReactionEmoji'); +const Collection = require('../util/Collection'); +const DataResolver = require('../util/DataResolver'); +const { parseEmoji } = require('../util/Util'); + +/** + * Manages API methods for GuildEmojis and stores their cache. + * @extends {BaseManager} + */ +class GuildEmojiManager extends BaseManager { + constructor(guild, iterable) { + super(guild.client, iterable, GuildEmoji); + /** + * The guild this manager belongs to + * @type {Guild} + */ + this.guild = guild; + } + + /** + * The cache of GuildEmojis + * @type {Collection} + * @name GuildEmojiManager#cache + */ + + add(data, cache) { + return super.add(data, cache, { extras: [this.guild] }); + } + + /** + * Creates a new custom emoji in the guild. + * @param {BufferResolvable|Base64Resolvable} attachment The image for the emoji + * @param {string} name The name for the emoji + * @param {Object} [options] Options + * @param {Collection|RoleResolvable[]} [options.roles] Roles to limit the emoji to + * @param {string} [options.reason] Reason for creating the emoji + * @returns {Promise} The created emoji + * @example + * // Create a new emoji from a url + * guild.emojis.create('https://i.imgur.com/w3duR07.png', 'rip') + * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`)) + * .catch(console.error); + * @example + * // Create a new emoji from a file on your computer + * guild.emojis.create('./memes/banana.png', 'banana') + * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`)) + * .catch(console.error); + */ + async create(attachment, name, { roles, reason } = {}) { + attachment = await DataResolver.resolveImage(attachment); + if (!attachment) throw new TypeError('REQ_RESOURCE_TYPE'); + + const data = { image: attachment, name }; + if (roles) { + data.roles = []; + for (let role of roles instanceof Collection ? roles.values() : roles) { + role = this.guild.roles.resolve(role); + if (!role) { + return Promise.reject( + new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true), + ); + } + data.roles.push(role.id); + } + } + + return this.client.api + .guilds(this.guild.id) + .emojis.post({ data, reason }) + .then(emoji => this.client.actions.GuildEmojiCreate.handle(this.guild, emoji).emoji); + } + + /** + * Data that can be resolved into an GuildEmoji object. This can be: + * * A custom emoji ID + * * A GuildEmoji object + * * A ReactionEmoji object + * @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable + */ + + /** + * Resolves an EmojiResolvable to an Emoji object. + * @param {EmojiResolvable} emoji The Emoji resolvable to identify + * @returns {?GuildEmoji} + */ + resolve(emoji) { + if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id); + return super.resolve(emoji); + } + + /** + * Resolves an EmojiResolvable to an Emoji ID string. + * @param {EmojiResolvable} emoji The Emoji resolvable to identify + * @returns {?Snowflake} + */ + resolveID(emoji) { + if (emoji instanceof ReactionEmoji) return emoji.id; + return super.resolveID(emoji); + } + + /** + * Data that can be resolved to give an emoji identifier. This can be: + * * The unicode representation of an emoji + * * The ``, `<:name:id>`, `:name:id` or `a:name:id` emoji identifier string of an emoji + * * An EmojiResolvable + * @typedef {string|EmojiResolvable} EmojiIdentifierResolvable + */ + + /** + * Resolves an EmojiResolvable to an emoji identifier. + * @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve + * @returns {?string} + */ + resolveIdentifier(emoji) { + const emojiResolvable = this.resolve(emoji); + if (emojiResolvable) return emojiResolvable.identifier; + if (emoji instanceof ReactionEmoji) return emoji.identifier; + if (typeof emoji === 'string') { + const res = parseEmoji(emoji); + if (res && res.name.length) { + emoji = `${res.animated ? 'a:' : ''}${res.name}${res.id ? `:${res.id}` : ''}`; + } + if (!emoji.includes('%')) return encodeURIComponent(emoji); + else return emoji; + } + return null; + } +} + +module.exports = GuildEmojiManager; diff --git a/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js new file mode 100644 index 0000000..038571f --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js @@ -0,0 +1,119 @@ +'use strict'; + +const { TypeError } = require('../errors'); +const Collection = require('../util/Collection'); + +/** + * Manages API methods for roles belonging to emojis and stores their cache. + */ +class GuildEmojiRoleManager { + constructor(emoji) { + /** + * The emoji belonging to this manager + * @type {GuildEmoji} + */ + this.emoji = emoji; + /** + * The guild belonging to this manager + * @type {Guild} + */ + this.guild = emoji.guild; + /** + * The client belonging to this manager + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: emoji.client }); + } + + /** + * The filtered collection of roles of the guild emoji + * @type {Collection} + * @private + * @readonly + */ + get _roles() { + return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id)); + } + + /** + * The cache of roles belonging to this emoji + * @type {Collection} + * @readonly + */ + get cache() { + return this._roles; + } + + /** + * Adds a role (or multiple roles) to the list of roles that can use this emoji. + * @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to add + * @returns {Promise} + */ + add(roleOrRoles) { + if (roleOrRoles instanceof Collection) return this.add(roleOrRoles.keyArray()); + if (!Array.isArray(roleOrRoles)) return this.add([roleOrRoles]); + roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); + + if (roleOrRoles.includes(null)) { + return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true)); + } + + const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))]; + return this.set(newRoles); + } + + /** + * Removes a role (or multiple roles) from the list of roles that can use this emoji. + * @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to remove + * @returns {Promise} + */ + remove(roleOrRoles) { + if (roleOrRoles instanceof Collection) return this.remove(roleOrRoles.keyArray()); + if (!Array.isArray(roleOrRoles)) return this.remove([roleOrRoles]); + roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolveID(r)); + + if (roleOrRoles.includes(null)) { + return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true)); + } + + const newRoles = this._roles.keyArray().filter(role => !roleOrRoles.includes(role)); + return this.set(newRoles); + } + + /** + * Sets the role(s) that can use this emoji. + * @param {Collection|RoleResolvable[]} roles The roles or role IDs to apply + * @returns {Promise} + * @example + * // Set the emoji's roles to a single role + * guildEmoji.roles.set(['391156570408615936']) + * .then(console.log) + * .catch(console.error); + * @example + * // Remove all roles from an emoji + * guildEmoji.roles.set([]) + * .then(console.log) + * .catch(console.error); + */ + set(roles) { + return this.emoji.edit({ roles }); + } + + clone() { + const clone = new this.constructor(this.emoji); + clone._patch(this._roles.keyArray().slice()); + return clone; + } + + /** + * Patches the roles for this manager's cache + * @param {Snowflake[]} roles The new roles + * @private + */ + _patch(roles) { + this.emoji._roles = roles; + } +} + +module.exports = GuildEmojiRoleManager; diff --git a/node_modules/discord.js/src/managers/GuildManager.js b/node_modules/discord.js/src/managers/GuildManager.js new file mode 100644 index 0000000..b04a52c --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildManager.js @@ -0,0 +1,252 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const Guild = require('../structures/Guild'); +const GuildChannel = require('../structures/GuildChannel'); +const GuildEmoji = require('../structures/GuildEmoji'); +const GuildMember = require('../structures/GuildMember'); +const Invite = require('../structures/Invite'); +const Role = require('../structures/Role'); +const { + ChannelTypes, + Events, + VerificationLevels, + DefaultMessageNotifications, + ExplicitContentFilterLevels, +} = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); +const Permissions = require('../util/Permissions'); +const { resolveColor } = require('../util/Util'); + +/** + * Manages API methods for Guilds and stores their cache. + * @extends {BaseManager} + */ +class GuildManager extends BaseManager { + constructor(client, iterable) { + super(client, iterable, Guild); + } + + /** + * The cache of this Manager + * @type {Collection} + * @name GuildManager#cache + */ + + /** + * Data that resolves to give a Guild object. This can be: + * * A Guild object + * * A GuildChannel object + * * A GuildEmoji object + * * A Role object + * * A Snowflake + * * An Invite object + * @typedef {Guild|GuildChannel|GuildMember|GuildEmoji|Role|Snowflake|Invite} GuildResolvable + */ + + /** + * Partial data for a Role. + * @typedef {Object} PartialRoleData + * @property {number} [id] The ID for this role, used to set channel overrides, + * this is a placeholder and will be replaced by the API after consumption + * @property {string} [name] The name of the role + * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number + * @property {boolean} [hoist] Whether or not the role should be hoisted + * @property {number} [position] The position of the role + * @property {PermissionResolvable|number} [permissions] The permissions of the role + * @property {boolean} [mentionable] Whether or not the role should be mentionable + */ + + /** + * Partial overwrite data. + * @typedef {Object} PartialOverwriteData + * @property {number|Snowflake} id The Role or User ID for this overwrite + * @property {string} [type] The type of this overwrite + * @property {PermissionResolvable} [allow] The permissions to allow + * @property {PermissionResolvable} [deny] The permissions to deny + */ + + /** + * Partial data for a Channel. + * @typedef {Object} PartialChannelData + * @property {number} [id] The ID for this channel, used to set its parent, + * this is a placeholder and will be replaced by the API after consumption + * @property {number} [parentID] The parent ID for this channel + * @property {string} [type] The type of the channel + * @property {string} name The name of the channel + * @property {string} [topic] The topic of the text channel + * @property {boolean} [nsfw] Whether the channel is NSFW + * @property {number} [bitrate] The bitrate of the voice channel + * @property {number} [userLimit] The user limit of the channel + * @property {PartialOverwriteData} [permissionOverwrites] + * Overwrites of the channel + * @property {number} [rateLimitPerUser] The rate limit per user of the channel in seconds + */ + + /** + * Resolves a GuildResolvable to a Guild object. + * @method resolve + * @memberof GuildManager + * @instance + * @param {GuildResolvable} guild The guild resolvable to identify + * @returns {?Guild} + */ + resolve(guild) { + if ( + guild instanceof GuildChannel || + guild instanceof GuildMember || + guild instanceof GuildEmoji || + guild instanceof Role || + (guild instanceof Invite && guild.guild) + ) { + return super.resolve(guild.guild); + } + return super.resolve(guild); + } + + /** + * Resolves a GuildResolvable to a Guild ID string. + * @method resolveID + * @memberof GuildManager + * @instance + * @param {GuildResolvable} guild The guild resolvable to identify + * @returns {?Snowflake} + */ + resolveID(guild) { + if ( + guild instanceof GuildChannel || + guild instanceof GuildMember || + guild instanceof GuildEmoji || + guild instanceof Role || + (guild instanceof Invite && guild.guild) + ) { + return super.resolveID(guild.guild.id); + } + return super.resolveID(guild); + } + + /** + * Creates a guild. + * This is only available to bots in fewer than 10 guilds. + * @param {string} name The name of the guild + * @param {Object} [options] Options for the creating + * @param {number} [options.afkChannelID] The ID of the AFK channel + * @param {number} [options.afkTimeout] The AFK timeout in seconds + * @param {PartialChannelData[]} [options.channels] The channels for this guild + * @param {DefaultMessageNotifications} [options.defaultMessageNotifications] The default message notifications + * for the guild + * @param {ExplicitContentFilterLevel} [options.explicitContentFilter] The explicit content filter level for the guild + * @param {BufferResolvable|Base64Resolvable} [options.icon=null] The icon for the guild + * @param {string} [options.region] The region for the server, defaults to the closest one available + * @param {PartialRoleData[]} [options.roles] The roles for this guild, + * the first element of this array is used to change properties of the guild's everyone role. + * @param {number} [options.systemChannelID] The ID of the system channel + * @param {VerificationLevel} [options.verificationLevel] The verification level for the guild + * @returns {Promise} The guild that was created + */ + async create( + name, + { + afkChannelID, + afkTimeout, + channels = [], + defaultMessageNotifications, + explicitContentFilter, + icon = null, + region, + roles = [], + systemChannelID, + verificationLevel, + } = {}, + ) { + icon = await DataResolver.resolveImage(icon); + if (typeof verificationLevel !== 'undefined' && typeof verificationLevel !== 'number') { + verificationLevel = VerificationLevels.indexOf(verificationLevel); + } + if (typeof defaultMessageNotifications !== 'undefined' && typeof defaultMessageNotifications !== 'number') { + defaultMessageNotifications = DefaultMessageNotifications.indexOf(defaultMessageNotifications); + } + if (typeof explicitContentFilter !== 'undefined' && typeof explicitContentFilter !== 'number') { + explicitContentFilter = ExplicitContentFilterLevels.indexOf(explicitContentFilter); + } + for (const channel of channels) { + if (channel.type) channel.type = ChannelTypes[channel.type.toUpperCase()]; + channel.parent_id = channel.parentID; + delete channel.parentID; + if (!channel.permissionOverwrites) continue; + for (const overwrite of channel.permissionOverwrites) { + if (overwrite.allow) overwrite.allow = Permissions.resolve(overwrite.allow); + if (overwrite.deny) overwrite.deny = Permissions.resolve(overwrite.deny); + } + channel.permission_overwrites = channel.permissionOverwrites; + delete channel.permissionOverwrites; + } + for (const role of roles) { + if (role.color) role.color = resolveColor(role.color); + if (role.permissions) role.permissions = Permissions.resolve(role.permissions); + } + return new Promise((resolve, reject) => + this.client.api.guilds + .post({ + data: { + name, + region, + icon, + verification_level: verificationLevel, + default_message_notifications: defaultMessageNotifications, + explicit_content_filter: explicitContentFilter, + roles, + channels, + afk_channel_id: afkChannelID, + afk_timeout: afkTimeout, + system_channel_id: systemChannelID, + }, + }) + .then(data => { + if (this.client.guilds.cache.has(data.id)) return resolve(this.client.guilds.cache.get(data.id)); + + const handleGuild = guild => { + if (guild.id === data.id) { + this.client.clearTimeout(timeout); + this.client.removeListener(Events.GUILD_CREATE, handleGuild); + this.client.decrementMaxListeners(); + resolve(guild); + } + }; + this.client.incrementMaxListeners(); + this.client.on(Events.GUILD_CREATE, handleGuild); + + const timeout = this.client.setTimeout(() => { + this.client.removeListener(Events.GUILD_CREATE, handleGuild); + this.client.decrementMaxListeners(); + resolve(this.client.guilds.add(data)); + }, 10000); + return undefined; + }, reject), + ); + } + + /** + * Obtains a guild from Discord, or the guild cache if it's already available. + * @param {Snowflake} id ID of the guild + * @param {boolean} [cache=true] Whether to cache the new guild object if it isn't already + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + * @example + * // Fetch a guild by its id + * client.guilds.fetch('222078108977594368') + * .then(guild => console.log(guild.name)) + * .catch(console.error); + */ + async fetch(id, cache = true, force = false) { + if (!force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + + const data = await this.client.api.guilds(id).get({ query: { with_counts: true } }); + return this.add(data, cache); + } +} + +module.exports = GuildManager; diff --git a/node_modules/discord.js/src/managers/GuildMemberManager.js b/node_modules/discord.js/src/managers/GuildMemberManager.js new file mode 100644 index 0000000..8dfa2d8 --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildMemberManager.js @@ -0,0 +1,325 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { Error, TypeError, RangeError } = require('../errors'); +const GuildMember = require('../structures/GuildMember'); +const Collection = require('../util/Collection'); +const { Events, OPCodes } = require('../util/Constants'); +const SnowflakeUtil = require('../util/Snowflake'); + +/** + * Manages API methods for GuildMembers and stores their cache. + * @extends {BaseManager} + */ +class GuildMemberManager extends BaseManager { + constructor(guild, iterable) { + super(guild.client, iterable, GuildMember); + /** + * The guild this manager belongs to + * @type {Guild} + */ + this.guild = guild; + } + + /** + * The cache of this Manager + * @type {Collection} + * @name GuildMemberManager#cache + */ + + add(data, cache = true) { + return super.add(data, cache, { id: data.user.id, extras: [this.guild] }); + } + + /** + * Data that resolves to give a GuildMember object. This can be: + * * A GuildMember object + * * A User resolvable + * @typedef {GuildMember|UserResolvable} GuildMemberResolvable + */ + + /** + * Resolves a GuildMemberResolvable to a GuildMember object. + * @param {GuildMemberResolvable} member The user that is part of the guild + * @returns {?GuildMember} + */ + resolve(member) { + const memberResolvable = super.resolve(member); + if (memberResolvable) return memberResolvable; + const userResolvable = this.client.users.resolveID(member); + if (userResolvable) return super.resolve(userResolvable); + return null; + } + + /** + * Resolves a GuildMemberResolvable to a member ID string. + * @param {GuildMemberResolvable} member The user that is part of the guild + * @returns {?Snowflake} + */ + resolveID(member) { + const memberResolvable = super.resolveID(member); + if (memberResolvable) return memberResolvable; + const userResolvable = this.client.users.resolveID(member); + return this.cache.has(userResolvable) ? userResolvable : null; + } + + /** + * Options used to fetch a single member from a guild. + * @typedef {Object} FetchMemberOptions + * @property {UserResolvable} user The user to fetch + * @property {boolean} [cache=true] Whether or not to cache the fetched member + * @property {boolean} [force=false] Whether to skip the cache check and request the API + */ + + /** + * Options used to fetch multiple members from a guild. + * @typedef {Object} FetchMembersOptions + * @property {UserResolvable|UserResolvable[]} user The user(s) to fetch + * @property {?string} query Limit fetch to members with similar usernames + * @property {number} [limit=0] Maximum number of members to request + * @property {boolean} [withPresences=false] Whether or not to include the presences + * @property {number} [time=120e3] Timeout for receipt of members + * @property {?string} nonce Nonce for this request (32 characters max - default to base 16 now timestamp) + * @property {boolean} [force=false] Whether to skip the cache check and request the API + */ + + /** + * Fetches member(s) from Discord, even if they're offline. + * @param {UserResolvable|FetchMemberOptions|FetchMembersOptions} [options] If a UserResolvable, the user to fetch. + * If undefined, fetches all members. + * If a query, it limits the results to users with similar usernames. + * @returns {Promise|Promise>} + * @example + * // Fetch all members from a guild + * guild.members.fetch() + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch a single member + * guild.members.fetch('66564597481480192') + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch a single member without checking cache + * guild.members.fetch({ user, force: true }) + * .then(console.log) + * .catch(console.error) + * @example + * // Fetch a single member without caching + * guild.members.fetch({ user, cache: false }) + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch by an array of users including their presences + * guild.members.fetch({ user: ['66564597481480192', '191615925336670208'], withPresences: true }) + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch by query + * guild.members.fetch({ query: 'hydra', limit: 1 }) + * .then(console.log) + * .catch(console.error); + */ + fetch(options) { + if (!options) return this._fetchMany(); + const user = this.client.users.resolveID(options); + if (user) return this._fetchSingle({ user, cache: true }); + if (options.user) { + if (Array.isArray(options.user)) { + options.user = options.user.map(u => this.client.users.resolveID(u)); + return this._fetchMany(options); + } else { + options.user = this.client.users.resolveID(options.user); + } + if (!options.limit && !options.withPresences) return this._fetchSingle(options); + } + return this._fetchMany(options); + } + + /** + * Prunes members from the guild based on how long they have been inactive. + * It's recommended to set options.count to `false` for large guilds. + * @param {Object} [options] Prune options + * @param {number} [options.days=7] Number of days of inactivity required to kick + * @param {boolean} [options.dry=false] Get number of users that will be kicked, without actually kicking them + * @param {boolean} [options.count=true] Whether or not to return the number of users that have been kicked. + * @param {RoleResolvable[]} [options.roles=[]] Array of roles to bypass the "...and no roles" constraint when pruning + * @param {string} [options.reason] Reason for this prune + * @returns {Promise} The number of members that were/will be kicked + * @example + * // See how many members will be pruned + * guild.members.prune({ dry: true }) + * .then(pruned => console.log(`This will prune ${pruned} people!`)) + * .catch(console.error); + * @example + * // Actually prune the members + * guild.members.prune({ days: 1, reason: 'too many people!' }) + * .then(pruned => console.log(`I just pruned ${pruned} people!`)) + * .catch(console.error); + * @example + * // Include members with a specified role + * guild.members.prune({ days: 7, roles: ['657259391652855808'] }) + * .then(pruned => console.log(`I just pruned ${pruned} people!`)) + * .catch(console.error); + */ + prune({ days = 7, dry = false, count: compute_prune_count = true, roles = [], reason } = {}) { + if (typeof days !== 'number') throw new TypeError('PRUNE_DAYS_TYPE'); + + const query = { days }; + const resolvedRoles = []; + + for (const role of roles) { + const resolvedRole = this.guild.roles.resolveID(role); + if (!resolvedRole) { + return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array of Roles or Snowflakes', true)); + } + resolvedRoles.push(resolvedRole); + } + + if (resolvedRoles.length) { + query.include_roles = dry ? resolvedRoles.join(',') : resolvedRoles; + } + + const endpoint = this.client.api.guilds(this.guild.id).prune; + + if (dry) { + return endpoint.get({ query, reason }).then(data => data.pruned); + } + + return endpoint + .post({ + data: { ...query, compute_prune_count }, + reason, + }) + .then(data => data.pruned); + } + + /** + * Bans a user from the guild. + * @param {UserResolvable} user The user to ban + * @param {Object} [options] Options for the ban + * @param {number} [options.days=0] Number of days of messages to delete, must be between 0 and 7 + * @param {string} [options.reason] Reason for banning + * @returns {Promise} Result object will be resolved as specifically as possible. + * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot + * be resolved, the user ID will be the result. + * @example + * // Ban a user by ID (or with a user/guild member object) + * guild.members.ban('84484653687267328') + * .then(user => console.log(`Banned ${user.username || user.id || user} from ${guild.name}`)) + * .catch(console.error); + */ + ban(user, options = { days: 0 }) { + if (options.days) options.delete_message_days = options.days; + const id = this.client.users.resolveID(user); + if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true)); + return this.client.api + .guilds(this.guild.id) + .bans[id].put({ data: options }) + .then(() => { + if (user instanceof GuildMember) return user; + const _user = this.client.users.resolve(id); + if (_user) { + const member = this.resolve(_user); + return member || _user; + } + return id; + }); + } + + /** + * Unbans a user from the guild. + * @param {UserResolvable} user The user to unban + * @param {string} [reason] Reason for unbanning user + * @returns {Promise} + * @example + * // Unban a user by ID (or with a user/guild member object) + * guild.members.unban('84484653687267328') + * .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`)) + * .catch(console.error); + */ + unban(user, reason) { + const id = this.client.users.resolveID(user); + if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID')); + return this.client.api + .guilds(this.guild.id) + .bans[id].delete({ reason }) + .then(() => this.client.users.resolve(user)); + } + + _fetchSingle({ user, cache, force = false }) { + if (!force) { + const existing = this.cache.get(user); + if (existing && !existing.partial) return Promise.resolve(existing); + } + + return this.client.api + .guilds(this.guild.id) + .members(user) + .get() + .then(data => this.add(data, cache)); + } + + _fetchMany({ + limit = 0, + withPresences: presences = false, + user: user_ids, + query, + time = 120e3, + nonce = SnowflakeUtil.generate(), + force = false, + } = {}) { + return new Promise((resolve, reject) => { + if (this.guild.memberCount === this.cache.size && !query && !limit && !presences && !user_ids && !force) { + resolve(this.cache); + return; + } + if (!query && !user_ids) query = ''; + if (nonce.length > 32) throw new RangeError('MEMBER_FETCH_NONCE_LENGTH'); + this.guild.shard.send({ + op: OPCodes.REQUEST_GUILD_MEMBERS, + d: { + guild_id: this.guild.id, + presences, + user_ids, + query, + nonce, + limit, + }, + }); + const fetchedMembers = new Collection(); + const option = query || limit || presences || user_ids; + let i = 0; + const handler = (members, _, chunk) => { + timeout.refresh(); + if (chunk.nonce !== nonce) return; + i++; + for (const member of members.values()) { + if (option) fetchedMembers.set(member.id, member); + } + if ( + this.guild.memberCount <= this.cache.size || + (option && members.size < 1000) || + (limit && fetchedMembers.size >= limit) || + i === chunk.count + ) { + this.client.clearTimeout(timeout); + this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler); + this.client.decrementMaxListeners(); + let fetched = option ? fetchedMembers : this.cache; + if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first(); + resolve(fetched); + } + }; + const timeout = this.client.setTimeout(() => { + this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler); + this.client.decrementMaxListeners(); + reject(new Error('GUILD_MEMBERS_TIMEOUT')); + }, time); + this.client.incrementMaxListeners(); + this.client.on(Events.GUILD_MEMBERS_CHUNK, handler); + }); + } +} + +module.exports = GuildMemberManager; diff --git a/node_modules/discord.js/src/managers/GuildMemberRoleManager.js b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js new file mode 100644 index 0000000..9fc6248 --- /dev/null +++ b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js @@ -0,0 +1,161 @@ +'use strict'; + +const { TypeError } = require('../errors'); +const Collection = require('../util/Collection'); + +/** + * Manages API methods for roles of a GuildMember and stores their cache. + */ +class GuildMemberRoleManager { + constructor(member) { + /** + * The GuildMember this manager belongs to + * @type {GuildMember} + */ + this.member = member; + /** + * The Guild this manager belongs to + * @type {Guild} + */ + this.guild = member.guild; + Object.defineProperty(this, 'client', { value: member.client }); + } + + /** + * The filtered collection of roles of the member + * @type {Collection} + * @private + * @readonly + */ + get _roles() { + const everyone = this.guild.roles.everyone; + return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone); + } + + /** + * The roles of this member + * @type {Collection} + * @readonly + */ + get cache() { + return this._roles; + } + + /** + * The role of the member used to hoist them in a separate category in the users list + * @type {?Role} + * @readonly + */ + get hoist() { + const hoistedRoles = this._roles.filter(role => role.hoist); + if (!hoistedRoles.size) return null; + return hoistedRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); + } + + /** + * The role of the member used to set their color + * @type {?Role} + * @readonly + */ + get color() { + const coloredRoles = this._roles.filter(role => role.color); + if (!coloredRoles.size) return null; + return coloredRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); + } + + /** + * The role of the member with the highest position + * @type {Role} + * @readonly + */ + get highest() { + return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first()); + } + + /** + * Adds a role (or multiple roles) to the member. + * @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to add + * @param {string} [reason] Reason for adding the role(s) + * @returns {Promise} + */ + async add(roleOrRoles, reason) { + if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { + roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); + if (roleOrRoles.includes(null)) { + throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + } + + const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))]; + return this.set(newRoles, reason); + } else { + roleOrRoles = this.guild.roles.resolve(roleOrRoles); + if (roleOrRoles === null) { + throw new TypeError('INVALID_TYPE', 'roles', 'Role, Snowflake or Array or Collection of Roles or Snowflakes'); + } + + await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].put({ reason }); + + const clone = this.member._clone(); + clone._roles = [...this._roles.keys(), roleOrRoles.id]; + return clone; + } + } + + /** + * Removes a role (or multiple roles) from the member. + * @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to remove + * @param {string} [reason] Reason for removing the role(s) + * @returns {Promise} + */ + async remove(roleOrRoles, reason) { + if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { + roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); + if (roleOrRoles.includes(null)) { + throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + } + + const newRoles = this._roles.filter(role => !roleOrRoles.includes(role)); + return this.set(newRoles, reason); + } else { + roleOrRoles = this.guild.roles.resolve(roleOrRoles); + if (roleOrRoles === null) { + throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + } + + await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].delete({ reason }); + + const clone = this.member._clone(); + const newRoles = this._roles.filter(role => role.id !== roleOrRoles.id); + clone._roles = [...newRoles.keys()]; + return clone; + } + } + + /** + * Sets the roles applied to the member. + * @param {Collection|RoleResolvable[]} roles The roles or role IDs to apply + * @param {string} [reason] Reason for applying the roles + * @returns {Promise} + * @example + * // Set the member's roles to a single role + * guildMember.roles.set(['391156570408615936']) + * .then(console.log) + * .catch(console.error); + * @example + * // Remove all the roles from a member + * guildMember.roles.set([]) + * .then(member => console.log(`Member roles is now of ${member.roles.cache.size} size`)) + * .catch(console.error); + */ + set(roles, reason) { + return this.member.edit({ roles }, reason); + } + + clone() { + const clone = new this.constructor(this.member); + clone.member._roles = [...this._roles.keyArray()]; + return clone; + } +} + +module.exports = GuildMemberRoleManager; diff --git a/node_modules/discord.js/src/managers/MessageManager.js b/node_modules/discord.js/src/managers/MessageManager.js new file mode 100644 index 0000000..96a9643 --- /dev/null +++ b/node_modules/discord.js/src/managers/MessageManager.js @@ -0,0 +1,147 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { TypeError } = require('../errors'); +const Message = require('../structures/Message'); +const Collection = require('../util/Collection'); +const LimitedCollection = require('../util/LimitedCollection'); + +/** + * Manages API methods for Messages and holds their cache. + * @extends {BaseManager} + */ +class MessageManager extends BaseManager { + constructor(channel, iterable) { + super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize); + /** + * The channel that the messages belong to + * @type {TextBasedChannel} + */ + this.channel = channel; + } + + /** + * The cache of Messages + * @type {Collection} + * @name MessageManager#cache + */ + + add(data, cache) { + return super.add(data, cache, { extras: [this.channel] }); + } + + /** + * The parameters to pass in when requesting previous messages from a channel. `around`, `before` and + * `after` are mutually exclusive. All the parameters are optional. + * @typedef {Object} ChannelLogsQueryOptions + * @property {number} [limit=50] Number of messages to acquire + * @property {Snowflake} [before] ID of a message to get the messages that were posted before it + * @property {Snowflake} [after] ID of a message to get the messages that were posted after it + * @property {Snowflake} [around] ID of a message to get the messages that were posted around it + */ + + /** + * Gets a message, or messages, from this channel. + * The returned Collection does not contain reaction users of the messages if they were not cached. + * Those need to be fetched separately in such a case. + * @param {Snowflake|ChannelLogsQueryOptions} [message] The ID of the message to fetch, or query parameters. + * @param {boolean} [cache=true] Whether to cache the message(s) + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise|Promise>} + * @example + * // Get message + * channel.messages.fetch('99539446449315840') + * .then(message => console.log(message.content)) + * .catch(console.error); + * @example + * // Get messages + * channel.messages.fetch({ limit: 10 }) + * .then(messages => console.log(`Received ${messages.size} messages`)) + * .catch(console.error); + * @example + * // Get messages and filter by user ID + * channel.messages.fetch() + * .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`)) + * .catch(console.error); + */ + fetch(message, cache = true, force = false) { + return typeof message === 'string' ? this._fetchId(message, cache, force) : this._fetchMany(message, cache); + } + + /** + * Fetches the pinned messages of this channel and returns a collection of them. + * The returned Collection does not contain any reaction data of the messages. + * Those need to be fetched separately. + * @param {boolean} [cache=true] Whether to cache the message(s) + * @returns {Promise>} + * @example + * // Get pinned messages + * channel.messages.fetchPinned() + * .then(messages => console.log(`Received ${messages.size} messages`)) + * .catch(console.error); + */ + fetchPinned(cache = true) { + return this.client.api.channels[this.channel.id].pins.get().then(data => { + const messages = new Collection(); + for (const message of data) messages.set(message.id, this.add(message, cache)); + return messages; + }); + } + + /** + * Data that can be resolved to a Message object. This can be: + * * A Message + * * A Snowflake + * @typedef {Message|Snowflake} MessageResolvable + */ + + /** + * Resolves a MessageResolvable to a Message object. + * @method resolve + * @memberof MessageManager + * @instance + * @param {MessageResolvable} message The message resolvable to resolve + * @returns {?Message} + */ + + /** + * Resolves a MessageResolvable to a Message ID string. + * @method resolveID + * @memberof MessageManager + * @instance + * @param {MessageResolvable} message The message resolvable to resolve + * @returns {?Snowflake} + */ + + /** + * Deletes a message, even if it's not cached. + * @param {MessageResolvable} message The message to delete + * @param {string} [reason] Reason for deleting this message, if it does not belong to the client user + * @returns {Promise} + */ + async delete(message, reason) { + message = this.resolveID(message); + if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + await this.client.api.channels(this.channel.id).messages(message).delete({ reason }); + } + + async _fetchId(messageID, cache, force) { + if (!force) { + const existing = this.cache.get(messageID); + if (existing && !existing.partial) return existing; + } + + const data = await this.client.api.channels[this.channel.id].messages[messageID].get(); + return this.add(data, cache); + } + + async _fetchMany(options = {}, cache) { + const data = await this.client.api.channels[this.channel.id].messages.get({ query: options }); + const messages = new Collection(); + for (const message of data) messages.set(message.id, this.add(message, cache)); + return messages; + } +} + +module.exports = MessageManager; diff --git a/node_modules/discord.js/src/managers/PresenceManager.js b/node_modules/discord.js/src/managers/PresenceManager.js new file mode 100644 index 0000000..c02fe04 --- /dev/null +++ b/node_modules/discord.js/src/managers/PresenceManager.js @@ -0,0 +1,59 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { Presence } = require('../structures/Presence'); + +/** + * Manages API methods for Presences and holds their cache. + * @extends {BaseManager} + */ +class PresenceManager extends BaseManager { + constructor(client, iterable) { + super(client, iterable, Presence); + } + + /** + * The cache of Presences + * @type {Collection} + * @name PresenceManager#cache + */ + + add(data, cache) { + const existing = this.cache.get(data.user.id); + return existing ? existing.patch(data) : super.add(data, cache, { id: data.user.id }); + } + + /** + * Data that can be resolved to a Presence object. This can be: + * * A Presence + * * A UserResolvable + * * A Snowflake + * @typedef {Presence|UserResolvable|Snowflake} PresenceResolvable + */ + + /** + * Resolves a PresenceResolvable to a Presence object. + * @param {PresenceResolvable} presence The presence resolvable to resolve + * @returns {?Presence} + */ + resolve(presence) { + const presenceResolvable = super.resolve(presence); + if (presenceResolvable) return presenceResolvable; + const UserResolvable = this.client.users.resolveID(presence); + return super.resolve(UserResolvable) || null; + } + + /** + * Resolves a PresenceResolvable to a Presence ID string. + * @param {PresenceResolvable} presence The presence resolvable to resolve + * @returns {?Snowflake} + */ + resolveID(presence) { + const presenceResolvable = super.resolveID(presence); + if (presenceResolvable) return presenceResolvable; + const userResolvable = this.client.users.resolveID(presence); + return this.cache.has(userResolvable) ? userResolvable : null; + } +} + +module.exports = PresenceManager; diff --git a/node_modules/discord.js/src/managers/ReactionManager.js b/node_modules/discord.js/src/managers/ReactionManager.js new file mode 100644 index 0000000..e194d84 --- /dev/null +++ b/node_modules/discord.js/src/managers/ReactionManager.js @@ -0,0 +1,69 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const MessageReaction = require('../structures/MessageReaction'); + +/** + * Manages API methods for reactions and holds their cache. + * @extends {BaseManager} + */ +class ReactionManager extends BaseManager { + constructor(message, iterable) { + super(message.client, iterable, MessageReaction); + + /** + * The message that this manager belongs to + * @type {Message} + */ + this.message = message; + } + + add(data, cache) { + return super.add(data, cache, { id: data.emoji.id || data.emoji.name, extras: [this.message] }); + } + + /** + * The reaction cache of this manager + * @type {Collection} + * @name ReactionManager#cache + */ + + /** + * Data that can be resolved to a MessageReaction object. This can be: + * * A MessageReaction + * * A Snowflake + * @typedef {MessageReaction|Snowflake} MessageReactionResolvable + */ + + /** + * Resolves a MessageReactionResolvable to a MessageReaction object. + * @method resolve + * @memberof ReactionManager + * @instance + * @param {MessageReactionResolvable} reaction The MessageReaction to resolve + * @returns {?MessageReaction} + */ + + /** + * Resolves a MessageReactionResolvable to a MessageReaction ID string. + * @method resolveID + * @memberof ReactionManager + * @instance + * @param {MessageReactionResolvable} reaction The MessageReaction to resolve + * @returns {?Snowflake} + */ + + /** + * Removes all reactions from a message. + * @returns {Promise} + */ + removeAll() { + return this.client.api + .channels(this.message.channel.id) + .messages(this.message.id) + .reactions.delete() + .then(() => this.message); + } +} + +module.exports = ReactionManager; diff --git a/node_modules/discord.js/src/managers/ReactionUserManager.js b/node_modules/discord.js/src/managers/ReactionUserManager.js new file mode 100644 index 0000000..1d93e42 --- /dev/null +++ b/node_modules/discord.js/src/managers/ReactionUserManager.js @@ -0,0 +1,66 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { Error } = require('../errors'); +const Collection = require('../util/Collection'); + +/** + * Manages API methods for users who reacted to a reaction and stores their cache. + * @extends {BaseManager} + */ +class ReactionUserManager extends BaseManager { + constructor(client, iterable, reaction) { + super(client, iterable, { name: 'User' }); + /** + * The reaction that this manager belongs to + * @type {MessageReaction} + */ + this.reaction = reaction; + } + + /** + * The cache of this manager + * @type {Collection} + * @name ReactionUserManager#cache + */ + + /** + * Fetches the users that gave this reaction. Resolves with a collection of users, mapped by their IDs. + * @param {Object} [options] Options for fetching the users + * @param {number} [options.limit=100] The maximum amount of users to fetch, defaults to 100 + * @param {Snowflake} [options.before] Limit fetching users to those with an id lower than the supplied id + * @param {Snowflake} [options.after] Limit fetching users to those with an id greater than the supplied id + * @returns {Promise>} + */ + async fetch({ limit = 100, after, before } = {}) { + const message = this.reaction.message; + const data = await this.client.api.channels[message.channel.id].messages[message.id].reactions[ + this.reaction.emoji.identifier + ].get({ query: { limit, before, after } }); + const users = new Collection(); + for (const rawUser of data) { + const user = this.client.users.add(rawUser); + this.cache.set(user.id, user); + users.set(user.id, user); + } + return users; + } + + /** + * Removes a user from this reaction. + * @param {UserResolvable} [user=this.client.user] The user to remove the reaction of + * @returns {Promise} + */ + remove(user = this.client.user) { + const userID = this.client.users.resolveID(user); + if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER')); + const message = this.reaction.message; + return this.client.api.channels[message.channel.id].messages[message.id].reactions[this.reaction.emoji.identifier][ + userID === this.client.user.id ? '@me' : userID + ] + .delete() + .then(() => this.reaction); + } +} + +module.exports = ReactionUserManager; diff --git a/node_modules/discord.js/src/managers/RoleManager.js b/node_modules/discord.js/src/managers/RoleManager.js new file mode 100644 index 0000000..a1586b0 --- /dev/null +++ b/node_modules/discord.js/src/managers/RoleManager.js @@ -0,0 +1,146 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const Role = require('../structures/Role'); +const Permissions = require('../util/Permissions'); +const { resolveColor } = require('../util/Util'); + +/** + * Manages API methods for roles and stores their cache. + * @extends {BaseManager} + */ +class RoleManager extends BaseManager { + constructor(guild, iterable) { + super(guild.client, iterable, Role); + /** + * The guild belonging to this manager + * @type {Guild} + */ + this.guild = guild; + } + + /** + * The role cache of this manager + * @type {Collection} + * @name RoleManager#cache + */ + + add(data, cache) { + return super.add(data, cache, { extras: [this.guild] }); + } + + /** + * Obtains one or more roles from Discord, or the role cache if they're already available. + * @param {Snowflake} [id] ID or IDs of the role(s) + * @param {boolean} [cache=true] Whether to cache the new roles objects if it weren't already + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + * @example + * // Fetch all roles from the guild + * message.guild.roles.fetch() + * .then(roles => console.log(`There are ${roles.cache.size} roles.`)) + * .catch(console.error); + * @example + * // Fetch a single role + * message.guild.roles.fetch('222078108977594368') + * .then(role => console.log(`The role color is: ${role.color}`)) + * .catch(console.error); + */ + async fetch(id, cache = true, force = false) { + if (id && !force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + + // We cannot fetch a single role, as of this commit's date, Discord API throws with 405 + const roles = await this.client.api.guilds(this.guild.id).roles.get(); + for (const role of roles) this.add(role, cache); + return id ? this.cache.get(id) || null : this; + } + + /** + * Data that can be resolved to a Role object. This can be: + * * A Role + * * A Snowflake + * @typedef {Role|Snowflake} RoleResolvable + */ + + /** + * Resolves a RoleResolvable to a Role object. + * @method resolve + * @memberof RoleManager + * @instance + * @param {RoleResolvable} role The role resolvable to resolve + * @returns {?Role} + */ + + /** + * Resolves a RoleResolvable to a role ID string. + * @method resolveID + * @memberof RoleManager + * @instance + * @param {RoleResolvable} role The role resolvable to resolve + * @returns {?Snowflake} + */ + + /** + * Creates a new role in the guild with given information. + * The position will silently reset to 1 if an invalid one is provided, or none. + * @param {Object} [options] Options + * @param {RoleData} [options.data] The data to create the role with + * @param {string} [options.reason] Reason for creating this role + * @returns {Promise} + * @example + * // Create a new role + * guild.roles.create() + * .then(console.log) + * .catch(console.error); + * @example + * // Create a new role with data and a reason + * guild.roles.create({ + * data: { + * name: 'Super Cool People', + * color: 'BLUE', + * }, + * reason: 'we needed a role for Super Cool People', + * }) + * .then(console.log) + * .catch(console.error); + */ + create({ data = {}, reason } = {}) { + if (data.color) data.color = resolveColor(data.color); + if (data.permissions) data.permissions = Permissions.resolve(data.permissions); + + return this.guild.client.api + .guilds(this.guild.id) + .roles.post({ data, reason }) + .then(r => { + const { role } = this.client.actions.GuildRoleCreate.handle({ + guild_id: this.guild.id, + role: r, + }); + if (data.position) return role.setPosition(data.position, reason); + return role; + }); + } + + /** + * The `@everyone` role of the guild + * @type {Role} + * @readonly + */ + get everyone() { + return this.cache.get(this.guild.id); + } + + /** + * The role with the highest position in the cache + * @type {Role} + * @readonly + */ + get highest() { + return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first()); + } +} + +module.exports = RoleManager; diff --git a/node_modules/discord.js/src/managers/UserManager.js b/node_modules/discord.js/src/managers/UserManager.js new file mode 100644 index 0000000..8928715 --- /dev/null +++ b/node_modules/discord.js/src/managers/UserManager.js @@ -0,0 +1,72 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const GuildMember = require('../structures/GuildMember'); +const Message = require('../structures/Message'); +const User = require('../structures/User'); + +/** + * Manages API methods for users and stores their cache. + * @extends {BaseManager} + */ +class UserManager extends BaseManager { + constructor(client, iterable) { + super(client, iterable, User); + } + + /** + * The cache of this manager + * @type {Collection} + * @name UserManager#cache + */ + + /** + * Data that resolves to give a User object. This can be: + * * A User object + * * A Snowflake + * * A Message object (resolves to the message author) + * * A GuildMember object + * @typedef {User|Snowflake|Message|GuildMember} UserResolvable + */ + + /** + * Resolves a UserResolvable to a User object. + * @param {UserResolvable} user The UserResolvable to identify + * @returns {?User} + */ + resolve(user) { + if (user instanceof GuildMember) return user.user; + if (user instanceof Message) return user.author; + return super.resolve(user); + } + + /** + * Resolves a UserResolvable to a user ID string. + * @param {UserResolvable} user The UserResolvable to identify + * @returns {?Snowflake} + */ + resolveID(user) { + if (user instanceof GuildMember) return user.user.id; + if (user instanceof Message) return user.author.id; + return super.resolveID(user); + } + + /** + * Obtains a user from Discord, or the user cache if it's already available. + * @param {Snowflake} id ID of the user + * @param {boolean} [cache=true] Whether to cache the new user object if it isn't already + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + async fetch(id, cache = true, force = false) { + if (!force) { + const existing = this.cache.get(id); + if (existing && !existing.partial) return existing; + } + + const data = await this.client.api.users(id).get(); + return this.add(data, cache); + } +} + +module.exports = UserManager; diff --git a/node_modules/discord.js/src/managers/VoiceStateManager.js b/node_modules/discord.js/src/managers/VoiceStateManager.js new file mode 100644 index 0000000..35045f7 --- /dev/null +++ b/node_modules/discord.js/src/managers/VoiceStateManager.js @@ -0,0 +1,35 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); + +/** + * Manages API methods for VoiceStates and stores their cache. + * @extends {BaseManager} + */ +class VoiceStateManager extends BaseManager { + constructor(guild, iterable) { + super(guild.client, iterable, { name: 'VoiceState' }); + /** + * The guild this manager belongs to + * @type {Guild} + */ + this.guild = guild; + } + + /** + * The cache of this manager + * @type {Collection} + * @name VoiceStateManager#cache + */ + + add(data, cache = true) { + const existing = this.cache.get(data.user_id); + if (existing) return existing._patch(data); + + const entry = new this.holds(this.guild, data); + if (cache) this.cache.set(data.user_id, entry); + return entry; + } +} + +module.exports = VoiceStateManager; diff --git a/node_modules/discord.js/src/rest/APIRequest.js b/node_modules/discord.js/src/rest/APIRequest.js new file mode 100644 index 0000000..837b38f --- /dev/null +++ b/node_modules/discord.js/src/rest/APIRequest.js @@ -0,0 +1,67 @@ +'use strict'; + +const https = require('https'); +const FormData = require('@discordjs/form-data'); +const AbortController = require('abort-controller'); +const fetch = require('node-fetch'); +const { browser, UserAgent } = require('../util/Constants'); + +if (https.Agent) var agent = new https.Agent({ keepAlive: true }); + +class APIRequest { + constructor(rest, method, path, options) { + this.rest = rest; + this.client = rest.client; + this.method = method; + this.route = options.route; + this.options = options; + this.retries = 0; + + let queryString = ''; + if (options.query) { + const query = Object.entries(options.query) + .filter(([, value]) => ![null, 'null', 'undefined'].includes(value) && typeof value !== 'undefined') + .flatMap(([key, value]) => (Array.isArray(value) ? value.map(v => [key, v]) : [[key, value]])); + queryString = new URLSearchParams(query).toString(); + } + this.path = `${path}${queryString && `?${queryString}`}`; + } + + make() { + const API = + this.options.versioned === false + ? this.client.options.http.api + : `${this.client.options.http.api}/v${this.client.options.http.version}`; + const url = API + this.path; + let headers = {}; + + if (this.options.auth !== false) headers.Authorization = this.rest.getAuth(); + if (this.options.reason) headers['X-Audit-Log-Reason'] = encodeURIComponent(this.options.reason); + if (!browser) headers['User-Agent'] = UserAgent; + if (this.options.headers) headers = Object.assign(headers, this.options.headers); + + let body; + if (this.options.files && this.options.files.length) { + body = new FormData(); + for (const file of this.options.files) if (file && file.file) body.append(file.name, file.file, file.name); + if (typeof this.options.data !== 'undefined') body.append('payload_json', JSON.stringify(this.options.data)); + if (!browser) headers = Object.assign(headers, body.getHeaders()); + // eslint-disable-next-line eqeqeq + } else if (this.options.data != null) { + body = JSON.stringify(this.options.data); + headers['Content-Type'] = 'application/json'; + } + + const controller = new AbortController(); + const timeout = this.client.setTimeout(() => controller.abort(), this.client.options.restRequestTimeout); + return fetch(url, { + method: this.method, + headers, + agent, + body, + signal: controller.signal, + }).finally(() => this.client.clearTimeout(timeout)); + } +} + +module.exports = APIRequest; diff --git a/node_modules/discord.js/src/rest/APIRouter.js b/node_modules/discord.js/src/rest/APIRouter.js new file mode 100644 index 0000000..e85c739 --- /dev/null +++ b/node_modules/discord.js/src/rest/APIRouter.js @@ -0,0 +1,53 @@ +'use strict'; + +const noop = () => {}; // eslint-disable-line no-empty-function +const methods = ['get', 'post', 'delete', 'patch', 'put']; +const reflectors = [ + 'toString', + 'valueOf', + 'inspect', + 'constructor', + Symbol.toPrimitive, + Symbol.for('nodejs.util.inspect.custom'), +]; + +function buildRoute(manager) { + const route = ['']; + const handler = { + get(target, name) { + if (reflectors.includes(name)) return () => route.join('/'); + if (methods.includes(name)) { + const routeBucket = []; + for (let i = 0; i < route.length; i++) { + // Reactions routes and sub-routes all share the same bucket + if (route[i - 1] === 'reactions') break; + // Literal IDs should only be taken account if they are the Major ID (the Channel/Guild ID) + if (/\d{16,19}/g.test(route[i]) && !/channels|guilds/.test(route[i - 1])) routeBucket.push(':id'); + // All other parts of the route should be considered as part of the bucket identifier + else routeBucket.push(route[i]); + } + return options => + manager.request( + name, + route.join('/'), + Object.assign( + { + versioned: manager.versioned, + route: routeBucket.join('/'), + }, + options, + ), + ); + } + route.push(name); + return new Proxy(noop, handler); + }, + apply(target, _, args) { + route.push(...args.filter(x => x != null)); // eslint-disable-line eqeqeq + return new Proxy(noop, handler); + }, + }; + return new Proxy(noop, handler); +} + +module.exports = buildRoute; diff --git a/node_modules/discord.js/src/rest/AsyncQueue.js b/node_modules/discord.js/src/rest/AsyncQueue.js new file mode 100644 index 0000000..b465f6a --- /dev/null +++ b/node_modules/discord.js/src/rest/AsyncQueue.js @@ -0,0 +1,95 @@ +/** + * MIT License + * + * Copyright (c) 2020 kyranet, discord.js + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +'use strict'; + +// TODO(kyranet, vladfrangu): replace this with discord.js v13's core AsyncQueue. + +/** + * An async queue that preserves the stack and prevents lock-ups. + * @private + */ +class AsyncQueue { + constructor() { + /** + * The promises array. + * @type {Array<{promise: Promise, resolve: Function}>} + * @private + */ + this.promises = []; + } + + /** + * The remaining amount of queued promises + * @type {number} + */ + get remaining() { + return this.promises.length; + } + + /** + * Waits for last promise and queues a new one. + * @returns {Promise} + * @example + * const queue = new AsyncQueue(); + * async function request(url, options) { + * await queue.wait(); + * try { + * const result = await fetch(url, options); + * // Do some operations with 'result' + * } finally { + * // Remove first entry from the queue and resolve for the next entry + * queue.shift(); + * } + * } + * + * request(someUrl1, someOptions1); // Will call fetch() immediately + * request(someUrl2, someOptions2); // Will call fetch() after the first finished + * request(someUrl3, someOptions3); // Will call fetch() after the second finished + */ + wait() { + const next = this.promises.length ? this.promises[this.promises.length - 1].promise : Promise.resolve(); + let resolve; + const promise = new Promise(res => { + resolve = res; + }); + + this.promises.push({ + resolve, + promise, + }); + + return next; + } + + /** + * Frees the queue's lock for the next item to process. + */ + shift() { + const deferred = this.promises.shift(); + if (typeof deferred !== 'undefined') deferred.resolve(); + } +} + +module.exports = AsyncQueue; diff --git a/node_modules/discord.js/src/rest/DiscordAPIError.js b/node_modules/discord.js/src/rest/DiscordAPIError.js new file mode 100644 index 0000000..aebe513 --- /dev/null +++ b/node_modules/discord.js/src/rest/DiscordAPIError.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * Represents an error from the Discord API. + * @extends Error + */ +class DiscordAPIError extends Error { + constructor(path, error, method, status) { + super(); + const flattened = this.constructor.flattenErrors(error.errors || error).join('\n'); + this.name = 'DiscordAPIError'; + this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message || flattened; + + /** + * The HTTP method used for the request + * @type {string} + */ + this.method = method; + + /** + * The path of the request relative to the HTTP endpoint + * @type {string} + */ + this.path = path; + + /** + * HTTP error code returned by Discord + * @type {number} + */ + this.code = error.code; + + /** + * The HTTP status code + * @type {number} + */ + this.httpStatus = status; + } + + /** + * Flattens an errors object returned from the API into an array. + * @param {Object} obj Discord errors object + * @param {string} [key] Used internally to determine key names of nested fields + * @returns {string[]} + * @private + */ + static flattenErrors(obj, key = '') { + let messages = []; + + for (const [k, v] of Object.entries(obj)) { + if (k === 'message') continue; + const newKey = key ? (isNaN(k) ? `${key}.${k}` : `${key}[${k}]`) : k; + + if (v._errors) { + messages.push(`${newKey}: ${v._errors.map(e => e.message).join(' ')}`); + } else if (v.code || v.message) { + messages.push(`${v.code ? `${v.code}: ` : ''}${v.message}`.trim()); + } else if (typeof v === 'string') { + messages.push(v); + } else { + messages = messages.concat(this.flattenErrors(v, newKey)); + } + } + + return messages; + } +} + +module.exports = DiscordAPIError; diff --git a/node_modules/discord.js/src/rest/HTTPError.js b/node_modules/discord.js/src/rest/HTTPError.js new file mode 100644 index 0000000..2911467 --- /dev/null +++ b/node_modules/discord.js/src/rest/HTTPError.js @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Represents a HTTP error from a request. + * @extends Error + */ +class HTTPError extends Error { + constructor(message, name, code, method, path) { + super(message); + + /** + * The name of the error + * @type {string} + */ + this.name = name; + + /** + * HTTP error code returned from the request + * @type {number} + */ + this.code = code || 500; + + /** + * The HTTP method used for the request + * @type {string} + */ + this.method = method; + + /** + * The path of the request relative to the HTTP endpoint + * @type {string} + */ + this.path = path; + } +} + +module.exports = HTTPError; diff --git a/node_modules/discord.js/src/rest/RESTManager.js b/node_modules/discord.js/src/rest/RESTManager.js new file mode 100644 index 0000000..799f602 --- /dev/null +++ b/node_modules/discord.js/src/rest/RESTManager.js @@ -0,0 +1,59 @@ +'use strict'; + +const APIRequest = require('./APIRequest'); +const routeBuilder = require('./APIRouter'); +const RequestHandler = require('./RequestHandler'); +const { Error } = require('../errors'); +const Collection = require('../util/Collection'); +const { Endpoints } = require('../util/Constants'); + +class RESTManager { + constructor(client, tokenPrefix = 'Bot') { + this.client = client; + this.handlers = new Collection(); + this.tokenPrefix = tokenPrefix; + this.versioned = true; + this.globalTimeout = null; + if (client.options.restSweepInterval > 0) { + client.setInterval(() => { + this.handlers.sweep(handler => handler._inactive); + }, client.options.restSweepInterval * 1000); + } + } + + get api() { + return routeBuilder(this); + } + + getAuth() { + const token = this.client.token || this.client.accessToken; + if (token) return `${this.tokenPrefix} ${token}`; + throw new Error('TOKEN_MISSING'); + } + + get cdn() { + return Endpoints.CDN(this.client.options.http.cdn); + } + + request(method, url, options = {}) { + const apiRequest = new APIRequest(this, method, url, options); + let handler = this.handlers.get(apiRequest.route); + + if (!handler) { + handler = new RequestHandler(this); + this.handlers.set(apiRequest.route, handler); + } + + return handler.push(apiRequest); + } + + get endpoint() { + return this.client.options.http.api; + } + + set endpoint(endpoint) { + this.client.options.http.api = endpoint; + } +} + +module.exports = RESTManager; diff --git a/node_modules/discord.js/src/rest/RequestHandler.js b/node_modules/discord.js/src/rest/RequestHandler.js new file mode 100644 index 0000000..b15b2fa --- /dev/null +++ b/node_modules/discord.js/src/rest/RequestHandler.js @@ -0,0 +1,173 @@ +'use strict'; + +const AsyncQueue = require('./AsyncQueue'); +const DiscordAPIError = require('./DiscordAPIError'); +const HTTPError = require('./HTTPError'); +const { + Events: { RATE_LIMIT }, + browser, +} = require('../util/Constants'); +const Util = require('../util/Util'); + +function parseResponse(res) { + if (res.headers.get('content-type').startsWith('application/json')) return res.json(); + if (browser) return res.blob(); + return res.buffer(); +} + +function getAPIOffset(serverDate) { + return new Date(serverDate).getTime() - Date.now(); +} + +function calculateReset(reset, serverDate) { + return new Date(Number(reset) * 1000).getTime() - getAPIOffset(serverDate); +} + +class RequestHandler { + constructor(manager) { + this.manager = manager; + this.queue = new AsyncQueue(); + this.reset = -1; + this.remaining = -1; + this.limit = -1; + this.retryAfter = -1; + } + + async push(request) { + await this.queue.wait(); + try { + return await this.execute(request); + } finally { + this.queue.shift(); + } + } + + get limited() { + return Boolean(this.manager.globalTimeout) || (this.remaining <= 0 && Date.now() < this.reset); + } + + get _inactive() { + return this.queue.remaining === 0 && !this.limited; + } + + async execute(request) { + // After calculations and requests have been done, pre-emptively stop further requests + if (this.limited) { + const timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now(); + + if (this.manager.client.listenerCount(RATE_LIMIT)) { + /** + * Emitted when the client hits a rate limit while making a request + * @event Client#rateLimit + * @param {Object} rateLimitInfo Object containing the rate limit info + * @param {number} rateLimitInfo.timeout Timeout in ms + * @param {number} rateLimitInfo.limit Number of requests that can be made to this endpoint + * @param {string} rateLimitInfo.method HTTP method used for request that triggered this event + * @param {string} rateLimitInfo.path Path used for request that triggered this event + * @param {string} rateLimitInfo.route Route used for request that triggered this event + */ + this.manager.client.emit(RATE_LIMIT, { + timeout, + limit: this.limit, + method: request.method, + path: request.path, + route: request.route, + }); + } + + if (this.manager.globalTimeout) { + await this.manager.globalTimeout; + } else { + // Wait for the timeout to expire in order to avoid an actual 429 + await Util.delayFor(timeout); + } + } + + // Perform the request + let res; + try { + res = await request.make(); + } catch (error) { + // Retry the specified number of times for request abortions + if (request.retries === this.manager.client.options.retryLimit) { + throw new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path); + } + + request.retries++; + return this.execute(request); + } + + if (res && res.headers) { + const serverDate = res.headers.get('date'); + const limit = res.headers.get('x-ratelimit-limit'); + const remaining = res.headers.get('x-ratelimit-remaining'); + const reset = res.headers.get('x-ratelimit-reset'); + const retryAfter = res.headers.get('retry-after'); + + this.limit = limit ? Number(limit) : Infinity; + this.remaining = remaining ? Number(remaining) : 1; + this.reset = reset ? calculateReset(reset, serverDate) : Date.now(); + this.retryAfter = retryAfter ? Number(retryAfter) : -1; + + // https://github.com/discordapp/discord-api-docs/issues/182 + if (request.route.includes('reactions')) { + this.reset = new Date(serverDate).getTime() - getAPIOffset(serverDate) + 250; + } + + // Handle global ratelimit + if (res.headers.get('x-ratelimit-global')) { + // Set the manager's global timeout as the promise for other requests to "wait" + this.manager.globalTimeout = Util.delayFor(this.retryAfter); + + // Wait for the global timeout to resolve before continuing + await this.manager.globalTimeout; + + // Clean up global timeout + this.manager.globalTimeout = null; + } + } + + // Handle 2xx and 3xx responses + if (res.ok) { + // Nothing wrong with the request, proceed with the next one + return parseResponse(res); + } + + // Handle 4xx responses + if (res.status >= 400 && res.status < 500) { + // Handle ratelimited requests + if (res.status === 429) { + // A ratelimit was hit - this should never happen + this.manager.client.emit('debug', `429 hit on route ${request.route}`); + await Util.delayFor(this.retryAfter); + return this.execute(request); + } + + // Handle possible malformed requests + let data; + try { + data = await parseResponse(res); + } catch (err) { + throw new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path); + } + + throw new DiscordAPIError(request.path, data, request.method, res.status); + } + + // Handle 5xx responses + if (res.status >= 500 && res.status < 600) { + // Retry the specified number of times for possible serverside issues + if (request.retries === this.manager.client.options.retryLimit) { + throw new HTTPError(res.statusText, res.constructor.name, res.status, request.method, request.path); + } + + request.retries++; + return this.execute(request); + } + + // Fallback in the rare case a status code outside the range 200..=599 is returned + return null; + } +} + +module.exports = RequestHandler; diff --git a/node_modules/discord.js/src/sharding/Shard.js b/node_modules/discord.js/src/sharding/Shard.js new file mode 100644 index 0000000..ecd535f --- /dev/null +++ b/node_modules/discord.js/src/sharding/Shard.js @@ -0,0 +1,396 @@ +'use strict'; + +const EventEmitter = require('events'); +const path = require('path'); +const { Error } = require('../errors'); +const Util = require('../util/Util'); +let childProcess = null; +let Worker = null; + +/** + * A self-contained shard created by the {@link ShardingManager}. Each one has a {@link ChildProcess} that contains + * an instance of the bot and its {@link Client}. When its child process/worker exits for any reason, the shard will + * spawn a new one to replace it as necessary. + * @extends EventEmitter + */ +class Shard extends EventEmitter { + /** + * @param {ShardingManager} manager Manager that is creating this shard + * @param {number} id ID of this shard + */ + constructor(manager, id) { + super(); + + if (manager.mode === 'process') childProcess = require('child_process'); + else if (manager.mode === 'worker') Worker = require('worker_threads').Worker; + + /** + * Manager that created the shard + * @type {ShardingManager} + */ + this.manager = manager; + + /** + * ID of the shard in the manager + * @type {number} + */ + this.id = id; + + /** + * Arguments for the shard's process (only when {@link ShardingManager#mode} is `process`) + * @type {string[]} + */ + this.args = manager.shardArgs || []; + + /** + * Arguments for the shard's process executable (only when {@link ShardingManager#mode} is `process`) + * @type {string[]} + */ + this.execArgv = manager.execArgv; + + /** + * Environment variables for the shard's process, or workerData for the shard's worker + * @type {Object} + */ + this.env = Object.assign({}, process.env, { + SHARDING_MANAGER: true, + SHARDS: this.id, + SHARD_COUNT: this.manager.totalShards, + DISCORD_TOKEN: this.manager.token, + }); + + /** + * Whether the shard's {@link Client} is ready + * @type {boolean} + */ + this.ready = false; + + /** + * Process of the shard (if {@link ShardingManager#mode} is `process`) + * @type {?ChildProcess} + */ + this.process = null; + + /** + * Worker of the shard (if {@link ShardingManager#mode} is `worker`) + * @type {?Worker} + */ + this.worker = null; + + /** + * Ongoing promises for calls to {@link Shard#eval}, mapped by the `script` they were called with + * @type {Map} + * @private + */ + this._evals = new Map(); + + /** + * Ongoing promises for calls to {@link Shard#fetchClientValue}, mapped by the `prop` they were called with + * @type {Map} + * @private + */ + this._fetches = new Map(); + + /** + * Listener function for the {@link ChildProcess}' `exit` event + * @type {Function} + * @private + */ + this._exitListener = this._handleExit.bind(this, undefined); + } + + /** + * Forks a child process or creates a worker thread for the shard. + * You should not need to call this manually. + * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready + * before resolving. (-1 or Infinity for no wait) + * @returns {Promise} + */ + async spawn(spawnTimeout = 30000) { + if (this.process) throw new Error('SHARDING_PROCESS_EXISTS', this.id); + if (this.worker) throw new Error('SHARDING_WORKER_EXISTS', this.id); + + if (this.manager.mode === 'process') { + this.process = childProcess + .fork(path.resolve(this.manager.file), this.args, { + env: this.env, + execArgv: this.execArgv, + }) + .on('message', this._handleMessage.bind(this)) + .on('exit', this._exitListener); + } else if (this.manager.mode === 'worker') { + this.worker = new Worker(path.resolve(this.manager.file), { workerData: this.env }) + .on('message', this._handleMessage.bind(this)) + .on('exit', this._exitListener); + } + + this._evals.clear(); + this._fetches.clear(); + + /** + * Emitted upon the creation of the shard's child process/worker. + * @event Shard#spawn + * @param {ChildProcess|Worker} process Child process/worker that was created + */ + this.emit('spawn', this.process || this.worker); + + if (spawnTimeout === -1 || spawnTimeout === Infinity) return this.process || this.worker; + await new Promise((resolve, reject) => { + const cleanup = () => { + clearTimeout(spawnTimeoutTimer); + this.off('ready', onReady); + this.off('disconnect', onDisconnect); + this.off('death', onDeath); + }; + + const onReady = () => { + cleanup(); + resolve(); + }; + + const onDisconnect = () => { + cleanup(); + reject(new Error('SHARDING_READY_DISCONNECTED', this.id)); + }; + + const onDeath = () => { + cleanup(); + reject(new Error('SHARDING_READY_DIED', this.id)); + }; + + const onTimeout = () => { + cleanup(); + reject(new Error('SHARDING_READY_TIMEOUT', this.id)); + }; + + const spawnTimeoutTimer = setTimeout(onTimeout, spawnTimeout); + this.once('ready', onReady); + this.once('disconnect', onDisconnect); + this.once('death', onDeath); + }); + return this.process || this.worker; + } + + /** + * Immediately kills the shard's process/worker and does not restart it. + */ + kill() { + if (this.process) { + this.process.removeListener('exit', this._exitListener); + this.process.kill(); + } else { + this.worker.removeListener('exit', this._exitListener); + this.worker.terminate(); + } + + this._handleExit(false); + } + + /** + * Kills and restarts the shard's process/worker. + * @param {number} [delay=500] How long to wait between killing the process/worker and restarting it (in milliseconds) + * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready + * before resolving. (-1 or Infinity for no wait) + * @returns {Promise} + */ + async respawn(delay = 500, spawnTimeout) { + this.kill(); + if (delay > 0) await Util.delayFor(delay); + return this.spawn(spawnTimeout); + } + + /** + * Sends a message to the shard's process/worker. + * @param {*} message Message to send to the shard + * @returns {Promise} + */ + send(message) { + return new Promise((resolve, reject) => { + if (this.process) { + this.process.send(message, err => { + if (err) reject(err); + else resolve(this); + }); + } else { + this.worker.postMessage(message); + resolve(this); + } + }); + } + + /** + * Fetches a client property value of the shard. + * @param {string} prop Name of the client property to get, using periods for nesting + * @returns {Promise<*>} + * @example + * shard.fetchClientValue('guilds.cache.size') + * .then(count => console.log(`${count} guilds in shard ${shard.id}`)) + * .catch(console.error); + */ + fetchClientValue(prop) { + // Shard is dead (maybe respawning), don't cache anything and error immediately + if (!this.process && !this.worker) return Promise.reject(new Error('SHARDING_NO_CHILD_EXISTS', this.id)); + + // Cached promise from previous call + if (this._fetches.has(prop)) return this._fetches.get(prop); + + const promise = new Promise((resolve, reject) => { + const child = this.process || this.worker; + + const listener = message => { + if (!message || message._fetchProp !== prop) return; + child.removeListener('message', listener); + this._fetches.delete(prop); + resolve(message._result); + }; + child.on('message', listener); + + this.send({ _fetchProp: prop }).catch(err => { + child.removeListener('message', listener); + this._fetches.delete(prop); + reject(err); + }); + }); + + this._fetches.set(prop, promise); + return promise; + } + + /** + * Evaluates a script or function on the shard, in the context of the {@link Client}. + * @param {string|Function} script JavaScript to run on the shard + * @returns {Promise<*>} Result of the script execution + */ + eval(script) { + // Shard is dead (maybe respawning), don't cache anything and error immediately + if (!this.process && !this.worker) return Promise.reject(new Error('SHARDING_NO_CHILD_EXISTS', this.id)); + + // Cached promise from previous call + if (this._evals.has(script)) return this._evals.get(script); + + const promise = new Promise((resolve, reject) => { + const child = this.process || this.worker; + + const listener = message => { + if (!message || message._eval !== script) return; + child.removeListener('message', listener); + this._evals.delete(script); + if (!message._error) resolve(message._result); + else reject(Util.makeError(message._error)); + }; + child.on('message', listener); + + const _eval = typeof script === 'function' ? `(${script})(this)` : script; + this.send({ _eval }).catch(err => { + child.removeListener('message', listener); + this._evals.delete(script); + reject(err); + }); + }); + + this._evals.set(script, promise); + return promise; + } + + /** + * Handles a message received from the child process/worker. + * @param {*} message Message received + * @private + */ + _handleMessage(message) { + if (message) { + // Shard is ready + if (message._ready) { + this.ready = true; + /** + * Emitted upon the shard's {@link Client#ready} event. + * @event Shard#ready + */ + this.emit('ready'); + return; + } + + // Shard has disconnected + if (message._disconnect) { + this.ready = false; + /** + * Emitted upon the shard's {@link Client#disconnect} event. + * @event Shard#disconnect + */ + this.emit('disconnect'); + return; + } + + // Shard is attempting to reconnect + if (message._reconnecting) { + this.ready = false; + /** + * Emitted upon the shard's {@link Client#reconnecting} event. + * @event Shard#reconnecting + */ + this.emit('reconnecting'); + return; + } + + // Shard is requesting a property fetch + if (message._sFetchProp) { + const resp = { _sFetchProp: message._sFetchProp, _sFetchPropShard: message._sFetchPropShard }; + this.manager.fetchClientValues(message._sFetchProp, message._sFetchPropShard).then( + results => this.send({ ...resp, _result: results }), + err => this.send({ ...resp, _error: Util.makePlainError(err) }), + ); + return; + } + + // Shard is requesting an eval broadcast + if (message._sEval) { + const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; + this.manager.broadcastEval(message._sEval, message._sEvalShard).then( + results => this.send({ ...resp, _result: results }), + err => this.send({ ...resp, _error: Util.makePlainError(err) }), + ); + return; + } + + // Shard is requesting a respawn of all shards + if (message._sRespawnAll) { + const { shardDelay, respawnDelay, spawnTimeout } = message._sRespawnAll; + this.manager.respawnAll(shardDelay, respawnDelay, spawnTimeout).catch(() => { + // Do nothing + }); + return; + } + } + + /** + * Emitted upon receiving a message from the child process/worker. + * @event Shard#message + * @param {*} message Message that was received + */ + this.emit('message', message); + } + + /** + * Handles the shard's process/worker exiting. + * @param {boolean} [respawn=this.manager.respawn] Whether to spawn the shard again + * @private + */ + _handleExit(respawn = this.manager.respawn) { + /** + * Emitted upon the shard's child process/worker exiting. + * @event Shard#death + * @param {ChildProcess|Worker} process Child process/worker that exited + */ + this.emit('death', this.process || this.worker); + + this.ready = false; + this.process = null; + this.worker = null; + this._evals.clear(); + this._fetches.clear(); + + if (respawn) this.spawn().catch(err => this.emit('error', err)); + } +} + +module.exports = Shard; diff --git a/node_modules/discord.js/src/sharding/ShardClientUtil.js b/node_modules/discord.js/src/sharding/ShardClientUtil.js new file mode 100644 index 0000000..e623042 --- /dev/null +++ b/node_modules/discord.js/src/sharding/ShardClientUtil.js @@ -0,0 +1,243 @@ +'use strict'; + +const { Events } = require('../util/Constants'); +const Util = require('../util/Util'); + +/** + * Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}. + * Utilises IPC to send and receive data to/from the master process and other shards. + */ +class ShardClientUtil { + /** + * @param {Client} client Client of the current shard + * @param {ShardingManagerMode} mode Mode the shard was spawned with + */ + constructor(client, mode) { + /** + * Client for the shard + * @type {Client} + */ + this.client = client; + + /** + * Mode the shard was spawned with + * @type {ShardingManagerMode} + */ + this.mode = mode; + + /** + * Message port for the master process (only when {@link ShardClientUtil#mode} is `worker`) + * @type {?MessagePort} + */ + this.parentPort = null; + + if (mode === 'process') { + process.on('message', this._handleMessage.bind(this)); + client.on('ready', () => { + process.send({ _ready: true }); + }); + client.on('disconnect', () => { + process.send({ _disconnect: true }); + }); + client.on('reconnecting', () => { + process.send({ _reconnecting: true }); + }); + } else if (mode === 'worker') { + this.parentPort = require('worker_threads').parentPort; + this.parentPort.on('message', this._handleMessage.bind(this)); + client.on('ready', () => { + this.parentPort.postMessage({ _ready: true }); + }); + client.on('disconnect', () => { + this.parentPort.postMessage({ _disconnect: true }); + }); + client.on('reconnecting', () => { + this.parentPort.postMessage({ _reconnecting: true }); + }); + } + } + + /** + * Array of shard IDs of this client + * @type {number[]} + * @readonly + */ + get ids() { + return this.client.options.shards; + } + + /** + * Total number of shards + * @type {number} + * @readonly + */ + get count() { + return this.client.options.shardCount; + } + + /** + * Sends a message to the master process. + * @param {*} message Message to send + * @returns {Promise} + * @emits Shard#message + */ + send(message) { + return new Promise((resolve, reject) => { + if (this.mode === 'process') { + process.send(message, err => { + if (err) reject(err); + else resolve(); + }); + } else if (this.mode === 'worker') { + this.parentPort.postMessage(message); + resolve(); + } + }); + } + + /** + * Fetches a client property value of each shard, or a given shard. + * @param {string} prop Name of the client property to get, using periods for nesting + * @param {number} [shard] Shard to fetch property from, all if undefined + * @returns {Promise<*>|Promise>} + * @example + * client.shard.fetchClientValues('guilds.cache.size') + * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)) + * .catch(console.error); + * @see {@link ShardingManager#fetchClientValues} + */ + fetchClientValues(prop, shard) { + return new Promise((resolve, reject) => { + const parent = this.parentPort || process; + + const listener = message => { + if (!message || message._sFetchProp !== prop || message._sFetchPropShard !== shard) return; + parent.removeListener('message', listener); + if (!message._error) resolve(message._result); + else reject(Util.makeError(message._error)); + }; + parent.on('message', listener); + + this.send({ _sFetchProp: prop, _sFetchPropShard: shard }).catch(err => { + parent.removeListener('message', listener); + reject(err); + }); + }); + } + + /** + * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s. + * @param {string|Function} script JavaScript to run on each shard + * @param {number} [shard] Shard to run script on, all if undefined + * @returns {Promise<*>|Promise>} Results of the script execution + * @example + * client.shard.broadcastEval('this.guilds.cache.size') + * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)) + * .catch(console.error); + * @see {@link ShardingManager#broadcastEval} + */ + broadcastEval(script, shard) { + return new Promise((resolve, reject) => { + const parent = this.parentPort || process; + script = typeof script === 'function' ? `(${script})(this)` : script; + + const listener = message => { + if (!message || message._sEval !== script || message._sEvalShard !== shard) return; + parent.removeListener('message', listener); + if (!message._error) resolve(message._result); + else reject(Util.makeError(message._error)); + }; + parent.on('message', listener); + + this.send({ _sEval: script, _sEvalShard: shard }).catch(err => { + parent.removeListener('message', listener); + reject(err); + }); + }); + } + + /** + * Requests a respawn of all shards. + * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds) + * @param {number} [respawnDelay=500] How long to wait between killing a shard's process/worker and restarting it + * (in milliseconds) + * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before + * continuing to another. (-1 or Infinity for no wait) + * @returns {Promise} Resolves upon the message being sent + * @see {@link ShardingManager#respawnAll} + */ + respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout = 30000) { + return this.send({ _sRespawnAll: { shardDelay, respawnDelay, spawnTimeout } }); + } + + /** + * Handles an IPC message. + * @param {*} message Message received + * @private + */ + async _handleMessage(message) { + if (!message) return; + if (message._fetchProp) { + const props = message._fetchProp.split('.'); + let value = this.client; + for (const prop of props) value = value[prop]; + this._respond('fetchProp', { _fetchProp: message._fetchProp, _result: value }); + } else if (message._eval) { + try { + this._respond('eval', { _eval: message._eval, _result: await this.client._eval(message._eval) }); + } catch (err) { + this._respond('eval', { _eval: message._eval, _error: Util.makePlainError(err) }); + } + } + } + + /** + * Sends a message to the master process, emitting an error from the client upon failure. + * @param {string} type Type of response to send + * @param {*} message Message to send + * @private + */ + _respond(type, message) { + this.send(message).catch(err => { + err.message = `Error when sending ${type} response to master process: ${err.message}`; + /** + * Emitted when the client encounters an error. + * @event Client#error + * @param {Error} error The error encountered + */ + this.client.emit(Events.ERROR, err); + }); + } + + /** + * Creates/gets the singleton of this class. + * @param {Client} client The client to use + * @param {ShardingManagerMode} mode Mode the shard was spawned with + * @returns {ShardClientUtil} + */ + static singleton(client, mode) { + if (!this._singleton) { + this._singleton = new this(client, mode); + } else { + client.emit( + Events.WARN, + 'Multiple clients created in child process/worker; only the first will handle sharding helpers.', + ); + } + return this._singleton; + } + + /** + * Get the shard ID for a given guild ID. + * @param {Snowflake} guildID Snowflake guild ID to get shard ID for + * @param {number} shardCount Number of shards + * @returns {number} + */ + static shardIDForGuildID(guildID, shardCount) { + const shard = Number(BigInt(guildID) >> 22n) % shardCount; + if (shard < 0) throw new Error('SHARDING_SHARD_MISCALCULATION', shard, guildID, shardCount); + return shard; + } +} + +module.exports = ShardClientUtil; diff --git a/node_modules/discord.js/src/sharding/ShardingManager.js b/node_modules/discord.js/src/sharding/ShardingManager.js new file mode 100644 index 0000000..9007c59 --- /dev/null +++ b/node_modules/discord.js/src/sharding/ShardingManager.js @@ -0,0 +1,290 @@ +'use strict'; + +const EventEmitter = require('events'); +const fs = require('fs'); +const path = require('path'); +const Shard = require('./Shard'); +const { Error, TypeError, RangeError } = require('../errors'); +const Collection = require('../util/Collection'); +const Util = require('../util/Util'); + +/** + * This is a utility class that makes multi-process sharding of a bot an easy and painless experience. + * It works by spawning a self-contained {@link ChildProcess} or {@link Worker} for each individual shard, each + * containing its own instance of your bot's {@link Client}. They all have a line of communication with the master + * process, and there are several useful methods that utilise it in order to simplify tasks that are normally difficult + * with sharding. It can spawn a specific number of shards or the amount that Discord suggests for the bot, and takes a + * path to your main bot script to launch for each one. + * @extends {EventEmitter} + */ +class ShardingManager extends EventEmitter { + /** + * The mode to spawn shards with for a {@link ShardingManager}: either "process" to use child processes, or + * "worker" to use [Worker threads](https://nodejs.org/api/worker_threads.html). + * @typedef {Object} ShardingManagerMode + */ + + /** + * @param {string} file Path to your shard script file + * @param {Object} [options] Options for the sharding manager + * @param {string|number} [options.totalShards='auto'] Number of total shards of all shard managers or "auto" + * @param {string|number[]} [options.shardList='auto'] List of shards to spawn or "auto" + * @param {ShardingManagerMode} [options.mode='process'] Which mode to use for shards + * @param {boolean} [options.respawn=true] Whether shards should automatically respawn upon exiting + * @param {string[]} [options.shardArgs=[]] Arguments to pass to the shard script when spawning + * (only available when using the `process` mode) + * @param {string[]} [options.execArgv=[]] Arguments to pass to the shard script executable when spawning + * (only available when using the `process` mode) + * @param {string} [options.token] Token to use for automatic shard count and passing to shards + */ + constructor(file, options = {}) { + super(); + options = Util.mergeDefault( + { + totalShards: 'auto', + mode: 'process', + respawn: true, + shardArgs: [], + execArgv: [], + token: process.env.DISCORD_TOKEN, + }, + options, + ); + + /** + * Path to the shard script file + * @type {string} + */ + this.file = file; + if (!file) throw new Error('CLIENT_INVALID_OPTION', 'File', 'specified.'); + if (!path.isAbsolute(file)) this.file = path.resolve(process.cwd(), file); + const stats = fs.statSync(this.file); + if (!stats.isFile()) throw new Error('CLIENT_INVALID_OPTION', 'File', 'a file'); + + /** + * List of shards this sharding manager spawns + * @type {string|number[]} + */ + this.shardList = options.shardList || 'auto'; + if (this.shardList !== 'auto') { + if (!Array.isArray(this.shardList)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.'); + } + this.shardList = [...new Set(this.shardList)]; + if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 ID.'); + if ( + this.shardList.some( + shardID => typeof shardID !== 'number' || isNaN(shardID) || !Number.isInteger(shardID) || shardID < 0, + ) + ) { + throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of positive integers.'); + } + } + + /** + * Amount of shards that all sharding managers spawn in total + * @type {number} + */ + this.totalShards = options.totalShards || 'auto'; + if (this.totalShards !== 'auto') { + if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.'); + } + if (this.totalShards < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.'); + if (!Number.isInteger(this.totalShards)) { + throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.'); + } + } + + /** + * Mode for shards to spawn with + * @type {ShardingManagerMode} + */ + this.mode = options.mode; + if (this.mode !== 'process' && this.mode !== 'worker') { + throw new RangeError('CLIENT_INVALID_OPTION', 'Sharding mode', '"process" or "worker"'); + } + + /** + * Whether shards should automatically respawn upon exiting + * @type {boolean} + */ + this.respawn = options.respawn; + + /** + * An array of arguments to pass to shards (only when {@link ShardingManager#mode} is `process`) + * @type {string[]} + */ + this.shardArgs = options.shardArgs; + + /** + * An array of arguments to pass to the executable (only when {@link ShardingManager#mode} is `process`) + * @type {string[]} + */ + this.execArgv = options.execArgv; + + /** + * Token to use for obtaining the automatic shard count, and passing to shards + * @type {?string} + */ + this.token = options.token ? options.token.replace(/^Bot\s*/i, '') : null; + + /** + * A collection of shards that this manager has spawned + * @type {Collection} + */ + this.shards = new Collection(); + + process.env.SHARDING_MANAGER = true; + process.env.SHARDING_MANAGER_MODE = this.mode; + process.env.DISCORD_TOKEN = this.token; + } + + /** + * Creates a single shard. + * Using this method is usually not necessary if you use the spawn method. + * @param {number} [id=this.shards.size] ID of the shard to create + * This is usually not necessary to manually specify. + * @returns {Shard} Note that the created shard needs to be explicitly spawned using its spawn method. + */ + createShard(id = this.shards.size) { + const shard = new Shard(this, id); + this.shards.set(id, shard); + /** + * Emitted upon creating a shard. + * @event ShardingManager#shardCreate + * @param {Shard} shard Shard that was created + */ + this.emit('shardCreate', shard); + return shard; + } + + /** + * Spawns multiple shards. + * @param {number|string} [amount=this.totalShards] Number of shards to spawn + * @param {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds) + * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready + * before resolving. (-1 or Infinity for no wait) + * @returns {Promise>} + */ + async spawn(amount = this.totalShards, delay = 5500, spawnTimeout) { + // Obtain/verify the number of shards to spawn + if (amount === 'auto') { + amount = await Util.fetchRecommendedShards(this.token); + } else { + if (typeof amount !== 'number' || isNaN(amount)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.'); + } + if (amount < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.'); + if (!Number.isInteger(amount)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.'); + } + } + + // Make sure this many shards haven't already been spawned + if (this.shards.size >= amount) throw new Error('SHARDING_ALREADY_SPAWNED', this.shards.size); + if (this.shardList === 'auto' || this.totalShards === 'auto' || this.totalShards !== amount) { + this.shardList = [...Array(amount).keys()]; + } + if (this.totalShards === 'auto' || this.totalShards !== amount) { + this.totalShards = amount; + } + + if (this.shardList.some(shardID => shardID >= amount)) { + throw new RangeError( + 'CLIENT_INVALID_OPTION', + 'Amount of shards', + 'bigger than the highest shardID in the shardList option.', + ); + } + + // Spawn the shards + for (const shardID of this.shardList) { + const promises = []; + const shard = this.createShard(shardID); + promises.push(shard.spawn(spawnTimeout)); + if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(Util.delayFor(delay)); + await Promise.all(promises); // eslint-disable-line no-await-in-loop + } + + return this.shards; + } + + /** + * Sends a message to all shards. + * @param {*} message Message to be sent to the shards + * @returns {Promise} + */ + broadcast(message) { + const promises = []; + for (const shard of this.shards.values()) promises.push(shard.send(message)); + return Promise.all(promises); + } + + /** + * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s. + * @param {string} script JavaScript to run on each shard + * @param {number} [shard] Shard to run on, all if undefined + * @returns {Promise<*>|Promise>} Results of the script execution + */ + broadcastEval(script, shard) { + return this._performOnShards('eval', [script], shard); + } + + /** + * Fetches a client property value of each shard, or a given shard. + * @param {string} prop Name of the client property to get, using periods for nesting + * @param {number} [shard] Shard to fetch property from, all if undefined + * @returns {Promise<*>|Promise>} + * @example + * manager.fetchClientValues('guilds.cache.size') + * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)) + * .catch(console.error); + */ + fetchClientValues(prop, shard) { + return this._performOnShards('fetchClientValue', [prop], shard); + } + + /** + * Runs a method with given arguments on all shards, or a given shard. + * @param {string} method Method name to run on each shard + * @param {Array<*>} args Arguments to pass through to the method call + * @param {number} [shard] Shard to run on, all if undefined + * @returns {Promise<*>|Promise>} Results of the method execution + * @private + */ + _performOnShards(method, args, shard) { + if (this.shards.size === 0) return Promise.reject(new Error('SHARDING_NO_SHARDS')); + if (this.shards.size !== this.shardList.length) return Promise.reject(new Error('SHARDING_IN_PROCESS')); + + if (typeof shard === 'number') { + if (this.shards.has(shard)) return this.shards.get(shard)[method](...args); + return Promise.reject(new Error('SHARDING_SHARD_NOT_FOUND', shard)); + } + + const promises = []; + for (const sh of this.shards.values()) promises.push(sh[method](...args)); + return Promise.all(promises); + } + + /** + * Kills all running shards and respawns them. + * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds) + * @param {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it + * (in milliseconds) + * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before + * continuing to another. (-1 or Infinity for no wait) + * @returns {Promise>} + */ + async respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout) { + let s = 0; + for (const shard of this.shards.values()) { + const promises = [shard.respawn(respawnDelay, spawnTimeout)]; + if (++s < this.shards.size && shardDelay > 0) promises.push(Util.delayFor(shardDelay)); + await Promise.all(promises); // eslint-disable-line no-await-in-loop + } + return this.shards; + } +} + +module.exports = ShardingManager; diff --git a/node_modules/discord.js/src/structures/APIMessage.js b/node_modules/discord.js/src/structures/APIMessage.js new file mode 100644 index 0000000..3451bdb --- /dev/null +++ b/node_modules/discord.js/src/structures/APIMessage.js @@ -0,0 +1,396 @@ +'use strict'; + +const MessageAttachment = require('./MessageAttachment'); +const MessageEmbed = require('./MessageEmbed'); +const { RangeError } = require('../errors'); +const { browser } = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); +const MessageFlags = require('../util/MessageFlags'); +const Util = require('../util/Util'); + +/** + * Represents a message to be sent to the API. + */ +class APIMessage { + /** + * @param {MessageTarget} target - The target for this message to be sent to + * @param {MessageOptions|WebhookMessageOptions} options - Options passed in from send + */ + constructor(target, options) { + /** + * The target for this message to be sent to + * @type {MessageTarget} + */ + this.target = target; + + /** + * Options passed in from send + * @type {MessageOptions|WebhookMessageOptions} + */ + this.options = options; + + /** + * Data sendable to the API + * @type {?Object} + */ + this.data = null; + + /** + * Files sendable to the API + * @type {?Object[]} + */ + this.files = null; + } + + /** + * Whether or not the target is a webhook + * @type {boolean} + * @readonly + */ + get isWebhook() { + const Webhook = require('./Webhook'); + const WebhookClient = require('../client/WebhookClient'); + return this.target instanceof Webhook || this.target instanceof WebhookClient; + } + + /** + * Whether or not the target is a user + * @type {boolean} + * @readonly + */ + get isUser() { + const User = require('./User'); + const GuildMember = require('./GuildMember'); + return this.target instanceof User || this.target instanceof GuildMember; + } + + /** + * Whether or not the target is a message + * @type {boolean} + * @readonly + */ + get isMessage() { + const Message = require('./Message'); + return this.target instanceof Message; + } + + /** + * Makes the content of this message. + * @returns {?(string|string[])} + */ + makeContent() { + const GuildMember = require('./GuildMember'); + + let content; + if (this.options.content === null) { + content = ''; + } else if (typeof this.options.content !== 'undefined') { + content = Util.resolveString(this.options.content); + } + + if (typeof content !== 'string') return content; + + const disableMentions = + typeof this.options.disableMentions === 'undefined' + ? this.target.client.options.disableMentions + : this.options.disableMentions; + if (disableMentions === 'all') { + content = Util.removeMentions(content); + } else if (disableMentions === 'everyone') { + content = content.replace(/@([^<>@ ]*)/gmsu, (match, target) => { + if (target.match(/^[&!]?\d+$/)) { + return `@${target}`; + } else { + return `@\u200b${target}`; + } + }); + } + + const isSplit = typeof this.options.split !== 'undefined' && this.options.split !== false; + const isCode = typeof this.options.code !== 'undefined' && this.options.code !== false; + const splitOptions = isSplit ? { ...this.options.split } : undefined; + + let mentionPart = ''; + if (this.options.reply && !this.isUser && this.target.type !== 'dm') { + const id = this.target.client.users.resolveID(this.options.reply); + mentionPart = `<@${this.options.reply instanceof GuildMember && this.options.reply.nickname ? '!' : ''}${id}>, `; + if (isSplit) { + splitOptions.prepend = `${mentionPart}${splitOptions.prepend || ''}`; + } + } + + if (content || mentionPart) { + if (isCode) { + const codeName = typeof this.options.code === 'string' ? this.options.code : ''; + content = `${mentionPart}\`\`\`${codeName}\n${Util.cleanCodeBlockContent(content)}\n\`\`\``; + if (isSplit) { + splitOptions.prepend = `${splitOptions.prepend || ''}\`\`\`${codeName}\n`; + splitOptions.append = `\n\`\`\`${splitOptions.append || ''}`; + } + } else if (mentionPart) { + content = `${mentionPart}${content}`; + } + + if (isSplit) { + content = Util.splitMessage(content, splitOptions); + } + } + + return content; + } + + /** + * Resolves data. + * @returns {APIMessage} + */ + resolveData() { + if (this.data) return this; + + const content = this.makeContent(); + const tts = Boolean(this.options.tts); + + let nonce; + if (typeof this.options.nonce !== 'undefined') { + nonce = parseInt(this.options.nonce); + if (isNaN(nonce) || nonce < 0) throw new RangeError('MESSAGE_NONCE_TYPE'); + } + + const embedLikes = []; + if (this.isWebhook) { + if (this.options.embeds) { + embedLikes.push(...this.options.embeds); + } + } else if (this.options.embed) { + embedLikes.push(this.options.embed); + } + const embeds = embedLikes.map(e => new MessageEmbed(e).toJSON()); + + let username; + let avatarURL; + if (this.isWebhook) { + username = this.options.username || this.target.name; + if (this.options.avatarURL) avatarURL = this.options.avatarURL; + } + + let flags; + if (this.isMessage) { + // eslint-disable-next-line eqeqeq + flags = this.options.flags != null ? new MessageFlags(this.options.flags).bitfield : this.target.flags.bitfield; + } + + let allowedMentions = + typeof this.options.allowedMentions === 'undefined' + ? this.target.client.options.allowedMentions + : this.options.allowedMentions; + if (this.options.reply) { + const id = this.target.client.users.resolveID(this.options.reply); + if (allowedMentions) { + // Clone the object as not to alter the ClientOptions object + allowedMentions = Util.cloneObject(allowedMentions); + const parsed = allowedMentions.parse && allowedMentions.parse.includes('users'); + // Check if the mention won't be parsed, and isn't supplied in `users` + if (!parsed && !(allowedMentions.users && allowedMentions.users.includes(id))) { + if (!allowedMentions.users) allowedMentions.users = []; + allowedMentions.users.push(id); + } + } else { + allowedMentions = { users: [id] }; + } + } + + this.data = { + content, + tts, + nonce, + embed: this.options.embed === null ? null : embeds[0], + embeds, + username, + avatar_url: avatarURL, + allowed_mentions: typeof content === 'undefined' ? undefined : allowedMentions, + flags, + }; + return this; + } + + /** + * Resolves files. + * @returns {Promise} + */ + async resolveFiles() { + if (this.files) return this; + + const embedLikes = []; + if (this.isWebhook) { + if (this.options.embeds) { + embedLikes.push(...this.options.embeds); + } + } else if (this.options.embed) { + embedLikes.push(this.options.embed); + } + + const fileLikes = []; + if (this.options.files) { + fileLikes.push(...this.options.files); + } + for (const embed of embedLikes) { + if (embed.files) { + fileLikes.push(...embed.files); + } + } + + this.files = await Promise.all(fileLikes.map(f => this.constructor.resolveFile(f))); + return this; + } + + /** + * Converts this APIMessage into an array of APIMessages for each split content + * @returns {APIMessage[]} + */ + split() { + if (!this.data) this.resolveData(); + + if (!Array.isArray(this.data.content)) return [this]; + + const apiMessages = []; + + for (let i = 0; i < this.data.content.length; i++) { + let data; + let opt; + + if (i === this.data.content.length - 1) { + data = { ...this.data, content: this.data.content[i] }; + opt = { ...this.options, content: this.data.content[i] }; + } else { + data = { content: this.data.content[i], tts: this.data.tts, allowed_mentions: this.options.allowedMentions }; + opt = { content: this.data.content[i], tts: this.data.tts, allowedMentions: this.options.allowedMentions }; + } + + const apiMessage = new APIMessage(this.target, opt); + apiMessage.data = data; + apiMessages.push(apiMessage); + } + + return apiMessages; + } + + /** + * Resolves a single file into an object sendable to the API. + * @param {BufferResolvable|Stream|FileOptions|MessageAttachment} fileLike Something that could be resolved to a file + * @returns {Object} + */ + static async resolveFile(fileLike) { + let attachment; + let name; + + const findName = thing => { + if (typeof thing === 'string') { + return Util.basename(thing); + } + + if (thing.path) { + return Util.basename(thing.path); + } + + return 'file.jpg'; + }; + + const ownAttachment = + typeof fileLike === 'string' || + fileLike instanceof (browser ? ArrayBuffer : Buffer) || + typeof fileLike.pipe === 'function'; + if (ownAttachment) { + attachment = fileLike; + name = findName(attachment); + } else { + attachment = fileLike.attachment; + name = fileLike.name || findName(attachment); + } + + const resource = await DataResolver.resolveFile(attachment); + return { attachment, name, file: resource }; + } + + /** + * Partitions embeds and attachments. + * @param {Array} items Items to partition + * @returns {Array} + */ + static partitionMessageAdditions(items) { + const embeds = []; + const files = []; + for (const item of items) { + if (item instanceof MessageEmbed) { + embeds.push(item); + } else if (item instanceof MessageAttachment) { + files.push(item); + } + } + + return [embeds, files]; + } + + /** + * Transforms the user-level arguments into a final options object. Passing a transformed options object alone into + * this method will keep it the same, allowing for the reuse of the final options object. + * @param {StringResolvable} [content] Content to send + * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use + * @param {MessageOptions|WebhookMessageOptions} [extra={}] Extra options to add onto transformed options + * @param {boolean} [isWebhook=false] Whether or not to use WebhookMessageOptions as the result + * @returns {MessageOptions|WebhookMessageOptions} + */ + static transformOptions(content, options, extra = {}, isWebhook = false) { + if (!options && typeof content === 'object' && !Array.isArray(content)) { + options = content; + content = undefined; + } + + if (!options) { + options = {}; + } else if (options instanceof MessageEmbed) { + return isWebhook ? { content, embeds: [options], ...extra } : { content, embed: options, ...extra }; + } else if (options instanceof MessageAttachment) { + return { content, files: [options], ...extra }; + } + + if (Array.isArray(options)) { + const [embeds, files] = this.partitionMessageAdditions(options); + return isWebhook ? { content, embeds, files, ...extra } : { content, embed: embeds[0], files, ...extra }; + } else if (Array.isArray(content)) { + const [embeds, files] = this.partitionMessageAdditions(content); + if (embeds.length || files.length) { + return isWebhook ? { embeds, files, ...extra } : { embed: embeds[0], files, ...extra }; + } + } + + return { content, ...options, ...extra }; + } + + /** + * Creates an `APIMessage` from user-level arguments. + * @param {MessageTarget} target Target to send to + * @param {StringResolvable} [content] Content to send + * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use + * @param {MessageOptions|WebhookMessageOptions} [extra={}] - Extra options to add onto transformed options + * @returns {MessageOptions|WebhookMessageOptions} + */ + static create(target, content, options, extra = {}) { + const Webhook = require('./Webhook'); + const WebhookClient = require('../client/WebhookClient'); + + const isWebhook = target instanceof Webhook || target instanceof WebhookClient; + const transformed = this.transformOptions(content, options, extra, isWebhook); + return new this(target, transformed); + } +} + +module.exports = APIMessage; + +/** + * A target for a message. + * @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient} MessageTarget + */ + +/** + * Additional items that can be sent with a message. + * @typedef {MessageEmbed|MessageAttachment|Array} MessageAdditions + */ diff --git a/node_modules/discord.js/src/structures/Base.js b/node_modules/discord.js/src/structures/Base.js new file mode 100644 index 0000000..cd43bf7 --- /dev/null +++ b/node_modules/discord.js/src/structures/Base.js @@ -0,0 +1,43 @@ +'use strict'; + +const Util = require('../util/Util'); + +/** + * Represents a data model that is identifiable by a Snowflake (i.e. Discord API data models). + * @abstract + */ +class Base { + constructor(client) { + /** + * The client that instantiated this + * @name Base#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + } + + _clone() { + return Object.assign(Object.create(this), this); + } + + _patch(data) { + return data; + } + + _update(data) { + const clone = this._clone(); + this._patch(data); + return clone; + } + + toJSON(...props) { + return Util.flatten(this, ...props); + } + + valueOf() { + return this.id; + } +} + +module.exports = Base; diff --git a/node_modules/discord.js/src/structures/BaseGuildEmoji.js b/node_modules/discord.js/src/structures/BaseGuildEmoji.js new file mode 100644 index 0000000..a2007c6 --- /dev/null +++ b/node_modules/discord.js/src/structures/BaseGuildEmoji.js @@ -0,0 +1,66 @@ +'use strict'; + +const Emoji = require('./Emoji'); + +/** + * Parent class for {@link GuildEmoji} and {@link GuildPreviewEmoji}. + * @extends {Emoji} + * @abstract + */ +class BaseGuildEmoji extends Emoji { + constructor(client, data, guild) { + super(client, data); + + /** + * The guild this emoji is a part of + * @type {Guild|GuildPreview} + */ + this.guild = guild; + + this.requireColons = null; + this.managed = null; + this.available = null; + + /** + * Array of role ids this emoji is active for + * @name BaseGuildEmoji#_roles + * @type {Snowflake[]} + * @private + */ + Object.defineProperty(this, '_roles', { value: [], writable: true }); + + this._patch(data); + } + + _patch(data) { + if (data.name) this.name = data.name; + + if (typeof data.require_colons !== 'undefined') { + /** + * Whether or not this emoji requires colons surrounding it + * @type {?boolean} + */ + this.requiresColons = data.require_colons; + } + + if (typeof data.managed !== 'undefined') { + /** + * Whether this emoji is managed by an external service + * @type {?boolean} + */ + this.managed = data.managed; + } + + if (typeof data.available !== 'undefined') { + /** + * Whether this emoji is available + * @type {?boolean} + */ + this.available = data.available; + } + + if (data.roles) this._roles = data.roles; + } +} + +module.exports = BaseGuildEmoji; diff --git a/node_modules/discord.js/src/structures/CategoryChannel.js b/node_modules/discord.js/src/structures/CategoryChannel.js new file mode 100644 index 0000000..4ba0140 --- /dev/null +++ b/node_modules/discord.js/src/structures/CategoryChannel.js @@ -0,0 +1,33 @@ +'use strict'; + +const GuildChannel = require('./GuildChannel'); + +/** + * Represents a guild category channel on Discord. + * @extends {GuildChannel} + */ +class CategoryChannel extends GuildChannel { + /** + * Channels that are a part of this category + * @type {Collection} + * @readonly + */ + get children() { + return this.guild.channels.cache.filter(c => c.parentID === this.id); + } + + /** + * Sets the category parent of this channel. + * It is not currently possible to set the parent of a CategoryChannel. + * @method setParent + * @memberof CategoryChannel + * @instance + * @param {?GuildChannel|Snowflake} channel Parent channel + * @param {Object} [options={}] Options to pass + * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are + * @param {string} [options.reason] Reason for modifying the parent of this channel + * @returns {Promise} + */ +} + +module.exports = CategoryChannel; diff --git a/node_modules/discord.js/src/structures/Channel.js b/node_modules/discord.js/src/structures/Channel.js new file mode 100644 index 0000000..baa02ee --- /dev/null +++ b/node_modules/discord.js/src/structures/Channel.js @@ -0,0 +1,161 @@ +'use strict'; + +const Base = require('./Base'); +const { ChannelTypes } = require('../util/Constants'); +const Snowflake = require('../util/Snowflake'); + +/** + * Represents any channel on Discord. + * @extends {Base} + * @abstract + */ +class Channel extends Base { + constructor(client, data) { + super(client); + + const type = Object.keys(ChannelTypes)[data.type]; + /** + * The type of the channel, either: + * * `dm` - a DM channel + * * `text` - a guild text channel + * * `voice` - a guild voice channel + * * `category` - a guild category channel + * * `news` - a guild news channel + * * `store` - a guild store channel + * * `unknown` - a generic channel of unknown type, could be Channel or GuildChannel + * @type {string} + */ + this.type = type ? type.toLowerCase() : 'unknown'; + + /** + * Whether the channel has been deleted + * @type {boolean} + */ + this.deleted = false; + + if (data) this._patch(data); + } + + _patch(data) { + /** + * The unique ID of the channel + * @type {Snowflake} + */ + this.id = data.id; + } + + /** + * The timestamp the channel was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the channel was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. + * @returns {string} + * @example + * // Logs: Hello from <#123456789012345678>! + * console.log(`Hello from ${channel}!`); + */ + toString() { + return `<#${this.id}>`; + } + + /** + * Deletes this channel. + * @returns {Promise} + * @example + * // Delete the channel + * channel.delete() + * .then(console.log) + * .catch(console.error); + */ + delete() { + return this.client.api + .channels(this.id) + .delete() + .then(() => this); + } + + /** + * Fetches this channel. + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + fetch(force = false) { + return this.client.channels.fetch(this.id, true, force); + } + + /** + * Indicates whether this channel is text-based. + * @returns {boolean} + */ + isText() { + return 'messages' in this; + } + + static create(client, data, guild) { + const Structures = require('../util/Structures'); + let channel; + if (!data.guild_id && !guild) { + if ((data.recipients && data.type !== ChannelTypes.GROUP) || data.type === ChannelTypes.DM) { + const DMChannel = Structures.get('DMChannel'); + channel = new DMChannel(client, data); + } else if (data.type === ChannelTypes.GROUP) { + const PartialGroupDMChannel = require('./PartialGroupDMChannel'); + channel = new PartialGroupDMChannel(client, data); + } + } else { + guild = guild || client.guilds.cache.get(data.guild_id); + if (guild) { + switch (data.type) { + case ChannelTypes.TEXT: { + const TextChannel = Structures.get('TextChannel'); + channel = new TextChannel(guild, data); + break; + } + case ChannelTypes.VOICE: { + const VoiceChannel = Structures.get('VoiceChannel'); + channel = new VoiceChannel(guild, data); + break; + } + case ChannelTypes.CATEGORY: { + const CategoryChannel = Structures.get('CategoryChannel'); + channel = new CategoryChannel(guild, data); + break; + } + case ChannelTypes.NEWS: { + const NewsChannel = Structures.get('NewsChannel'); + channel = new NewsChannel(guild, data); + break; + } + case ChannelTypes.STORE: { + const StoreChannel = Structures.get('StoreChannel'); + channel = new StoreChannel(guild, data); + break; + } + } + if (channel) guild.channels.cache.set(channel.id, channel); + } + } + return channel; + } + + toJSON(...props) { + return super.toJSON({ createdTimestamp: true }, ...props); + } +} + +module.exports = Channel; diff --git a/node_modules/discord.js/src/structures/ClientApplication.js b/node_modules/discord.js/src/structures/ClientApplication.js new file mode 100644 index 0000000..7e35b9e --- /dev/null +++ b/node_modules/discord.js/src/structures/ClientApplication.js @@ -0,0 +1,46 @@ +'use strict'; + +const Team = require('./Team'); +const Application = require('./interfaces/Application'); + +/** + * Represents a Client OAuth2 Application. + * @extends {Application} + */ +class ClientApplication extends Application { + _patch(data) { + super._patch(data); + + /** + * The app's cover image + * @type {?string} + */ + this.cover = data.cover_image || null; + + /** + * The app's RPC origins, if enabled + * @type {string[]} + */ + this.rpcOrigins = data.rpc_origins || []; + + /** + * If this app's bot requires a code grant when using the OAuth2 flow + * @type {?boolean} + */ + this.botRequireCodeGrant = typeof data.bot_require_code_grant !== 'undefined' ? data.bot_require_code_grant : null; + + /** + * If this app's bot is public + * @type {?boolean} + */ + this.botPublic = typeof data.bot_public !== 'undefined' ? data.bot_public : null; + + /** + * The owner of this OAuth application + * @type {?User|Team} + */ + this.owner = data.team ? new Team(this.client, data.team) : data.owner ? this.client.users.add(data.owner) : null; + } +} + +module.exports = ClientApplication; diff --git a/node_modules/discord.js/src/structures/ClientPresence.js b/node_modules/discord.js/src/structures/ClientPresence.js new file mode 100644 index 0000000..a39ba00 --- /dev/null +++ b/node_modules/discord.js/src/structures/ClientPresence.js @@ -0,0 +1,87 @@ +'use strict'; + +const { Presence } = require('./Presence'); +const { TypeError } = require('../errors'); +const Collection = require('../util/Collection'); +const { ActivityTypes, OPCodes } = require('../util/Constants'); + +class ClientPresence extends Presence { + /** + * @param {Client} client The instantiating client + * @param {Object} [data={}] The data for the client presence + */ + constructor(client, data = {}) { + super(client, Object.assign(data, { status: 'online', user: { id: null } })); + } + + async set(presence) { + const packet = await this._parse(presence); + this.patch(packet); + if (typeof presence.shardID === 'undefined') { + this.client.ws.broadcast({ op: OPCodes.STATUS_UPDATE, d: packet }); + } else if (Array.isArray(presence.shardID)) { + for (const shardID of presence.shardID) { + this.client.ws.shards.get(shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet }); + } + } else { + this.client.ws.shards.get(presence.shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet }); + } + return this; + } + + async _parse({ status, since, afk, activity }) { + const applicationID = activity && (activity.application ? activity.application.id || activity.application : null); + let assets = new Collection(); + if (activity) { + if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', 'name', 'string'); + if (!activity.type) activity.type = 0; + if (activity.assets && applicationID) { + try { + const a = await this.client.api.oauth2.applications(applicationID).assets.get(); + for (const asset of a) assets.set(asset.name, asset.id); + } catch {} // eslint-disable-line no-empty + } + } + + const packet = { + afk: afk != null ? afk : false, // eslint-disable-line eqeqeq + since: since != null ? since : null, // eslint-disable-line eqeqeq + status: status || this.status, + game: activity + ? { + type: activity.type, + name: activity.name, + url: activity.url, + details: activity.details || undefined, + state: activity.state || undefined, + assets: activity.assets + ? { + large_text: activity.assets.largeText || undefined, + small_text: activity.assets.smallText || undefined, + large_image: assets.get(activity.assets.largeImage) || activity.assets.largeImage, + small_image: assets.get(activity.assets.smallImage) || activity.assets.smallImage, + } + : undefined, + timestamps: activity.timestamps || undefined, + party: activity.party || undefined, + application_id: applicationID || undefined, + secrets: activity.secrets || undefined, + instance: activity.instance || undefined, + } + : null, + }; + + if ((status || afk || since) && !activity) { + packet.game = this.activities[0] || null; + } + + if (packet.game) { + packet.game.type = + typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type); + } + + return packet; + } +} + +module.exports = ClientPresence; diff --git a/node_modules/discord.js/src/structures/ClientUser.js b/node_modules/discord.js/src/structures/ClientUser.js new file mode 100644 index 0000000..65112b8 --- /dev/null +++ b/node_modules/discord.js/src/structures/ClientUser.js @@ -0,0 +1,178 @@ +'use strict'; + +const DataResolver = require('../util/DataResolver'); +const Structures = require('../util/Structures'); + +/** + * Represents the logged in client's Discord user. + * @extends {User} + */ +class ClientUser extends Structures.get('User') { + constructor(client, data) { + super(client, data); + this._typing = new Map(); + } + + _patch(data) { + super._patch(data); + + if ('verified' in data) { + /** + * Whether or not this account has been verified + * @type {boolean} + */ + this.verified = data.verified; + } + + if ('mfa_enabled' in data) { + /** + * If the bot's {@link ClientApplication#owner Owner} has MFA enabled on their account + * @type {?boolean} + */ + this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null; + } else if (typeof this.mfaEnabled === 'undefined') { + this.mfaEnabled = null; + } + + if (data.token) this.client.token = data.token; + } + + /** + * ClientUser's presence + * @type {Presence} + * @readonly + */ + get presence() { + return this.client.presence; + } + + edit(data) { + return this.client.api + .users('@me') + .patch({ data }) + .then(newData => { + this.client.token = newData.token; + const { updated } = this.client.actions.UserUpdate.handle(newData); + if (updated) return updated; + return this; + }); + } + + /** + * Sets the username of the logged in client. + * Changing usernames in Discord is heavily rate limited, with only 2 requests + * every hour. Use this sparingly! + * @param {string} username The new username + * @returns {Promise} + * @example + * // Set username + * client.user.setUsername('discordjs') + * .then(user => console.log(`My new username is ${user.username}`)) + * .catch(console.error); + */ + setUsername(username) { + return this.edit({ username }); + } + + /** + * Sets the avatar of the logged in client. + * @param {BufferResolvable|Base64Resolvable} avatar The new avatar + * @returns {Promise} + * @example + * // Set avatar + * client.user.setAvatar('./avatar.png') + * .then(user => console.log(`New avatar set!`)) + * .catch(console.error); + */ + async setAvatar(avatar) { + return this.edit({ avatar: await DataResolver.resolveImage(avatar) }); + } + + /** + * Data resembling a raw Discord presence. + * @typedef {Object} PresenceData + * @property {PresenceStatusData} [status] Status of the user + * @property {boolean} [afk] Whether the user is AFK + * @property {Object} [activity] Activity the user is playing + * @property {string} [activity.name] Name of the activity + * @property {ActivityType|number} [activity.type] Type of the activity + * @property {string} [activity.url] Twitch / YouTube stream URL + * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on + */ + + /** + * Sets the full presence of the client user. + * @param {PresenceData} data Data for the presence + * @returns {Promise} + * @example + * // Set the client user's presence + * client.user.setPresence({ activity: { name: 'with discord.js' }, status: 'idle' }) + * .then(console.log) + * .catch(console.error); + */ + setPresence(data) { + return this.client.presence.set(data); + } + + /** + * A user's status. Must be one of: + * * `online` + * * `idle` + * * `invisible` + * * `dnd` (do not disturb) + * @typedef {string} PresenceStatusData + */ + + /** + * Sets the status of the client user. + * @param {PresenceStatusData} status Status to change to + * @param {?number|number[]} [shardID] Shard ID(s) to have the activity set on + * @returns {Promise} + * @example + * // Set the client user's status + * client.user.setStatus('idle') + * .then(console.log) + * .catch(console.error); + */ + setStatus(status, shardID) { + return this.setPresence({ status, shardID }); + } + + /** + * Options for setting an activity. + * @typedef ActivityOptions + * @type {Object} + * @property {string} [url] Twitch / YouTube stream URL + * @property {ActivityType|number} [type] Type of the activity + * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on + */ + + /** + * Sets the activity the client user is playing. + * @param {string|ActivityOptions} [name] Activity being played, or options for setting the activity + * @param {ActivityOptions} [options] Options for setting the activity + * @returns {Promise} + * @example + * // Set the client user's activity + * client.user.setActivity('discord.js', { type: 'WATCHING' }) + * .then(presence => console.log(`Activity set to ${presence.activities[0].name}`)) + * .catch(console.error); + */ + setActivity(name, options = {}) { + if (!name) return this.setPresence({ activity: null, shardID: options.shardID }); + + const activity = Object.assign({}, options, typeof name === 'object' ? name : { name }); + return this.setPresence({ activity, shardID: activity.shardID }); + } + + /** + * Sets/removes the AFK flag for the client user. + * @param {boolean} afk Whether or not the user is AFK + * @returns {Promise} + */ + setAFK(afk) { + return this.setPresence({ afk }); + } +} + +module.exports = ClientUser; diff --git a/node_modules/discord.js/src/structures/DMChannel.js b/node_modules/discord.js/src/structures/DMChannel.js new file mode 100644 index 0000000..4807597 --- /dev/null +++ b/node_modules/discord.js/src/structures/DMChannel.js @@ -0,0 +1,99 @@ +'use strict'; + +const Channel = require('./Channel'); +const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const MessageManager = require('../managers/MessageManager'); + +/** + * Represents a direct message channel between two users. + * @extends {Channel} + * @implements {TextBasedChannel} + */ +class DMChannel extends Channel { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the DM channel + */ + constructor(client, data) { + super(client, data); + // Override the channel type so partials have a known type + this.type = 'dm'; + /** + * A manager of the messages belonging to this channel + * @type {MessageManager} + */ + this.messages = new MessageManager(this); + this._typing = new Map(); + } + + _patch(data) { + super._patch(data); + + if (data.recipients) { + /** + * The recipient on the other end of the DM + * @type {User} + */ + this.recipient = this.client.users.add(data.recipients[0]); + } + + /** + * The ID of the last message in the channel, if one was sent + * @type {?Snowflake} + */ + this.lastMessageID = data.last_message_id; + + /** + * The timestamp when the last pinned message was pinned, if there was one + * @type {?number} + */ + this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null; + } + + /** + * Whether this DMChannel is a partial + * @type {boolean} + * @readonly + */ + get partial() { + return typeof this.lastMessageID === 'undefined'; + } + + /** + * Fetch this DMChannel. + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + fetch(force = false) { + return this.recipient.createDM(force); + } + + /** + * When concatenated with a string, this automatically returns the recipient's mention instead of the + * DMChannel object. + * @returns {string} + * @example + * // Logs: Hello from <@123456789012345678>! + * console.log(`Hello from ${channel}!`); + */ + toString() { + return this.recipient.toString(); + } + + // These are here only for documentation purposes - they are implemented by TextBasedChannel + /* eslint-disable no-empty-function */ + get lastMessage() {} + get lastPinAt() {} + send() {} + startTyping() {} + stopTyping() {} + get typing() {} + get typingCount() {} + createMessageCollector() {} + awaitMessages() {} + // Doesn't work on DM channels; bulkDelete() {} +} + +TextBasedChannel.applyToClass(DMChannel, true, ['bulkDelete']); + +module.exports = DMChannel; diff --git a/node_modules/discord.js/src/structures/Emoji.js b/node_modules/discord.js/src/structures/Emoji.js new file mode 100644 index 0000000..0214ea8 --- /dev/null +++ b/node_modules/discord.js/src/structures/Emoji.js @@ -0,0 +1,104 @@ +'use strict'; + +const Base = require('./Base'); +const Snowflake = require('../util/Snowflake'); + +/** + * Represents an emoji, see {@link GuildEmoji} and {@link ReactionEmoji}. + * @extends {Base} + */ +class Emoji extends Base { + constructor(client, emoji) { + super(client); + /** + * Whether this emoji is animated + * @type {boolean} + */ + this.animated = emoji.animated; + + /** + * The name of this emoji + * @type {string} + */ + this.name = emoji.name; + + /** + * The ID of this emoji + * @type {?Snowflake} + */ + this.id = emoji.id; + + /** + * Whether this emoji has been deleted + * @type {boolean} + */ + this.deleted = false; + } + + /** + * The identifier of this emoji, used for message reactions + * @type {string} + * @readonly + */ + get identifier() { + if (this.id) return `${this.animated ? 'a:' : ''}${this.name}:${this.id}`; + return encodeURIComponent(this.name); + } + + /** + * The URL to the emoji file if its a custom emoji + * @type {?string} + * @readonly + */ + get url() { + if (!this.id) return null; + return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png'); + } + + /** + * The timestamp the emoji was created at, or null if unicode + * @type {?number} + * @readonly + */ + get createdTimestamp() { + if (!this.id) return null; + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the emoji was created at, or null if unicode + * @type {?Date} + * @readonly + */ + get createdAt() { + if (!this.id) return null; + return new Date(this.createdTimestamp); + } + + /** + * When concatenated with a string, this automatically returns the text required to form a graphical emoji on Discord + * instead of the Emoji object. + * @returns {string} + * @example + * // Send a custom emoji from a guild: + * const emoji = guild.emojis.cache.first(); + * msg.reply(`Hello! ${emoji}`); + * @example + * // Send the emoji used in a reaction to the channel the reaction is part of + * reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`); + */ + toString() { + return this.id ? `<${this.animated ? 'a' : ''}:${this.name}:${this.id}>` : this.name; + } + + toJSON() { + return super.toJSON({ + guild: 'guildID', + createdTimestamp: true, + url: true, + identifier: true, + }); + } +} + +module.exports = Emoji; diff --git a/node_modules/discord.js/src/structures/Guild.js b/node_modules/discord.js/src/structures/Guild.js new file mode 100644 index 0000000..46dc76a --- /dev/null +++ b/node_modules/discord.js/src/structures/Guild.js @@ -0,0 +1,1583 @@ +'use strict'; + +const { deprecate } = require('util'); +const Base = require('./Base'); +const GuildAuditLogs = require('./GuildAuditLogs'); +const GuildPreview = require('./GuildPreview'); +const GuildTemplate = require('./GuildTemplate'); +const Integration = require('./Integration'); +const Invite = require('./Invite'); +const VoiceRegion = require('./VoiceRegion'); +const Webhook = require('./Webhook'); +const { Error, TypeError } = require('../errors'); +const GuildChannelManager = require('../managers/GuildChannelManager'); +const GuildEmojiManager = require('../managers/GuildEmojiManager'); +const GuildMemberManager = require('../managers/GuildMemberManager'); +const PresenceManager = require('../managers/PresenceManager'); +const RoleManager = require('../managers/RoleManager'); +const VoiceStateManager = require('../managers/VoiceStateManager'); +const Collection = require('../util/Collection'); +const { + browser, + ChannelTypes, + DefaultMessageNotifications, + PartialTypes, + VerificationLevels, + ExplicitContentFilterLevels, +} = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); +const Snowflake = require('../util/Snowflake'); +const SystemChannelFlags = require('../util/SystemChannelFlags'); +const Util = require('../util/Util'); + +/** + * Represents a guild (or a server) on Discord. + * It's recommended to see if a guild is available before performing operations or reading data from it. You can + * check this with `guild.available`. + * @extends {Base} + */ +class Guild extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the guild + */ + constructor(client, data) { + super(client); + + /** + * A manager of the members belonging to this guild + * @type {GuildMemberManager} + */ + this.members = new GuildMemberManager(this); + + /** + * A manager of the channels belonging to this guild + * @type {GuildChannelManager} + */ + this.channels = new GuildChannelManager(this); + + /** + * A manager of the roles belonging to this guild + * @type {RoleManager} + */ + this.roles = new RoleManager(this); + + /** + * A manager of the presences belonging to this guild + * @type {PresenceManager} + */ + this.presences = new PresenceManager(this.client); + + /** + * A manager of the voice states of this guild + * @type {VoiceStateManager} + */ + this.voiceStates = new VoiceStateManager(this); + + /** + * Whether the bot has been removed from the guild + * @type {boolean} + */ + this.deleted = false; + + if (!data) return; + if (data.unavailable) { + /** + * Whether the guild is available to access. If it is not available, it indicates a server outage + * @type {boolean} + */ + this.available = false; + + /** + * The Unique ID of the guild, useful for comparisons + * @type {Snowflake} + */ + this.id = data.id; + } else { + this._patch(data); + if (!data.channels) this.available = false; + } + + /** + * The id of the shard this Guild belongs to. + * @type {number} + */ + this.shardID = data.shardID; + } + + /** + * The Shard this Guild belongs to. + * @type {WebSocketShard} + * @readonly + */ + get shard() { + return this.client.ws.shards.get(this.shardID); + } + + /** + * Sets up the guild. + * @param {*} data The raw data of the guild + * @private + */ + _patch(data) { + /** + * The name of the guild + * @type {string} + */ + this.name = data.name; + + /** + * The hash of the guild icon + * @type {?string} + */ + this.icon = data.icon; + + /** + * The hash of the guild invite splash image + * @type {?string} + */ + this.splash = data.splash; + + /** + * The hash of the guild discovery splash image + * @type {?string} + */ + this.discoverySplash = data.discovery_splash; + + /** + * The region the guild is located in + * @type {string} + */ + this.region = data.region; + + /** + * The full amount of members in this guild + * @type {number} + */ + this.memberCount = data.member_count || this.memberCount; + + /** + * Whether the guild is "large" (has more than large_threshold members, 50 by default) + * @type {boolean} + */ + this.large = Boolean('large' in data ? data.large : this.large); + + /** + * An array of enabled guild features, here are the possible values: + * * ANIMATED_ICON + * * BANNER + * * COMMERCE + * * COMMUNITY + * * DISCOVERABLE + * * FEATURABLE + * * INVITE_SPLASH + * * NEWS + * * PARTNERED + * * RELAY_ENABLED + * * VANITY_URL + * * VERIFIED + * * VIP_REGIONS + * * WELCOME_SCREEN_ENABLED + * @typedef {string} Features + */ + + /** + * An array of guild features partnered guilds have enabled + * @type {Features[]} + */ + this.features = data.features; + + /** + * The ID of the application that created this guild (if applicable) + * @type {?Snowflake} + */ + this.applicationID = data.application_id; + + /** + * The time in seconds before a user is counted as "away from keyboard" + * @type {?number} + */ + this.afkTimeout = data.afk_timeout; + + /** + * The ID of the voice channel where AFK members are moved + * @type {?Snowflake} + */ + this.afkChannelID = data.afk_channel_id; + + /** + * The ID of the system channel + * @type {?Snowflake} + */ + this.systemChannelID = data.system_channel_id; + + /** + * Whether embedded images are enabled on this guild + * @type {boolean} + * @deprecated + */ + this.embedEnabled = data.embed_enabled; + + /** + * The type of premium tier: + * * 0: NONE + * * 1: TIER_1 + * * 2: TIER_2 + * * 3: TIER_3 + * @typedef {number} PremiumTier + */ + + /** + * The premium tier on this guild + * @type {PremiumTier} + */ + this.premiumTier = data.premium_tier; + + if (typeof data.premium_subscription_count !== 'undefined') { + /** + * The total number of boosts for this server + * @type {?number} + */ + this.premiumSubscriptionCount = data.premium_subscription_count; + } + + if (typeof data.widget_enabled !== 'undefined') { + /** + * Whether widget images are enabled on this guild + * @type {?boolean} + */ + this.widgetEnabled = data.widget_enabled; + } + + if (typeof data.widget_channel_id !== 'undefined') { + /** + * The widget channel ID, if enabled + * @type {?string} + */ + this.widgetChannelID = data.widget_channel_id; + } + + if (typeof data.embed_channel_id !== 'undefined') { + /** + * The embed channel ID, if enabled + * @type {?string} + * @deprecated + */ + this.embedChannelID = data.embed_channel_id; + } + + /** + * The verification level of the guild + * @type {VerificationLevel} + */ + this.verificationLevel = VerificationLevels[data.verification_level]; + + /** + * The explicit content filter level of the guild + * @type {ExplicitContentFilterLevel} + */ + this.explicitContentFilter = ExplicitContentFilterLevels[data.explicit_content_filter]; + + /** + * The required MFA level for the guild + * @type {number} + */ + this.mfaLevel = data.mfa_level; + + /** + * The timestamp the client user joined the guild at + * @type {number} + */ + this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp; + + /** + * The value set for the guild's default message notifications + * @type {DefaultMessageNotifications|number} + */ + this.defaultMessageNotifications = + DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications; + + /** + * The value set for the guild's system channel flags + * @type {Readonly} + */ + this.systemChannelFlags = new SystemChannelFlags(data.system_channel_flags).freeze(); + + if (typeof data.max_members !== 'undefined') { + /** + * The maximum amount of members the guild can have + * @type {?number} + */ + this.maximumMembers = data.max_members; + } else if (typeof this.maximumMembers === 'undefined') { + this.maximumMembers = null; + } + + if (typeof data.max_presences !== 'undefined') { + /** + * The maximum amount of presences the guild can have + * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter + * @type {?number} + */ + this.maximumPresences = data.max_presences || 25000; + } else if (typeof this.maximumPresences === 'undefined') { + this.maximumPresences = null; + } + + if (typeof data.approximate_member_count !== 'undefined') { + /** + * The approximate amount of members the guild has + * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter + * @type {?number} + */ + this.approximateMemberCount = data.approximate_member_count; + } else if (typeof this.approximateMemberCount === 'undefined') { + this.approximateMemberCount = null; + } + + if (typeof data.approximate_presence_count !== 'undefined') { + /** + * The approximate amount of presences the guild has + * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter + * @type {?number} + */ + this.approximatePresenceCount = data.approximate_presence_count; + } else if (typeof this.approximatePresenceCount === 'undefined') { + this.approximatePresenceCount = null; + } + + /** + * The vanity invite code of the guild, if any + * @type {?string} + */ + this.vanityURLCode = data.vanity_url_code; + + /* eslint-disable max-len */ + /** + * The use count of the vanity URL code of the guild, if any + * You will need to fetch this parameter using {@link Guild#fetchVanityData} if you want to receive it + * @type {?number} + */ + this.vanityURLUses = null; + /* eslint-enable max-len */ + + /** + * The description of the guild, if any + * @type {?string} + */ + this.description = data.description; + + /** + * The hash of the guild banner + * @type {?string} + */ + this.banner = data.banner; + + this.id = data.id; + this.available = !data.unavailable; + this.features = data.features || this.features || []; + + /** + * The ID of the rules channel for the guild + * @type {?Snowflake} + */ + this.rulesChannelID = data.rules_channel_id; + + /** + * The ID of the community updates channel for the guild + * @type {?Snowflake} + */ + this.publicUpdatesChannelID = data.public_updates_channel_id; + + /** + * The preferred locale of the guild, defaults to `en-US` + * @type {string} + */ + this.preferredLocale = data.preferred_locale; + + if (data.channels) { + this.channels.cache.clear(); + for (const rawChannel of data.channels) { + this.client.channels.add(rawChannel, this); + } + } + + if (data.roles) { + this.roles.cache.clear(); + for (const role of data.roles) this.roles.add(role); + } + + if (data.members) { + this.members.cache.clear(); + for (const guildUser of data.members) this.members.add(guildUser); + } + + if (data.owner_id) { + /** + * The user ID of this guild's owner + * @type {Snowflake} + */ + this.ownerID = data.owner_id; + } + + if (data.presences) { + for (const presence of data.presences) { + this.presences.add(Object.assign(presence, { guild: this })); + } + } + + if (data.voice_states) { + this.voiceStates.cache.clear(); + for (const voiceState of data.voice_states) { + this.voiceStates.add(voiceState); + } + } + + if (!this.emojis) { + /** + * A manager of the emojis belonging to this guild + * @type {GuildEmojiManager} + */ + this.emojis = new GuildEmojiManager(this); + if (data.emojis) for (const emoji of data.emojis) this.emojis.add(emoji); + } else if (data.emojis) { + this.client.actions.GuildEmojisUpdate.handle({ + guild_id: this.id, + emojis: data.emojis, + }); + } + } + + /** + * The URL to this guild's banner. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + bannerURL({ format, size } = {}) { + if (!this.banner) return null; + return this.client.rest.cdn.Banner(this.id, this.banner, format, size); + } + + /** + * The timestamp the guild was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the guild was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The time the client user joined the guild + * @type {Date} + * @readonly + */ + get joinedAt() { + return new Date(this.joinedTimestamp); + } + + /** + * If this guild is partnered + * @type {boolean} + * @readonly + */ + get partnered() { + return this.features.includes('PARTNERED'); + } + + /** + * If this guild is verified + * @type {boolean} + * @readonly + */ + get verified() { + return this.features.includes('VERIFIED'); + } + + /** + * The URL to this guild's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + iconURL({ format, size, dynamic } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); + } + + /** + * The acronym that shows up in place of a guild icon. + * @type {string} + * @readonly + */ + get nameAcronym() { + return this.name + .replace(/'s /g, ' ') + .replace(/\w+/g, e => e[0]) + .replace(/\s/g, ''); + } + + /** + * The URL to this guild's invite splash image. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + splashURL({ format, size } = {}) { + if (!this.splash) return null; + return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + } + + /** + * The URL to this guild's discovery splash image. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + discoverySplashURL({ format, size } = {}) { + if (!this.discoverySplash) return null; + return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + } + + /** + * The owner of the guild + * @type {?GuildMember} + * @readonly + */ + get owner() { + return ( + this.members.cache.get(this.ownerID) || + (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) + ? this.members.add({ user: { id: this.ownerID } }, true) + : null) + ); + } + + /** + * AFK voice channel for this guild + * @type {?VoiceChannel} + * @readonly + */ + get afkChannel() { + return this.client.channels.cache.get(this.afkChannelID) || null; + } + + /** + * System channel for this guild + * @type {?TextChannel} + * @readonly + */ + get systemChannel() { + return this.client.channels.cache.get(this.systemChannelID) || null; + } + + /** + * Widget channel for this guild + * @type {?TextChannel} + * @readonly + */ + get widgetChannel() { + return this.client.channels.cache.get(this.widgetChannelID) || null; + } + + /** + * Embed channel for this guild + * @type {?TextChannel} + * @readonly + * @deprecated + */ + get embedChannel() { + return this.client.channels.cache.get(this.embedChannelID) || null; + } + + /** + * Rules channel for this guild + * @type {?TextChannel} + * @readonly + */ + get rulesChannel() { + return this.client.channels.cache.get(this.rulesChannelID) || null; + } + + /** + * Public updates channel for this guild + * @type {?TextChannel} + * @readonly + */ + get publicUpdatesChannel() { + return this.client.channels.cache.get(this.publicUpdatesChannelID) || null; + } + + /** + * The client user as a GuildMember of this guild + * @type {?GuildMember} + * @readonly + */ + get me() { + return ( + this.members.cache.get(this.client.user.id) || + (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) + ? this.members.add({ user: { id: this.client.user.id } }, true) + : null) + ); + } + + /** + * The voice state for the client user of this guild, if any + * @type {?VoiceState} + * @readonly + */ + get voice() { + return this.voiceStates.cache.get(this.client.user.id); + } + + /** + * Returns the GuildMember form of a User object, if the user is present in the guild. + * @param {UserResolvable} user The user that you want to obtain the GuildMember of + * @returns {?GuildMember} + * @example + * // Get the guild member of a user + * const member = guild.member(message.author); + */ + member(user) { + return this.members.resolve(user); + } + + /** + * Fetches this guild. + * @returns {Promise} + */ + fetch() { + return this.client.api + .guilds(this.id) + .get({ query: { with_counts: true } }) + .then(data => { + this._patch(data); + return this; + }); + } + + /** + * An object containing information about a guild member's ban. + * @typedef {Object} BanInfo + * @property {User} user User that was banned + * @property {?string} reason Reason the user was banned + */ + + /** + * Fetches information on a banned user from this guild. + * @param {UserResolvable} user The User to fetch the ban info of + * @returns {Promise} + */ + fetchBan(user) { + const id = this.client.users.resolveID(user); + if (!id) throw new Error('FETCH_BAN_RESOLVE_ID'); + return this.client.api + .guilds(this.id) + .bans(id) + .get() + .then(ban => ({ + reason: ban.reason, + user: this.client.users.add(ban.user), + })); + } + + /** + * Fetches a collection of banned users in this guild. + * @returns {Promise>} + */ + fetchBans() { + return this.client.api + .guilds(this.id) + .bans.get() + .then(bans => + bans.reduce((collection, ban) => { + collection.set(ban.user.id, { + reason: ban.reason, + user: this.client.users.add(ban.user), + }); + return collection; + }, new Collection()), + ); + } + + /** + * Fetches a collection of integrations to this guild. + * Resolves with a collection mapping integrations by their ids. + * @param {Object} [options] Options for fetching integrations + * @param {boolean} [options.includeApplications] Whether to include bot and Oauth2 webhook integrations + * @returns {Promise>} + * @example + * // Fetch integrations + * guild.fetchIntegrations() + * .then(integrations => console.log(`Fetched ${integrations.size} integrations`)) + * .catch(console.error); + */ + fetchIntegrations({ includeApplications = false } = {}) { + return this.client.api + .guilds(this.id) + .integrations.get({ + query: { + include_applications: includeApplications, + }, + }) + .then(data => + data.reduce( + (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)), + new Collection(), + ), + ); + } + + /** + * Fetches a collection of templates from this guild. + * Resolves with a collection mapping templates by their codes. + * @returns {Promise>} + */ + fetchTemplates() { + return this.client.api + .guilds(this.id) + .templates.get() + .then(templates => + templates.reduce((col, data) => col.set(data.code, new GuildTemplate(this.client, data)), new Collection()), + ); + } + + /** + * The data for creating an integration. + * @typedef {Object} IntegrationData + * @property {string} id The integration id + * @property {string} type The integration type + */ + + /** + * Creates an integration by attaching an integration object + * @param {IntegrationData} data The data for the integration + * @param {string} reason Reason for creating the integration + * @returns {Promise} + */ + createIntegration(data, reason) { + return this.client.api + .guilds(this.id) + .integrations.post({ data, reason }) + .then(() => this); + } + + /** + * Creates a template for the guild. + * @param {string} name The name for the template + * @param {string} [description] The description for the template + * @returns {Promise} + */ + createTemplate(name, description) { + return this.client.api + .guilds(this.id) + .templates.post({ data: { name, description } }) + .then(data => new GuildTemplate(this.client, data)); + } + + /** + * Fetches a collection of invites to this guild. + * Resolves with a collection mapping invites by their codes. + * @returns {Promise>} + * @example + * // Fetch invites + * guild.fetchInvites() + * .then(invites => console.log(`Fetched ${invites.size} invites`)) + * .catch(console.error); + * @example + * // Fetch invite creator by their id + * guild.fetchInvites() + * .then(invites => console.log(invites.find(invite => invite.inviter.id === '84484653687267328'))) + * .catch(console.error); + */ + fetchInvites() { + return this.client.api + .guilds(this.id) + .invites.get() + .then(inviteItems => { + const invites = new Collection(); + for (const inviteItem of inviteItems) { + const invite = new Invite(this.client, inviteItem); + invites.set(invite.code, invite); + } + return invites; + }); + } + + /** + * Obtains a guild preview for this guild from Discord. + * @returns {Promise} + */ + fetchPreview() { + return this.client.api + .guilds(this.id) + .preview.get() + .then(data => new GuildPreview(this.client, data)); + } + + /** + * Fetches the vanity url invite code to this guild. + * Resolves with a string matching the vanity url invite code, not the full url. + * @returns {Promise} + * @deprecated + * @example + * // Fetch invites + * guild.fetchVanityCode() + * .then(code => { + * console.log(`Vanity URL: https://discord.gg/${code}`); + * }) + * .catch(console.error); + */ + fetchVanityCode() { + return this.fetchVanityData().then(vanity => vanity.code); + } + + /** + * An object containing information about a guild's vanity invite. + * @typedef {Object} Vanity + * @property {?string} code Vanity invite code + * @property {?number} uses How many times this invite has been used + */ + + /** + * Fetches the vanity url invite object to this guild. + * Resolves with an object containing the vanity url invite code and the use count + * @returns {Promise} + * @example + * // Fetch invite data + * guild.fetchVanityData() + * .then(res => { + * console.log(`Vanity URL: https://discord.gg/${res.code} with ${res.uses} uses`); + * }) + * .catch(console.error); + */ + async fetchVanityData() { + if (!this.features.includes('VANITY_URL')) { + throw new Error('VANITY_URL'); + } + const data = await this.client.api.guilds(this.id, 'vanity-url').get(); + this.vanityURLUses = data.uses; + + return data; + } + + /** + * Fetches all webhooks for the guild. + * @returns {Promise>} + * @example + * // Fetch webhooks + * guild.fetchWebhooks() + * .then(webhooks => console.log(`Fetched ${webhooks.size} webhooks`)) + * .catch(console.error); + */ + fetchWebhooks() { + return this.client.api + .guilds(this.id) + .webhooks.get() + .then(data => { + const hooks = new Collection(); + for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook)); + return hooks; + }); + } + + /** + * Fetches available voice regions. + * @returns {Promise>} + */ + fetchVoiceRegions() { + return this.client.api + .guilds(this.id) + .regions.get() + .then(res => { + const regions = new Collection(); + for (const region of res) regions.set(region.id, new VoiceRegion(region)); + return regions; + }); + } + + /** + * Data for the Guild Widget object + * @typedef {Object} GuildWidget + * @property {boolean} enabled Whether the widget is enabled + * @property {?GuildChannel} channel The widget channel + */ + + /** + * The Guild Widget object + * @typedef {Object} GuildWidgetData + * @property {boolean} enabled Whether the widget is enabled + * @property {?GuildChannelResolvable} channel The widget channel + */ + + /** + * Fetches the guild embed. + * @returns {Promise} + * @deprecated + * @example + * // Fetches the guild embed + * guild.fetchEmbed() + * .then(embed => console.log(`The embed is ${embed.enabled ? 'enabled' : 'disabled'}`)) + * .catch(console.error); + */ + fetchEmbed() { + return this.fetchWidget(); + } + + /** + * Fetches the guild widget. + * @returns {Promise} + * @example + * // Fetches the guild widget + * guild.fetchWidget() + * .then(widget => console.log(`The widget is ${widget.enabled ? 'enabled' : 'disabled'}`)) + * .catch(console.error); + */ + async fetchWidget() { + const data = await this.client.api.guilds(this.id).widget.get(); + this.widgetEnabled = this.embedEnabled = data.enabled; + this.widgetChannelID = this.embedChannelID = data.channel_id; + return { + enabled: data.enabled, + channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null, + }; + } + + /** + * Fetches audit logs for this guild. + * @param {Object} [options={}] Options for fetching audit logs + * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry + * @param {number} [options.limit] Limit number of entries + * @param {UserResolvable} [options.user] Only show entries involving this user + * @param {AuditLogAction|number} [options.type] Only show entries involving this action type + * @returns {Promise} + * @example + * // Output audit log entries + * guild.fetchAuditLogs() + * .then(audit => console.log(audit.entries.first())) + * .catch(console.error); + */ + fetchAuditLogs(options = {}) { + if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; + if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type]; + + return this.client.api + .guilds(this.id) + ['audit-logs'].get({ + query: { + before: options.before, + limit: options.limit, + user_id: this.client.users.resolveID(options.user), + action_type: options.type, + }, + }) + .then(data => GuildAuditLogs.build(this, data)); + } + + /** + * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission. + * @param {UserResolvable} user User to add to the guild + * @param {Object} options Options for the addition + * @param {string} options.accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the + * bot's application + * @param {string} [options.nick] Nickname to give the member (requires `MANAGE_NICKNAMES`) + * @param {Collection|RoleResolvable[]} [options.roles] Roles to add to the member + * (requires `MANAGE_ROLES`) + * @param {boolean} [options.mute] Whether the member should be muted (requires `MUTE_MEMBERS`) + * @param {boolean} [options.deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`) + * @returns {Promise} + */ + async addMember(user, options) { + user = this.client.users.resolveID(user); + if (!user) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + if (this.members.cache.has(user)) return this.members.cache.get(user); + options.access_token = options.accessToken; + if (options.roles) { + const roles = []; + for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) { + role = this.roles.resolve(role); + if (!role) { + throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true); + } + roles.push(role.id); + } + options.roles = roles; + } + const data = await this.client.api.guilds(this.id).members(user).put({ data: options }); + // Data is an empty buffer if the member is already part of the guild. + return data instanceof (browser ? ArrayBuffer : Buffer) ? this.members.fetch(user) : this.members.add(data); + } + + /** + * The data for editing a guild. + * @typedef {Object} GuildEditData + * @property {string} [name] The name of the guild + * @property {string} [region] The region of the guild + * @property {VerificationLevel|number} [verificationLevel] The verification level of the guild + * @property {ExplicitContentFilterLevel|number} [explicitContentFilter] The level of the explicit content filter + * @property {ChannelResolvable} [afkChannel] The AFK channel of the guild + * @property {ChannelResolvable} [systemChannel] The system channel of the guild + * @property {number} [afkTimeout] The AFK timeout of the guild + * @property {Base64Resolvable} [icon] The icon of the guild + * @property {GuildMemberResolvable} [owner] The owner of the guild + * @property {Base64Resolvable} [splash] The invite splash image of the guild + * @property {Base64Resolvable} [discoverySplash] The discovery splash image of the guild + * @property {Base64Resolvable} [banner] The banner of the guild + * @property {DefaultMessageNotifications|number} [defaultMessageNotifications] The default message notifications + * @property {SystemChannelFlagsResolvable} [systemChannelFlags] The system channel flags of the guild + * @property {ChannelResolvable} [rulesChannel] The rules channel of the guild + * @property {ChannelResolvable} [publicUpdatesChannel] The community updates channel of the guild + * @property {string} [preferredLocale] The preferred locale of the guild + */ + + /** + * Updates the guild with new information - e.g. a new name. + * @param {GuildEditData} data The data to update the guild with + * @param {string} [reason] Reason for editing this guild + * @returns {Promise} + * @example + * // Set the guild name and region + * guild.edit({ + * name: 'Discord Guild', + * region: 'london', + * }) + * .then(updated => console.log(`New guild name ${updated} in region ${updated.region}`)) + * .catch(console.error); + */ + edit(data, reason) { + const _data = {}; + if (data.name) _data.name = data.name; + if (data.region) _data.region = data.region; + if (typeof data.verificationLevel !== 'undefined') { + _data.verification_level = + typeof data.verificationLevel === 'number' + ? Number(data.verificationLevel) + : VerificationLevels.indexOf(data.verificationLevel); + } + if (typeof data.afkChannel !== 'undefined') { + _data.afk_channel_id = this.client.channels.resolveID(data.afkChannel); + } + if (typeof data.systemChannel !== 'undefined') { + _data.system_channel_id = this.client.channels.resolveID(data.systemChannel); + } + if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout); + if (typeof data.icon !== 'undefined') _data.icon = data.icon; + if (data.owner) _data.owner_id = this.client.users.resolveID(data.owner); + if (data.splash) _data.splash = data.splash; + if (data.discoverySplash) _data.discovery_splash = data.discoverySplash; + if (data.banner) _data.banner = data.banner; + if (typeof data.explicitContentFilter !== 'undefined') { + _data.explicit_content_filter = + typeof data.explicitContentFilter === 'number' + ? data.explicitContentFilter + : ExplicitContentFilterLevels.indexOf(data.explicitContentFilter); + } + if (typeof data.defaultMessageNotifications !== 'undefined') { + _data.default_message_notifications = + typeof data.defaultMessageNotifications === 'string' + ? DefaultMessageNotifications.indexOf(data.defaultMessageNotifications) + : data.defaultMessageNotifications; + } + if (typeof data.systemChannelFlags !== 'undefined') { + _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags); + } + if (typeof data.rulesChannel !== 'undefined') { + _data.rules_channel_id = this.client.channels.resolveID(data.rulesChannel); + } + if (typeof data.publicUpdatesChannel !== 'undefined') { + _data.public_updates_channel_id = this.client.channels.resolveID(data.publicUpdatesChannel); + } + if (data.preferredLocale) _data.preferred_locale = data.preferredLocale; + return this.client.api + .guilds(this.id) + .patch({ data: _data, reason }) + .then(newData => this.client.actions.GuildUpdate.handle(newData).updated); + } + + /** + * Edits the level of the explicit content filter. + * @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter + * @param {string} [reason] Reason for changing the level of the guild's explicit content filter + * @returns {Promise} + */ + setExplicitContentFilter(explicitContentFilter, reason) { + return this.edit({ explicitContentFilter }, reason); + } + + /* eslint-disable max-len */ + /** + * Edits the setting of the default message notifications of the guild. + * @param {DefaultMessageNotifications|number} defaultMessageNotifications The new setting for the default message notifications + * @param {string} [reason] Reason for changing the setting of the default message notifications + * @returns {Promise} + */ + setDefaultMessageNotifications(defaultMessageNotifications, reason) { + return this.edit({ defaultMessageNotifications }, reason); + } + /* eslint-enable max-len */ + + /** + * Edits the flags of the default message notifications of the guild. + * @param {SystemChannelFlagsResolvable} systemChannelFlags The new flags for the default message notifications + * @param {string} [reason] Reason for changing the flags of the default message notifications + * @returns {Promise} + */ + setSystemChannelFlags(systemChannelFlags, reason) { + return this.edit({ systemChannelFlags }, reason); + } + + /** + * Edits the name of the guild. + * @param {string} name The new name of the guild + * @param {string} [reason] Reason for changing the guild's name + * @returns {Promise} + * @example + * // Edit the guild name + * guild.setName('Discord Guild') + * .then(updated => console.log(`Updated guild name to ${updated.name}`)) + * .catch(console.error); + */ + setName(name, reason) { + return this.edit({ name }, reason); + } + + /** + * Edits the region of the guild. + * @param {string} region The new region of the guild + * @param {string} [reason] Reason for changing the guild's region + * @returns {Promise} + * @example + * // Edit the guild region + * guild.setRegion('london') + * .then(updated => console.log(`Updated guild region to ${updated.region}`)) + * .catch(console.error); + */ + setRegion(region, reason) { + return this.edit({ region }, reason); + } + + /** + * Edits the verification level of the guild. + * @param {VerificationLevel|number} verificationLevel The new verification level of the guild + * @param {string} [reason] Reason for changing the guild's verification level + * @returns {Promise} + * @example + * // Edit the guild verification level + * guild.setVerificationLevel(1) + * .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`)) + * .catch(console.error); + */ + setVerificationLevel(verificationLevel, reason) { + return this.edit({ verificationLevel }, reason); + } + + /** + * Edits the AFK channel of the guild. + * @param {ChannelResolvable} afkChannel The new AFK channel + * @param {string} [reason] Reason for changing the guild's AFK channel + * @returns {Promise} + * @example + * // Edit the guild AFK channel + * guild.setAFKChannel(channel) + * .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel.name}`)) + * .catch(console.error); + */ + setAFKChannel(afkChannel, reason) { + return this.edit({ afkChannel }, reason); + } + + /** + * Edits the system channel of the guild. + * @param {ChannelResolvable} systemChannel The new system channel + * @param {string} [reason] Reason for changing the guild's system channel + * @returns {Promise} + * @example + * // Edit the guild system channel + * guild.setSystemChannel(channel) + * .then(updated => console.log(`Updated guild system channel to ${guild.systemChannel.name}`)) + * .catch(console.error); + */ + setSystemChannel(systemChannel, reason) { + return this.edit({ systemChannel }, reason); + } + + /** + * Edits the AFK timeout of the guild. + * @param {number} afkTimeout The time in seconds that a user must be idle to be considered AFK + * @param {string} [reason] Reason for changing the guild's AFK timeout + * @returns {Promise} + * @example + * // Edit the guild AFK channel + * guild.setAFKTimeout(60) + * .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`)) + * .catch(console.error); + */ + setAFKTimeout(afkTimeout, reason) { + return this.edit({ afkTimeout }, reason); + } + + /** + * Sets a new guild icon. + * @param {Base64Resolvable|BufferResolvable} icon The new icon of the guild + * @param {string} [reason] Reason for changing the guild's icon + * @returns {Promise} + * @example + * // Edit the guild icon + * guild.setIcon('./icon.png') + * .then(updated => console.log('Updated the guild icon')) + * .catch(console.error); + */ + async setIcon(icon, reason) { + return this.edit({ icon: await DataResolver.resolveImage(icon), reason }); + } + + /** + * Sets a new owner of the guild. + * @param {GuildMemberResolvable} owner The new owner of the guild + * @param {string} [reason] Reason for setting the new owner + * @returns {Promise} + * @example + * // Edit the guild owner + * guild.setOwner(guild.members.cache.first()) + * .then(updated => console.log(`Updated the guild owner to ${updated.owner.displayName}`)) + * .catch(console.error); + */ + setOwner(owner, reason) { + return this.edit({ owner }, reason); + } + + /** + * Sets a new guild invite splash image. + * @param {Base64Resolvable|BufferResolvable} splash The new invite splash image of the guild + * @param {string} [reason] Reason for changing the guild's invite splash image + * @returns {Promise} + * @example + * // Edit the guild splash + * guild.setSplash('./splash.png') + * .then(updated => console.log('Updated the guild splash')) + * .catch(console.error); + */ + async setSplash(splash, reason) { + return this.edit({ splash: await DataResolver.resolveImage(splash), reason }); + } + + /** + * Sets a new guild discovery splash image. + * @param {Base64Resolvable|BufferResolvable} discoverySplash The new discovery splash image of the guild + * @param {string} [reason] Reason for changing the guild's discovery splash image + * @returns {Promise} + * @example + * // Edit the guild discovery splash + * guild.setDiscoverySplash('./discoverysplash.png') + * .then(updated => console.log('Updated the guild discovery splash')) + * .catch(console.error); + */ + async setDiscoverySplash(discoverySplash, reason) { + return this.edit({ discoverySplash: await DataResolver.resolveImage(discoverySplash), reason }); + } + + /** + * Sets a new guild banner. + * @param {Base64Resolvable|BufferResolvable} banner The new banner of the guild + * @param {string} [reason] Reason for changing the guild's banner + * @returns {Promise} + * @example + * guild.setBanner('./banner.png') + * .then(updated => console.log('Updated the guild banner')) + * .catch(console.error); + */ + async setBanner(banner, reason) { + return this.edit({ banner: await DataResolver.resolveImage(banner), reason }); + } + + /** + * Edits the rules channel of the guild. + * @param {ChannelResolvable} rulesChannel The new rules channel + * @param {string} [reason] Reason for changing the guild's rules channel + * @returns {Promise} + * @example + * // Edit the guild rules channel + * guild.setRulesChannel(channel) + * .then(updated => console.log(`Updated guild rules channel to ${guild.rulesChannel.name}`)) + * .catch(console.error); + */ + setRulesChannel(rulesChannel, reason) { + return this.edit({ rulesChannel }, reason); + } + + /** + * Edits the community updates channel of the guild. + * @param {ChannelResolvable} publicUpdatesChannel The new community updates channel + * @param {string} [reason] Reason for changing the guild's community updates channel + * @returns {Promise} + * @example + * // Edit the guild community updates channel + * guild.setPublicUpdatesChannel(channel) + * .then(updated => console.log(`Updated guild community updates channel to ${guild.publicUpdatesChannel.name}`)) + * .catch(console.error); + */ + setPublicUpdatesChannel(publicUpdatesChannel, reason) { + return this.edit({ publicUpdatesChannel }, reason); + } + + /** + * Edits the preferred locale of the guild. + * @param {string} preferredLocale The new preferred locale of the guild + * @param {string} [reason] Reason for changing the guild's preferred locale + * @returns {Promise} + * @example + * // Edit the guild preferred locale + * guild.setPreferredLocale('en-US') + * .then(updated => console.log(`Updated guild preferred locale to ${guild.preferredLocale}`)) + * .catch(console.error); + */ + setPreferredLocale(preferredLocale, reason) { + return this.edit({ preferredLocale }, reason); + } + + /** + * The data needed for updating a channel's position. + * @typedef {Object} ChannelPosition + * @property {ChannelResolvable} channel Channel to update + * @property {number} position New position for the channel + */ + + /** + * Batch-updates the guild's channels' positions. + * @param {ChannelPosition[]} channelPositions Channel positions to update + * @returns {Promise} + * @example + * guild.setChannelPositions([{ channel: channelID, position: newChannelIndex }]) + * .then(guild => console.log(`Updated channel positions for ${guild}`)) + * .catch(console.error); + */ + setChannelPositions(channelPositions) { + const updatedChannels = channelPositions.map(r => ({ + id: this.client.channels.resolveID(r.channel), + position: r.position, + })); + + return this.client.api + .guilds(this.id) + .channels.patch({ data: updatedChannels }) + .then( + () => + this.client.actions.GuildChannelsPositionUpdate.handle({ + guild_id: this.id, + channels: updatedChannels, + }).guild, + ); + } + + /** + * The data needed for updating a guild role's position + * @typedef {Object} GuildRolePosition + * @property {RoleResolveable} role The ID of the role + * @property {number} position The position to update + */ + + /** + * Batch-updates the guild's role positions + * @param {GuildRolePosition[]} rolePositions Role positions to update + * @returns {Promise} + * @example + * guild.setRolePositions([{ role: roleID, position: updatedRoleIndex }]) + * .then(guild => console.log(`Role permissions updated for ${guild}`)) + * .catch(console.error); + */ + setRolePositions(rolePositions) { + // Make sure rolePositions are prepared for API + rolePositions = rolePositions.map(o => ({ + id: this.roles.resolveID(o.role), + position: o.position, + })); + + // Call the API to update role positions + return this.client.api + .guilds(this.id) + .roles.patch({ + data: rolePositions, + }) + .then( + () => + this.client.actions.GuildRolesPositionUpdate.handle({ + guild_id: this.id, + roles: rolePositions, + }).guild, + ); + } + + /** + * Edits the guild's embed. + * @param {GuildWidgetData} embed The embed for the guild + * @param {string} [reason] Reason for changing the guild's embed + * @returns {Promise} + * @deprecated + */ + setEmbed(embed, reason) { + return this.setWidget(embed, reason); + } + + /** + * Edits the guild's widget. + * @param {GuildWidgetData} widget The widget for the guild + * @param {string} [reason] Reason for changing the guild's widget + * @returns {Promise} + */ + setWidget(widget, reason) { + return this.client.api + .guilds(this.id) + .widget.patch({ + data: { + enabled: widget.enabled, + channel_id: this.channels.resolveID(widget.channel), + }, + reason, + }) + .then(() => this); + } + + /** + * Leaves the guild. + * @returns {Promise} + * @example + * // Leave a guild + * guild.leave() + * .then(g => console.log(`Left the guild ${g}`)) + * .catch(console.error); + */ + leave() { + if (this.ownerID === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED')); + return this.client.api + .users('@me') + .guilds(this.id) + .delete() + .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild); + } + + /** + * Deletes the guild. + * @returns {Promise} + * @example + * // Delete a guild + * guild.delete() + * .then(g => console.log(`Deleted the guild ${g}`)) + * .catch(console.error); + */ + delete() { + return this.client.api + .guilds(this.id) + .delete() + .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild); + } + + /** + * Whether this guild equals another guild. It compares all properties, so for most operations + * it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often + * what most users need. + * @param {Guild} guild The guild to compare with + * @returns {boolean} + */ + equals(guild) { + let equal = + guild && + guild instanceof this.constructor && + this.id === guild.id && + this.available === guild.available && + this.splash === guild.splash && + this.discoverySplash === guild.discoverySplash && + this.region === guild.region && + this.name === guild.name && + this.memberCount === guild.memberCount && + this.large === guild.large && + this.icon === guild.icon && + this.ownerID === guild.ownerID && + this.verificationLevel === guild.verificationLevel && + this.embedEnabled === guild.embedEnabled && + (this.features === guild.features || + (this.features.length === guild.features.length && + this.features.every((feat, i) => feat === guild.features[i]))); + + if (equal) { + if (this.embedChannel) { + if (!guild.embedChannel || this.embedChannel.id !== guild.embedChannel.id) equal = false; + } else if (guild.embedChannel) { + equal = false; + } + } + + return equal; + } + + /** + * When concatenated with a string, this automatically returns the guild's name instead of the Guild object. + * @returns {string} + * @example + * // Logs: Hello from My Guild! + * console.log(`Hello from ${guild}!`); + */ + toString() { + return this.name; + } + + toJSON() { + const json = super.toJSON({ + available: false, + createdTimestamp: true, + nameAcronym: true, + presences: false, + voiceStates: false, + }); + json.iconURL = this.iconURL(); + json.splashURL = this.splashURL(); + json.discoverySplashURL = this.discoverySplashURL(); + json.bannerURL = this.bannerURL(); + return json; + } + + /** + * Creates a collection of this guild's roles, sorted by their position and IDs. + * @returns {Collection} + * @private + */ + _sortedRoles() { + return Util.discordSort(this.roles.cache); + } + + /** + * Creates a collection of this guild's or a specific category's channels, sorted by their position and IDs. + * @param {GuildChannel} [channel] Category to get the channels of + * @returns {Collection} + * @private + */ + _sortedChannels(channel) { + const category = channel.type === ChannelTypes.CATEGORY; + return Util.discordSort( + this.channels.cache.filter( + c => + (['text', 'news', 'store'].includes(channel.type) + ? ['text', 'news', 'store'].includes(c.type) + : c.type === channel.type) && + (category || c.parent === channel.parent), + ), + ); + } +} + +Guild.prototype.setEmbed = deprecate(Guild.prototype.setEmbed, 'Guild#setEmbed: Use setWidget instead'); + +Guild.prototype.fetchEmbed = deprecate(Guild.prototype.fetchEmbed, 'Guild#fetchEmbed: Use fetchWidget instead'); + +Guild.prototype.fetchVanityCode = deprecate( + Guild.prototype.fetchVanityCode, + 'Guild#fetchVanityCode: Use fetchVanityData() instead', +); + +module.exports = Guild; diff --git a/node_modules/discord.js/src/structures/GuildAuditLogs.js b/node_modules/discord.js/src/structures/GuildAuditLogs.js new file mode 100644 index 0000000..823b003 --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildAuditLogs.js @@ -0,0 +1,509 @@ +'use strict'; + +const Integration = require('./Integration'); +const Webhook = require('./Webhook'); +const Collection = require('../util/Collection'); +const { PartialTypes } = require('../util/Constants'); +const Snowflake = require('../util/Snowflake'); +const Util = require('../util/Util'); + +/** + * The target type of an entry, e.g. `GUILD`. Here are the available types: + * * GUILD + * * CHANNEL + * * USER + * * ROLE + * * INVITE + * * WEBHOOK + * * EMOJI + * * MESSAGE + * * INTEGRATION + * @typedef {string} AuditLogTargetType + */ + +/** + * Key mirror of all available audit log targets. + * @name GuildAuditLogs.Targets + * @type {Object} + */ +const Targets = { + ALL: 'ALL', + GUILD: 'GUILD', + CHANNEL: 'CHANNEL', + USER: 'USER', + ROLE: 'ROLE', + INVITE: 'INVITE', + WEBHOOK: 'WEBHOOK', + EMOJI: 'EMOJI', + MESSAGE: 'MESSAGE', + INTEGRATION: 'INTEGRATION', + UNKNOWN: 'UNKNOWN', +}; + +/** + * The action of an entry. Here are the available actions: + * * ALL: null + * * GUILD_UPDATE: 1 + * * CHANNEL_CREATE: 10 + * * CHANNEL_UPDATE: 11 + * * CHANNEL_DELETE: 12 + * * CHANNEL_OVERWRITE_CREATE: 13 + * * CHANNEL_OVERWRITE_UPDATE: 14 + * * CHANNEL_OVERWRITE_DELETE: 15 + * * MEMBER_KICK: 20 + * * MEMBER_PRUNE: 21 + * * MEMBER_BAN_ADD: 22 + * * MEMBER_BAN_REMOVE: 23 + * * MEMBER_UPDATE: 24 + * * MEMBER_ROLE_UPDATE: 25 + * * MEMBER_MOVE: 26 + * * MEMBER_DISCONNECT: 27 + * * BOT_ADD: 28, + * * ROLE_CREATE: 30 + * * ROLE_UPDATE: 31 + * * ROLE_DELETE: 32 + * * INVITE_CREATE: 40 + * * INVITE_UPDATE: 41 + * * INVITE_DELETE: 42 + * * WEBHOOK_CREATE: 50 + * * WEBHOOK_UPDATE: 51 + * * WEBHOOK_DELETE: 52 + * * EMOJI_CREATE: 60 + * * EMOJI_UPDATE: 61 + * * EMOJI_DELETE: 62 + * * MESSAGE_DELETE: 72 + * * MESSAGE_BULK_DELETE: 73 + * * MESSAGE_PIN: 74 + * * MESSAGE_UNPIN: 75 + * * INTEGRATION_CREATE: 80 + * * INTEGRATION_UPDATE: 81 + * * INTEGRATION_DELETE: 82 + * @typedef {?number|string} AuditLogAction + */ + +/** + * All available actions keyed under their names to their numeric values. + * @name GuildAuditLogs.Actions + * @type {Object} + */ +const Actions = { + ALL: null, + GUILD_UPDATE: 1, + CHANNEL_CREATE: 10, + CHANNEL_UPDATE: 11, + CHANNEL_DELETE: 12, + CHANNEL_OVERWRITE_CREATE: 13, + CHANNEL_OVERWRITE_UPDATE: 14, + CHANNEL_OVERWRITE_DELETE: 15, + MEMBER_KICK: 20, + MEMBER_PRUNE: 21, + MEMBER_BAN_ADD: 22, + MEMBER_BAN_REMOVE: 23, + MEMBER_UPDATE: 24, + MEMBER_ROLE_UPDATE: 25, + MEMBER_MOVE: 26, + MEMBER_DISCONNECT: 27, + BOT_ADD: 28, + ROLE_CREATE: 30, + ROLE_UPDATE: 31, + ROLE_DELETE: 32, + INVITE_CREATE: 40, + INVITE_UPDATE: 41, + INVITE_DELETE: 42, + WEBHOOK_CREATE: 50, + WEBHOOK_UPDATE: 51, + WEBHOOK_DELETE: 52, + EMOJI_CREATE: 60, + EMOJI_UPDATE: 61, + EMOJI_DELETE: 62, + MESSAGE_DELETE: 72, + MESSAGE_BULK_DELETE: 73, + MESSAGE_PIN: 74, + MESSAGE_UNPIN: 75, + INTEGRATION_CREATE: 80, + INTEGRATION_UPDATE: 81, + INTEGRATION_DELETE: 82, +}; + +/** + * Audit logs entries are held in this class. + */ +class GuildAuditLogs { + constructor(guild, data) { + if (data.users) for (const user of data.users) guild.client.users.add(user); + /** + * Cached webhooks + * @type {Collection} + * @private + */ + this.webhooks = new Collection(); + if (data.webhooks) { + for (const hook of data.webhooks) { + this.webhooks.set(hook.id, new Webhook(guild.client, hook)); + } + } + + /** + * Cached integrations + * @type {Collection} + * @private + */ + this.integrations = new Collection(); + if (data.integrations) { + for (const integration of data.integrations) { + this.integrations.set(integration.id, new Integration(guild.client, integration, guild)); + } + } + + /** + * The entries for this guild's audit logs + * @type {Collection} + */ + this.entries = new Collection(); + for (const item of data.audit_log_entries) { + const entry = new GuildAuditLogsEntry(this, guild, item); + this.entries.set(entry.id, entry); + } + } + + /** + * Handles possible promises for entry targets. + * @returns {Promise} + */ + static build(...args) { + const logs = new GuildAuditLogs(...args); + return Promise.all(logs.entries.map(e => e.target)).then(() => logs); + } + + /** + * The target of an entry. It can be one of: + * * A guild + * * A user + * * A role + * * An emoji + * * An invite + * * A webhook + * * An integration + * * An object with an id key if target was deleted + * * An object where the keys represent either the new value or the old value + * @typedef {?Object|Guild|User|Role|GuildEmoji|Invite|Webhook|Integration} AuditLogEntryTarget + */ + + /** + * Finds the target type from the entry action. + * @param {AuditLogAction} target The action target + * @returns {AuditLogTargetType} + */ + static targetType(target) { + if (target < 10) return Targets.GUILD; + if (target < 20) return Targets.CHANNEL; + if (target < 30) return Targets.USER; + if (target < 40) return Targets.ROLE; + if (target < 50) return Targets.INVITE; + if (target < 60) return Targets.WEBHOOK; + if (target < 70) return Targets.EMOJI; + if (target < 80) return Targets.MESSAGE; + if (target < 90) return Targets.INTEGRATION; + return Targets.UNKNOWN; + } + + /** + * The action type of an entry, e.g. `CREATE`. Here are the available types: + * * CREATE + * * DELETE + * * UPDATE + * * ALL + * @typedef {string} AuditLogActionType + */ + + /** + * Finds the action type from the entry action. + * @param {AuditLogAction} action The action target + * @returns {AuditLogActionType} + */ + static actionType(action) { + if ( + [ + Actions.CHANNEL_CREATE, + Actions.CHANNEL_OVERWRITE_CREATE, + Actions.MEMBER_BAN_REMOVE, + Actions.BOT_ADD, + Actions.ROLE_CREATE, + Actions.INVITE_CREATE, + Actions.WEBHOOK_CREATE, + Actions.EMOJI_CREATE, + Actions.MESSAGE_PIN, + Actions.INTEGRATION_CREATE, + ].includes(action) + ) { + return 'CREATE'; + } + + if ( + [ + Actions.CHANNEL_DELETE, + Actions.CHANNEL_OVERWRITE_DELETE, + Actions.MEMBER_KICK, + Actions.MEMBER_PRUNE, + Actions.MEMBER_BAN_ADD, + Actions.MEMBER_DISCONNECT, + Actions.ROLE_DELETE, + Actions.INVITE_DELETE, + Actions.WEBHOOK_DELETE, + Actions.EMOJI_DELETE, + Actions.MESSAGE_DELETE, + Actions.MESSAGE_BULK_DELETE, + Actions.MESSAGE_UNPIN, + Actions.INTEGRATION_DELETE, + ].includes(action) + ) { + return 'DELETE'; + } + + if ( + [ + Actions.GUILD_UPDATE, + Actions.CHANNEL_UPDATE, + Actions.CHANNEL_OVERWRITE_UPDATE, + Actions.MEMBER_UPDATE, + Actions.MEMBER_ROLE_UPDATE, + Actions.MEMBER_MOVE, + Actions.ROLE_UPDATE, + Actions.INVITE_UPDATE, + Actions.WEBHOOK_UPDATE, + Actions.EMOJI_UPDATE, + Actions.INTEGRATION_UPDATE, + ].includes(action) + ) { + return 'UPDATE'; + } + + return 'ALL'; + } + + toJSON() { + return Util.flatten(this); + } +} + +/** + * Audit logs entry. + */ +class GuildAuditLogsEntry { + constructor(logs, guild, data) { + const targetType = GuildAuditLogs.targetType(data.action_type); + /** + * The target type of this entry + * @type {AuditLogTargetType} + */ + this.targetType = targetType; + + /** + * The action type of this entry + * @type {AuditLogActionType} + */ + this.actionType = GuildAuditLogs.actionType(data.action_type); + + /** + * Specific action type of this entry in its string presentation + * @type {AuditLogAction} + */ + this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type); + + /** + * The reason of this entry + * @type {?string} + */ + this.reason = data.reason || null; + + /** + * The user that executed this entry + * @type {User} + */ + this.executor = guild.client.options.partials.includes(PartialTypes.USER) + ? guild.client.users.add({ id: data.user_id }) + : guild.client.users.cache.get(data.user_id); + + /** + * An entry in the audit log representing a specific change. + * @typedef {object} AuditLogChange + * @property {string} key The property that was changed, e.g. `nick` for nickname changes + * @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname + * @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname + */ + + /** + * Specific property changes + * @type {AuditLogChange[]} + */ + this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null; + + /** + * The ID of this entry + * @type {Snowflake} + */ + this.id = data.id; + + /** + * Any extra data from the entry + * @type {?Object|Role|GuildMember} + */ + this.extra = null; + switch (data.action_type) { + case Actions.MEMBER_PRUNE: + this.extra = { + removed: Number(data.options.members_removed), + days: Number(data.options.delete_member_days), + }; + break; + + case Actions.MEMBER_MOVE: + case Actions.MESSAGE_DELETE: + case Actions.MESSAGE_BULK_DELETE: + this.extra = { + channel: guild.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id }, + count: Number(data.options.count), + }; + break; + + case Actions.MESSAGE_PIN: + case Actions.MESSAGE_UNPIN: + this.extra = { + channel: guild.client.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id }, + messageID: data.options.message_id, + }; + break; + + case Actions.MEMBER_DISCONNECT: + this.extra = { + count: Number(data.options.count), + }; + break; + + case Actions.CHANNEL_OVERWRITE_CREATE: + case Actions.CHANNEL_OVERWRITE_UPDATE: + case Actions.CHANNEL_OVERWRITE_DELETE: + switch (data.options.type) { + case 'member': + this.extra = guild.members.cache.get(data.options.id) || { id: data.options.id, type: 'member' }; + break; + + case 'role': + this.extra = guild.roles.cache.get(data.options.id) || { + id: data.options.id, + name: data.options.role_name, + type: 'role', + }; + break; + + default: + break; + } + break; + + default: + break; + } + + /** + * The target of this entry + * @type {?AuditLogEntryTarget} + */ + this.target = null; + if (targetType === Targets.UNKNOWN) { + this.target = this.changes.reduce((o, c) => { + o[c.key] = c.new || c.old; + return o; + }, {}); + this.target.id = data.target_id; + // MEMBER_DISCONNECT and similar types do not provide a target_id. + } else if (targetType === Targets.USER && data.target_id) { + this.target = guild.client.options.partials.includes(PartialTypes.USER) + ? guild.client.users.add({ id: data.target_id }) + : guild.client.users.cache.get(data.target_id); + } else if (targetType === Targets.GUILD) { + this.target = guild.client.guilds.cache.get(data.target_id); + } else if (targetType === Targets.WEBHOOK) { + this.target = + logs.webhooks.get(data.target_id) || + new Webhook( + guild.client, + this.changes.reduce( + (o, c) => { + o[c.key] = c.new || c.old; + return o; + }, + { + id: data.target_id, + guild_id: guild.id, + }, + ), + ); + } else if (targetType === Targets.INVITE) { + this.target = guild.members.fetch(guild.client.user.id).then(me => { + if (me.permissions.has('MANAGE_GUILD')) { + const change = this.changes.find(c => c.key === 'code'); + return guild.fetchInvites().then(invites => { + this.target = invites.find(i => i.code === (change.new || change.old)); + }); + } else { + this.target = this.changes.reduce((o, c) => { + o[c.key] = c.new || c.old; + return o; + }, {}); + return this.target; + } + }); + } else if (targetType === Targets.MESSAGE) { + // Discord sends a channel id for the MESSAGE_BULK_DELETE action type. + this.target = + data.action_type === Actions.MESSAGE_BULK_DELETE + ? guild.channels.cache.get(data.target_id) || { id: data.target_id } + : guild.client.users.cache.get(data.target_id); + } else if (targetType === Targets.INTEGRATION) { + this.target = + logs.integrations.get(data.target_id) || + new Integration( + guild.client, + this.changes.reduce( + (o, c) => { + o[c.key] = c.new || c.old; + return o; + }, + { id: data.target_id }, + ), + guild, + ); + } else if (data.target_id) { + this.target = guild[`${targetType.toLowerCase()}s`].cache.get(data.target_id) || { id: data.target_id }; + } + } + + /** + * The timestamp this entry was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time this entry was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + toJSON() { + return Util.flatten(this, { createdTimestamp: true }); + } +} + +GuildAuditLogs.Actions = Actions; +GuildAuditLogs.Targets = Targets; +GuildAuditLogs.Entry = GuildAuditLogsEntry; + +module.exports = GuildAuditLogs; diff --git a/node_modules/discord.js/src/structures/GuildChannel.js b/node_modules/discord.js/src/structures/GuildChannel.js new file mode 100644 index 0000000..f397c3c --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildChannel.js @@ -0,0 +1,624 @@ +'use strict'; + +const Channel = require('./Channel'); +const Invite = require('./Invite'); +const PermissionOverwrites = require('./PermissionOverwrites'); +const Role = require('./Role'); +const { Error, TypeError } = require('../errors'); +const Collection = require('../util/Collection'); +const Permissions = require('../util/Permissions'); +const Util = require('../util/Util'); + +/** + * Represents a guild channel from any of the following: + * - {@link TextChannel} + * - {@link VoiceChannel} + * - {@link CategoryChannel} + * - {@link NewsChannel} + * - {@link StoreChannel} + * @extends {Channel} + * @abstract + */ +class GuildChannel extends Channel { + /** + * @param {Guild} guild The guild the guild channel is part of + * @param {Object} data The data for the guild channel + */ + constructor(guild, data) { + super(guild.client, data); + + /** + * The guild the channel is in + * @type {Guild} + */ + this.guild = guild; + } + + _patch(data) { + super._patch(data); + + /** + * The name of the guild channel + * @type {string} + */ + this.name = data.name; + + /** + * The raw position of the channel from discord + * @type {number} + */ + this.rawPosition = data.position; + + /** + * The ID of the category parent of this channel + * @type {?Snowflake} + */ + this.parentID = data.parent_id || null; + + /** + * A map of permission overwrites in this channel for roles and users + * @type {Collection} + */ + this.permissionOverwrites = new Collection(); + if (data.permission_overwrites) { + for (const overwrite of data.permission_overwrites) { + this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite)); + } + } + } + + /** + * The category parent of this channel + * @type {?CategoryChannel} + * @readonly + */ + get parent() { + return this.guild.channels.cache.get(this.parentID) || null; + } + + /** + * If the permissionOverwrites match the parent channel, null if no parent + * @type {?boolean} + * @readonly + */ + get permissionsLocked() { + if (!this.parent) return null; + if (this.permissionOverwrites.size !== this.parent.permissionOverwrites.size) return false; + return this.permissionOverwrites.every((value, key) => { + const testVal = this.parent.permissionOverwrites.get(key); + return ( + testVal !== undefined && + testVal.deny.bitfield === value.deny.bitfield && + testVal.allow.bitfield === value.allow.bitfield + ); + }); + } + + /** + * The position of the channel + * @type {number} + * @readonly + */ + get position() { + const sorted = this.guild._sortedChannels(this); + return sorted.array().indexOf(sorted.get(this.id)); + } + + /** + * Gets the overall set of permissions for a member or role in this channel, taking into account channel overwrites. + * @param {GuildMemberResolvable|RoleResolvable} memberOrRole The member or role to obtain the overall permissions for + * @returns {?Readonly} + */ + permissionsFor(memberOrRole) { + const member = this.guild.members.resolve(memberOrRole); + if (member) return this.memberPermissions(member); + const role = this.guild.roles.resolve(memberOrRole); + if (role) return this.rolePermissions(role); + return null; + } + + overwritesFor(member, verified = false, roles = null) { + if (!verified) member = this.guild.members.resolve(member); + if (!member) return []; + + roles = roles || member.roles.cache; + const roleOverwrites = []; + let memberOverwrites; + let everyoneOverwrites; + + for (const overwrite of this.permissionOverwrites.values()) { + if (overwrite.id === this.guild.id) { + everyoneOverwrites = overwrite; + } else if (roles.has(overwrite.id)) { + roleOverwrites.push(overwrite); + } else if (overwrite.id === member.id) { + memberOverwrites = overwrite; + } + } + + return { + everyone: everyoneOverwrites, + roles: roleOverwrites, + member: memberOverwrites, + }; + } + + /** + * Gets the overall set of permissions for a member in this channel, taking into account channel overwrites. + * @param {GuildMember} member The member to obtain the overall permissions for + * @returns {Readonly} + * @private + */ + memberPermissions(member) { + if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze(); + + const roles = member.roles.cache; + const permissions = new Permissions(roles.map(role => role.permissions)); + + if (permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze(); + + const overwrites = this.overwritesFor(member, true, roles); + + return permissions + .remove(overwrites.everyone ? overwrites.everyone.deny : 0) + .add(overwrites.everyone ? overwrites.everyone.allow : 0) + .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : 0) + .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : 0) + .remove(overwrites.member ? overwrites.member.deny : 0) + .add(overwrites.member ? overwrites.member.allow : 0) + .freeze(); + } + + /** + * Gets the overall set of permissions for a role in this channel, taking into account channel overwrites. + * @param {Role} role The role to obtain the overall permissions for + * @returns {Readonly} + * @private + */ + rolePermissions(role) { + if (role.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze(); + + const everyoneOverwrites = this.permissionOverwrites.get(this.guild.id); + const roleOverwrites = this.permissionOverwrites.get(role.id); + + return role.permissions + .remove(everyoneOverwrites ? everyoneOverwrites.deny : 0) + .add(everyoneOverwrites ? everyoneOverwrites.allow : 0) + .remove(roleOverwrites ? roleOverwrites.deny : 0) + .add(roleOverwrites ? roleOverwrites.allow : 0) + .freeze(); + } + + /** + * Replaces the permission overwrites in this channel. + * @param {OverwriteResolvable[]|Collection} overwrites + * Permission overwrites the channel gets updated with + * @param {string} [reason] Reason for updating the channel overwrites + * @returns {Promise} + * @example + * channel.overwritePermissions([ + * { + * id: message.author.id, + * deny: ['VIEW_CHANNEL'], + * }, + * ], 'Needed to change permissions'); + */ + overwritePermissions(overwrites, reason) { + if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { + return Promise.reject( + new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true), + ); + } + return this.edit({ permissionOverwrites: overwrites, reason }).then(() => this); + } + + /** + * Updates Overwrites for a user or role in this channel. (creates if non-existent) + * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update + * @param {PermissionOverwriteOptions} options The options for the update + * @param {string} [reason] Reason for creating/editing this overwrite + * @returns {Promise} + * @example + * // Update or Create permission overwrites for a message author + * message.channel.updateOverwrite(message.author, { + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) + * .catch(console.error); + */ + updateOverwrite(userOrRole, options, reason) { + userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); + if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); + + const existing = this.permissionOverwrites.get(userOrRole.id); + if (existing) return existing.update(options, reason).then(() => this); + return this.createOverwrite(userOrRole, options, reason); + } + + /** + * Overwrites the permissions for a user or role in this channel. (replaces if existent) + * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update + * @param {PermissionOverwriteOptions} options The options for the update + * @param {string} [reason] Reason for creating/editing this overwrite + * @returns {Promise} + * @example + * // Create or Replace permissions overwrites for a message author + * message.channel.createOverwrite(message.author, { + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) + * .catch(console.error); + */ + createOverwrite(userOrRole, options, reason) { + userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); + if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); + + const type = userOrRole instanceof Role ? 'role' : 'member'; + const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); + + return this.client.api + .channels(this.id) + .permissions[userOrRole.id].put({ + data: { id: userOrRole.id, type, allow: allow.bitfield, deny: deny.bitfield }, + reason, + }) + .then(() => this); + } + + /** + * Locks in the permission overwrites from the parent channel. + * @returns {Promise} + */ + lockPermissions() { + if (!this.parent) return Promise.reject(new Error('GUILD_CHANNEL_ORPHAN')); + const permissionOverwrites = this.parent.permissionOverwrites.map(overwrite => overwrite.toJSON()); + return this.edit({ permissionOverwrites }); + } + + /** + * A collection of members that can see this channel, mapped by their ID + * @type {Collection} + * @readonly + */ + get members() { + const members = new Collection(); + for (const member of this.guild.members.cache.values()) { + if (this.permissionsFor(member).has('VIEW_CHANNEL', false)) { + members.set(member.id, member); + } + } + return members; + } + + /** + * The data for a guild channel. + * @typedef {Object} ChannelData + * @property {string} [name] The name of the channel + * @property {number} [position] The position of the channel + * @property {string} [topic] The topic of the text channel + * @property {boolean} [nsfw] Whether the channel is NSFW + * @property {number} [bitrate] The bitrate of the voice channel + * @property {number} [userLimit] The user limit of the voice channel + * @property {?Snowflake} [parentID] The parent ID of the channel + * @property {boolean} [lockPermissions] + * Lock the permissions of the channel to what the parent's permissions are + * @property {OverwriteResolvable[]|Collection} [permissionOverwrites] + * Permission overwrites for the channel + * @property {number} [rateLimitPerUser] The ratelimit per user for the channel in seconds + */ + + /** + * Edits the channel. + * @param {ChannelData} data The new data for the channel + * @param {string} [reason] Reason for editing this channel + * @returns {Promise} + * @example + * // Edit a channel + * channel.edit({ name: 'new-channel' }) + * .then(console.log) + * .catch(console.error); + */ + async edit(data, reason) { + if (typeof data.position !== 'undefined') { + await Util.setPosition( + this, + data.position, + false, + this.guild._sortedChannels(this), + this.client.api.guilds(this.guild.id).channels, + reason, + ).then(updatedChannels => { + this.client.actions.GuildChannelsPositionUpdate.handle({ + guild_id: this.guild.id, + channels: updatedChannels, + }); + }); + } + + let permission_overwrites; + + if (data.permissionOverwrites) { + permission_overwrites = data.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + } + + if (data.lockPermissions) { + if (data.parentID) { + const newParent = this.guild.channels.resolve(data.parentID); + if (newParent && newParent.type === 'category') { + permission_overwrites = newParent.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + } + } else if (this.parent) { + permission_overwrites = this.parent.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + } + } + + const newData = await this.client.api.channels(this.id).patch({ + data: { + name: (data.name || this.name).trim(), + topic: data.topic, + nsfw: data.nsfw, + bitrate: data.bitrate || this.bitrate, + user_limit: typeof data.userLimit !== 'undefined' ? data.userLimit : this.userLimit, + parent_id: data.parentID, + lock_permissions: data.lockPermissions, + rate_limit_per_user: data.rateLimitPerUser, + permission_overwrites, + }, + reason, + }); + + const clone = this._clone(); + clone._patch(newData); + return clone; + } + + /** + * Sets a new name for the guild channel. + * @param {string} name The new name for the guild channel + * @param {string} [reason] Reason for changing the guild channel's name + * @returns {Promise} + * @example + * // Set a new channel name + * channel.setName('not_general') + * .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`)) + * .catch(console.error); + */ + setName(name, reason) { + return this.edit({ name }, reason); + } + + /** + * Sets the category parent of this channel. + * @param {?CategoryChannel|Snowflake} channel Parent channel + * @param {Object} [options={}] Options to pass + * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are + * @param {string} [options.reason] Reason for modifying the parent of this channel + * @returns {Promise} + * @example + * // Add a parent to a channel + * message.channel.setParent('355908108431917066', { lockPermissions: false }) + * .then(channel => console.log(`New parent of ${message.channel.name}: ${channel.name}`)) + * .catch(console.error); + */ + setParent(channel, { lockPermissions = true, reason } = {}) { + return this.edit( + { + // eslint-disable-next-line no-prototype-builtins + parentID: channel !== null ? (channel.hasOwnProperty('id') ? channel.id : channel) : null, + lockPermissions, + }, + reason, + ); + } + + /** + * Sets a new topic for the guild channel. + * @param {?string} topic The new topic for the guild channel + * @param {string} [reason] Reason for changing the guild channel's topic + * @returns {Promise} + * @example + * // Set a new channel topic + * channel.setTopic('needs more rate limiting') + * .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`)) + * .catch(console.error); + */ + setTopic(topic, reason) { + return this.edit({ topic }, reason); + } + + /** + * Sets a new position for the guild channel. + * @param {number} position The new position for the guild channel + * @param {Object} [options] Options for setting position + * @param {boolean} [options.relative=false] Change the position relative to its current value + * @param {string} [options.reason] Reason for changing the position + * @returns {Promise} + * @example + * // Set a new channel position + * channel.setPosition(2) + * .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`)) + * .catch(console.error); + */ + setPosition(position, { relative, reason } = {}) { + return Util.setPosition( + this, + position, + relative, + this.guild._sortedChannels(this), + this.client.api.guilds(this.guild.id).channels, + reason, + ).then(updatedChannels => { + this.client.actions.GuildChannelsPositionUpdate.handle({ + guild_id: this.guild.id, + channels: updatedChannels, + }); + return this; + }); + } + + /** + * Creates an invite to this guild channel. + * @param {Object} [options={}] Options for the invite + * @param {boolean} [options.temporary=false] Whether members that joined via the invite should be automatically + * kicked after 24 hours if they have not yet received a role + * @param {number} [options.maxAge=86400] How long the invite should last (in seconds, 0 for forever) + * @param {number} [options.maxUses=0] Maximum number of uses + * @param {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings + * @param {string} [options.reason] Reason for creating this + * @returns {Promise} + * @example + * // Create an invite to a channel + * channel.createInvite() + * .then(invite => console.log(`Created an invite with a code of ${invite.code}`)) + * .catch(console.error); + */ + createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) { + return this.client.api + .channels(this.id) + .invites.post({ + data: { + temporary, + max_age: maxAge, + max_uses: maxUses, + unique, + }, + reason, + }) + .then(invite => new Invite(this.client, invite)); + } + + /** + * Fetches a collection of invites to this guild channel. + * Resolves with a collection mapping invites by their codes. + * @returns {Promise>} + */ + async fetchInvites() { + const inviteItems = await this.client.api.channels(this.id).invites.get(); + const invites = new Collection(); + for (const inviteItem of inviteItems) { + const invite = new Invite(this.client, inviteItem); + invites.set(invite.code, invite); + } + return invites; + } + + /* eslint-disable max-len */ + /** + * Clones this channel. + * @param {Object} [options] The options + * @param {string} [options.name=this.name] Name of the new channel + * @param {OverwriteResolvable[]|Collection} [options.permissionOverwrites=this.permissionOverwrites] + * Permission overwrites of the new channel + * @param {string} [options.type=this.type] Type of the new channel + * @param {string} [options.topic=this.topic] Topic of the new channel (only text) + * @param {boolean} [options.nsfw=this.nsfw] Whether the new channel is nsfw (only text) + * @param {number} [options.bitrate=this.bitrate] Bitrate of the new channel in bits (only voice) + * @param {number} [options.userLimit=this.userLimit] Maximum amount of users allowed in the new channel (only voice) + * @param {number} [options.rateLimitPerUser=this.rateLimitPerUser] Ratelimit per user for the new channel (only text) + * @param {ChannelResolvable} [options.parent=this.parent] Parent of the new channel + * @param {string} [options.reason] Reason for cloning this channel + * @returns {Promise} + */ + clone(options = {}) { + Util.mergeDefault( + { + name: this.name, + permissionOverwrites: this.permissionOverwrites, + topic: this.topic, + type: this.type, + nsfw: this.nsfw, + parent: this.parent, + bitrate: this.bitrate, + userLimit: this.userLimit, + rateLimitPerUser: this.rateLimitPerUser, + reason: null, + }, + options, + ); + return this.guild.channels.create(options.name, options); + } + /* eslint-enable max-len */ + + /** + * Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel. + * In most cases, a simple `channel.id === channel2.id` will do, and is much faster too. + * @param {GuildChannel} channel Channel to compare with + * @returns {boolean} + */ + equals(channel) { + let equal = + channel && + this.id === channel.id && + this.type === channel.type && + this.topic === channel.topic && + this.position === channel.position && + this.name === channel.name; + + if (equal) { + if (this.permissionOverwrites && channel.permissionOverwrites) { + equal = this.permissionOverwrites.equals(channel.permissionOverwrites); + } else { + equal = !this.permissionOverwrites && !channel.permissionOverwrites; + } + } + + return equal; + } + + /** + * Whether the channel is deletable by the client user + * @type {boolean} + * @readonly + */ + get deletable() { + return this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false); + } + + /** + * Whether the channel is manageable by the client user + * @type {boolean} + * @readonly + */ + get manageable() { + if (this.client.user.id === this.guild.ownerID) return true; + if (this.type === 'voice') { + if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) { + return false; + } + } else if (!this.viewable) { + return false; + } + return this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false); + } + + /** + * Whether the channel is viewable by the client user + * @type {boolean} + * @readonly + */ + get viewable() { + if (this.client.user.id === this.guild.ownerID) return true; + const permissions = this.permissionsFor(this.client.user); + if (!permissions) return false; + return permissions.has(Permissions.FLAGS.VIEW_CHANNEL, false); + } + + /** + * Deletes this channel. + * @param {string} [reason] Reason for deleting this channel + * @returns {Promise} + * @example + * // Delete the channel + * channel.delete('making room for new channels') + * .then(console.log) + * .catch(console.error); + */ + delete(reason) { + return this.client.api + .channels(this.id) + .delete({ reason }) + .then(() => this); + } +} + +module.exports = GuildChannel; diff --git a/node_modules/discord.js/src/structures/GuildEmoji.js b/node_modules/discord.js/src/structures/GuildEmoji.js new file mode 100644 index 0000000..a4ab2a5 --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildEmoji.js @@ -0,0 +1,168 @@ +'use strict'; + +const BaseGuildEmoji = require('./BaseGuildEmoji'); +const { Error } = require('../errors'); +const GuildEmojiRoleManager = require('../managers/GuildEmojiRoleManager'); +const Permissions = require('../util/Permissions'); + +/** + * Represents a custom emoji. + * @extends {BaseGuildEmoji} + */ +class GuildEmoji extends BaseGuildEmoji { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the guild emoji + * @param {Guild} guild The guild the guild emoji is part of + */ + constructor(client, data, guild) { + super(client, data, guild); + + /** + * The user who created this emoji + * @type {?User} + */ + this.author = null; + } + + /** + * The guild this emoji is part of + * @type {Guild} + * @name GuildEmoji#guild + */ + + _clone() { + const clone = super._clone(); + clone._roles = this._roles.slice(); + return clone; + } + + _patch(data) { + super._patch(data); + if (typeof data.user !== 'undefined') this.author = this.client.users.add(data.user); + } + + /** + * Whether the emoji is deletable by the client user + * @type {boolean} + * @readonly + */ + get deletable() { + if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); + return !this.managed && this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS); + } + + /** + * A manager for roles this emoji is active for. + * @type {GuildEmojiRoleManager} + * @readonly + */ + get roles() { + return new GuildEmojiRoleManager(this); + } + + /** + * Fetches the author for this emoji + * @returns {Promise} + */ + async fetchAuthor() { + if (this.managed) { + throw new Error('EMOJI_MANAGED'); + } else { + if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); + if (!this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS)) { + throw new Error('MISSING_MANAGE_EMOJIS_PERMISSION', this.guild); + } + } + const data = await this.client.api.guilds(this.guild.id).emojis(this.id).get(); + this._patch(data); + return this.author; + } + + /** + * Data for editing an emoji. + * @typedef {Object} GuildEmojiEditData + * @property {string} [name] The name of the emoji + * @property {Collection|RoleResolvable[]} [roles] Roles to restrict emoji to + */ + + /** + * Edits the emoji. + * @param {GuildEmojiEditData} data The new data for the emoji + * @param {string} [reason] Reason for editing this emoji + * @returns {Promise} + * @example + * // Edit an emoji + * emoji.edit({ name: 'newemoji' }) + * .then(e => console.log(`Edited emoji ${e}`)) + * .catch(console.error); + */ + edit(data, reason) { + const roles = data.roles ? data.roles.map(r => r.id || r) : undefined; + return this.client.api + .guilds(this.guild.id) + .emojis(this.id) + .patch({ + data: { + name: data.name, + roles, + }, + reason, + }) + .then(newData => { + const clone = this._clone(); + clone._patch(newData); + return clone; + }); + } + + /** + * Sets the name of the emoji. + * @param {string} name The new name for the emoji + * @param {string} [reason] Reason for changing the emoji's name + * @returns {Promise} + */ + setName(name, reason) { + return this.edit({ name }, reason); + } + + /** + * Deletes the emoji. + * @param {string} [reason] Reason for deleting the emoji + * @returns {Promise} + */ + delete(reason) { + return this.client.api + .guilds(this.guild.id) + .emojis(this.id) + .delete({ reason }) + .then(() => this); + } + + /** + * Whether this emoji is the same as another one. + * @param {GuildEmoji|Object} other The emoji to compare it to + * @returns {boolean} Whether the emoji is equal to the given emoji or not + */ + equals(other) { + if (other instanceof GuildEmoji) { + return ( + other.id === this.id && + other.name === this.name && + other.managed === this.managed && + other.requiresColons === this.requiresColons && + other.roles.cache.size === this.roles.cache.size && + other.roles.cache.every(role => this.roles.cache.has(role.id)) + ); + } else { + return ( + other.id === this.id && + other.name === this.name && + other.roles.length === this.roles.cache.size && + other.roles.every(role => this.roles.cache.has(role)) + ); + } + } +} + +module.exports = GuildEmoji; diff --git a/node_modules/discord.js/src/structures/GuildMember.js b/node_modules/discord.js/src/structures/GuildMember.js new file mode 100644 index 0000000..1bd0dfd --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildMember.js @@ -0,0 +1,414 @@ +'use strict'; + +const Base = require('./Base'); +const Role = require('./Role'); +const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const { Error } = require('../errors'); +const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager'); +const Permissions = require('../util/Permissions'); +let Structures; + +/** + * Represents a member of a guild on Discord. + * @implements {TextBasedChannel} + * @extends {Base} + */ +class GuildMember extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the guild member + * @param {Guild} guild The guild the member is part of + */ + constructor(client, data, guild) { + super(client); + + /** + * The guild that this member is part of + * @type {Guild} + */ + this.guild = guild; + + /** + * The timestamp the member joined the guild at + * @type {?number} + */ + this.joinedTimestamp = null; + + /** + * The ID of the last message sent by the member in their guild, if one was sent + * @type {?Snowflake} + */ + this.lastMessageID = null; + + /** + * The ID of the channel for the last message sent by the member in their guild, if one was sent + * @type {?Snowflake} + */ + this.lastMessageChannelID = null; + + /** + * The timestamp of when the member used their Nitro boost on the guild, if it was used + * @type {?number} + */ + this.premiumSinceTimestamp = null; + + /** + * Whether the member has been removed from the guild + * @type {boolean} + */ + this.deleted = false; + + /** + * The nickname of this member, if they have one + * @type {?string} + */ + this.nickname = null; + + this._roles = []; + if (data) this._patch(data); + } + + _patch(data) { + if ('user' in data) { + /** + * The user that this guild member instance represents + * @type {User} + */ + this.user = this.client.users.add(data.user, true); + } + + if ('nick' in data) this.nickname = data.nick; + if ('joined_at' in data) this.joinedTimestamp = new Date(data.joined_at).getTime(); + if ('premium_since' in data) this.premiumSinceTimestamp = new Date(data.premium_since).getTime(); + if ('roles' in data) this._roles = data.roles; + } + + _clone() { + const clone = super._clone(); + clone._roles = this._roles.slice(); + return clone; + } + + /** + * Whether this GuildMember is a partial + * @type {boolean} + * @readonly + */ + get partial() { + return !this.joinedTimestamp; + } + + /** + * A manager for the roles belonging to this member + * @type {GuildMemberRoleManager} + * @readonly + */ + get roles() { + return new GuildMemberRoleManager(this); + } + + /** + * The Message object of the last message sent by the member in their guild, if one was sent + * @type {?Message} + * @readonly + */ + get lastMessage() { + const channel = this.guild.channels.cache.get(this.lastMessageChannelID); + return (channel && channel.messages.cache.get(this.lastMessageID)) || null; + } + + /** + * The voice state of this member + * @type {VoiceState} + * @readonly + */ + get voice() { + if (!Structures) Structures = require('../util/Structures'); + const VoiceState = Structures.get('VoiceState'); + return this.guild.voiceStates.cache.get(this.id) || new VoiceState(this.guild, { user_id: this.id }); + } + + /** + * The time this member joined the guild + * @type {?Date} + * @readonly + */ + get joinedAt() { + return this.joinedTimestamp ? new Date(this.joinedTimestamp) : null; + } + + /** + * The time of when the member used their Nitro boost on the guild, if it was used + * @type {?Date} + * @readonly + */ + get premiumSince() { + return this.premiumSinceTimestamp ? new Date(this.premiumSinceTimestamp) : null; + } + + /** + * The presence of this guild member + * @type {Presence} + * @readonly + */ + get presence() { + if (!Structures) Structures = require('../util/Structures'); + const Presence = Structures.get('Presence'); + return ( + this.guild.presences.cache.get(this.id) || + new Presence(this.client, { + user: { + id: this.id, + }, + guild: this.guild, + }) + ); + } + + /** + * The displayed color of this member in base 10 + * @type {number} + * @readonly + */ + get displayColor() { + const role = this.roles.color; + return (role && role.color) || 0; + } + + /** + * The displayed color of this member in hexadecimal + * @type {string} + * @readonly + */ + get displayHexColor() { + const role = this.roles.color; + return (role && role.hexColor) || '#000000'; + } + + /** + * The ID of this member + * @type {Snowflake} + * @readonly + */ + get id() { + return this.user.id; + } + + /** + * The nickname of this member, or their username if they don't have one + * @type {?string} + * @readonly + */ + get displayName() { + return this.nickname || this.user.username; + } + + /** + * The overall set of permissions for this member, taking only roles into account + * @type {Readonly} + * @readonly + */ + get permissions() { + if (this.user.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze(); + return new Permissions(this.roles.cache.map(role => role.permissions)).freeze(); + } + + /** + * Whether the client user is above this user in the hierarchy, according to role position and guild ownership. + * This is a prerequisite for many moderative actions. + * @type {boolean} + * @readonly + */ + get manageable() { + if (this.user.id === this.guild.ownerID) return false; + if (this.user.id === this.client.user.id) return false; + if (this.client.user.id === this.guild.ownerID) return true; + if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); + return this.guild.me.roles.highest.comparePositionTo(this.roles.highest) > 0; + } + + /** + * Whether this member is kickable by the client user + * @type {boolean} + * @readonly + */ + get kickable() { + return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.KICK_MEMBERS); + } + + /** + * Whether this member is bannable by the client user + * @type {boolean} + * @readonly + */ + get bannable() { + return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.BAN_MEMBERS); + } + + /** + * Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel, + * taking into account roles and permission overwrites. + * @param {ChannelResolvable} channel The guild channel to use as context + * @returns {Readonly} + */ + permissionsIn(channel) { + channel = this.guild.channels.resolve(channel); + if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE'); + return channel.memberPermissions(this); + } + + /** + * Checks if any of this member's roles have a permission. + * @param {PermissionResolvable} permission Permission(s) to check for + * @param {Object} [options] Options + * @param {boolean} [options.checkAdmin=true] Whether to allow the administrator permission to override + * @param {boolean} [options.checkOwner=true] Whether to allow being the guild's owner to override + * @returns {boolean} + */ + hasPermission(permission, { checkAdmin = true, checkOwner = true } = {}) { + if (checkOwner && this.user.id === this.guild.ownerID) return true; + const permissions = new Permissions(this.roles.cache.map(role => role.permissions)); + return permissions.has(permission, checkAdmin); + } + + /** + * The data for editing a guild member. + * @typedef {Object} GuildMemberEditData + * @property {string} [nick] The nickname to set for the member + * @property {Collection|RoleResolvable[]} [roles] The roles or role IDs to apply + * @property {boolean} [mute] Whether or not the member should be muted + * @property {boolean} [deaf] Whether or not the member should be deafened + * @property {ChannelResolvable|null} [channel] Channel to move member to (if they are connected to voice), or `null` + * if you want to kick them from voice + */ + + /** + * Edits this member. + * @param {GuildMemberEditData} data The data to edit the member with + * @param {string} [reason] Reason for editing this user + * @returns {Promise} + */ + async edit(data, reason) { + if (data.channel) { + data.channel = this.guild.channels.resolve(data.channel); + if (!data.channel || data.channel.type !== 'voice') { + throw new Error('GUILD_VOICE_CHANNEL_RESOLVE'); + } + data.channel_id = data.channel.id; + data.channel = undefined; + } else if (data.channel === null) { + data.channel_id = null; + data.channel = undefined; + } + if (data.roles) data.roles = data.roles.map(role => (role instanceof Role ? role.id : role)); + let endpoint = this.client.api.guilds(this.guild.id); + if (this.user.id === this.client.user.id) { + const keys = Object.keys(data); + if (keys.length === 1 && keys[0] === 'nick') endpoint = endpoint.members('@me').nick; + else endpoint = endpoint.members(this.id); + } else { + endpoint = endpoint.members(this.id); + } + await endpoint.patch({ data, reason }); + + const clone = this._clone(); + data.user = this.user; + clone._patch(data); + return clone; + } + + /** + * Sets the nickname for this member. + * @param {string} nick The nickname for the guild member + * @param {string} [reason] Reason for setting the nickname + * @returns {Promise} + */ + setNickname(nick, reason) { + return this.edit({ nick }, reason); + } + + /** + * Creates a DM channel between the client and this member. + * @returns {Promise} + */ + createDM() { + return this.user.createDM(); + } + + /** + * Deletes any DMs with this member. + * @returns {Promise} + */ + deleteDM() { + return this.user.deleteDM(); + } + + /** + * Kicks this member from the guild. + * @param {string} [reason] Reason for kicking user + * @returns {Promise} + */ + kick(reason) { + return this.client.api + .guilds(this.guild.id) + .members(this.user.id) + .delete({ reason }) + .then(() => this); + } + + /** + * Bans this guild member. + * @param {Object} [options] Options for the ban + * @param {number} [options.days=0] Number of days of messages to delete, must be between 0 and 7 + * @param {string} [options.reason] Reason for banning + * @returns {Promise} + * @example + * // ban a guild member + * guildMember.ban({ days: 7, reason: 'They deserved it' }) + * .then(console.log) + * .catch(console.error); + */ + ban(options) { + return this.guild.members.ban(this, options); + } + + /** + * Fetches this GuildMember. + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + fetch(force = false) { + return this.guild.members.fetch({ user: this.id, cache: true, force }); + } + + /** + * When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object. + * @returns {string} + * @example + * // Logs: Hello from <@123456789012345678>! + * console.log(`Hello from ${member}!`); + */ + toString() { + return `<@${this.nickname ? '!' : ''}${this.user.id}>`; + } + + toJSON() { + return super.toJSON({ + guild: 'guildID', + user: 'userID', + displayName: true, + speaking: false, + lastMessage: false, + lastMessageID: false, + roles: true, + }); + } + + // These are here only for documentation purposes - they are implemented by TextBasedChannel + /* eslint-disable no-empty-function */ + send() {} +} + +TextBasedChannel.applyToClass(GuildMember); + +module.exports = GuildMember; diff --git a/node_modules/discord.js/src/structures/GuildPreview.js b/node_modules/discord.js/src/structures/GuildPreview.js new file mode 100644 index 0000000..76f5342 --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildPreview.js @@ -0,0 +1,157 @@ +'use strict'; + +const Base = require('./Base'); +const GuildPreviewEmoji = require('./GuildPreviewEmoji'); +const Collection = require('../util/Collection'); + +/** + * Represents the data about the guild any bot can preview, connected to the specified guild. + * @extends {Base} + */ +class GuildPreview extends Base { + constructor(client, data) { + super(client); + + if (!data) return; + + this._patch(data); + } + + /** + * Builds the guild with the provided data. + * @param {*} data The raw data of the guild + * @private + */ + _patch(data) { + /** + * The id of this guild + * @type {string} + */ + this.id = data.id; + + /** + * The name of this guild + * @type {string} + */ + this.name = data.name; + + /** + * The icon of this guild + * @type {?string} + */ + this.icon = data.icon; + + /** + * The splash icon of this guild + * @type {?string} + */ + this.splash = data.splash; + + /** + * The discovery splash icon of this guild + * @type {?string} + */ + this.discoverySplash = data.discovery_splash; + + /** + * An array of enabled guild features + * @type {Features[]} + */ + this.features = data.features; + + /** + * The approximate count of members in this guild + * @type {number} + */ + this.approximateMemberCount = data.approximate_member_count; + + /** + * The approximate count of online members in this guild + * @type {number} + */ + this.approximatePresenceCount = data.approximate_presence_count; + + /** + * The description for this guild + * @type {?string} + */ + this.description = data.description || null; + + if (!this.emojis) { + /** + * Collection of emojis belonging to this guild + * @type {Collection} + */ + this.emojis = new Collection(); + } else { + this.emojis.clear(); + } + for (const emoji of data.emojis) { + this.emojis.set(emoji.id, new GuildPreviewEmoji(this.client, emoji, this)); + } + } + + /** + * The URL to this guild's splash. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + splashURL({ format, size } = {}) { + if (!this.splash) return null; + return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + } + + /** + * The URL to this guild's discovery splash. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + discoverySplashURL({ format, size } = {}) { + if (!this.discoverySplash) return null; + return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + } + + /** + * The URL to this guild's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + iconURL({ format, size, dynamic } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); + } + + /** + * Fetches this guild. + * @returns {Promise} + */ + fetch() { + return this.client.api + .guilds(this.id) + .preview.get() + .then(data => { + this._patch(data); + return this; + }); + } + + /** + * When concatenated with a string, this automatically returns the guild's name instead of the Guild object. + * @returns {string} + * @example + * // Logs: Hello from My Guild! + * console.log(`Hello from ${previewGuild}!`); + */ + toString() { + return this.name; + } + + toJSON() { + const json = super.toJSON(); + json.iconURL = this.iconURL(); + json.splashURL = this.splashURL(); + return json; + } +} + +module.exports = GuildPreview; diff --git a/node_modules/discord.js/src/structures/GuildPreviewEmoji.js b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js new file mode 100644 index 0000000..4c70903 --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js @@ -0,0 +1,26 @@ +'use strict'; + +const BaseGuildEmoji = require('./BaseGuildEmoji'); + +/** + * Represents an instance of an emoji belonging to a public guild obtained through Discord's preview endpoint. + * @extends {BaseGuildEmoji} + */ +class GuildPreviewEmoji extends BaseGuildEmoji { + /** + * The public guild this emoji is part of + * @type {GuildPreview} + * @name GuildPreviewEmoji#guild + */ + + /** + * Set of roles this emoji is active for + * @type {Set} + * @readonly + */ + get roles() { + return new Set(this._roles); + } +} + +module.exports = GuildPreviewEmoji; diff --git a/node_modules/discord.js/src/structures/GuildTemplate.js b/node_modules/discord.js/src/structures/GuildTemplate.js new file mode 100644 index 0000000..7510bb9 --- /dev/null +++ b/node_modules/discord.js/src/structures/GuildTemplate.js @@ -0,0 +1,225 @@ +'use strict'; + +const Base = require('./Base'); +const { Events } = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); + +/** + * Represents the template for a guild. + * @extends {Base} + */ +class GuildTemplate extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The raw data for the template + */ + constructor(client, data) { + super(client); + this._patch(data); + } + + /** + * Builds or updates the template with the provided data. + * @param {Object} data The raw data for the template + * @returns {GuildTemplate} + * @private + */ + _patch(data) { + /** + * The unique code of this template + * @type {string} + */ + this.code = data.code; + + /** + * The name of this template + * @type {string} + */ + this.name = data.name; + + /** + * The description of this template + * @type {?string} + */ + this.description = data.description; + + /** + * The amount of times this template has been used + * @type {number} + */ + this.usageCount = data.usage_count; + + /** + * The ID of the user that created this template + * @type {Snowflake} + */ + this.creatorID = data.creator_id; + + /** + * The user that created this template + * @type {User} + */ + this.creator = this.client.users.add(data.creator); + + /** + * The time of when this template was created at + * @type {Date} + */ + this.createdAt = new Date(data.created_at); + + /** + * The time of when this template was last synced to the guild + * @type {Date} + */ + this.updatedAt = new Date(data.updated_at); + + /** + * The ID of the guild that this template belongs to + * @type {Snowflake} + */ + this.guildID = data.source_guild_id; + + /** + * The data of the guild that this template would create + * @type {Object} + * @see {@link https://discord.com/developers/docs/resources/guild#guild-resource} + */ + this.serializedGuild = data.serialized_source_guild; + + /** + * Whether this template has unsynced changes + * @type {?boolean} + */ + this.unSynced = 'is_dirty' in data ? Boolean(data.is_dirty) : null; + + return this; + } + + /** + * Creates a guild based from this template. + * This is only available to bots in fewer than 10 guilds. + * @param {string} name The name of the guild + * @param {BufferResolvable|Base64Resolvable} [icon] The icon for the guild + * @returns {Promise} + */ + async createGuild(name, icon) { + const { client } = this; + const data = await client.api.guilds.templates(this.code).post({ + data: { + name, + icon: await DataResolver.resolveImage(icon), + }, + }); + // eslint-disable-next-line consistent-return + return new Promise(resolve => { + const createdGuild = client.guilds.cache.get(data.id); + if (createdGuild) return resolve(createdGuild); + + const resolveGuild = guild => { + client.off(Events.GUILD_CREATE, handleGuild); + client.decrementMaxListeners(); + resolve(guild); + }; + + const handleGuild = guild => { + if (guild.id === data.id) { + client.clearTimeout(timeout); + resolveGuild(guild); + } + }; + + client.incrementMaxListeners(); + client.on(Events.GUILD_CREATE, handleGuild); + + const timeout = client.setTimeout(() => resolveGuild(client.guilds.add(data)), 10000); + }); + } + + /** + * Updates the metadata on this template. + * @param {Object} options Options for the template + * @param {string} [options.name] The name of this template + * @param {string} [options.description] The description of this template + * @returns {Promise} + */ + edit({ name, description } = {}) { + return this.client.api + .guilds(this.guildID) + .templates(this.code) + .patch({ data: { name, description } }) + .then(data => this._patch(data)); + } + + /** + * Deletes this template. + * @returns {Promise} + */ + delete() { + return this.client.api + .guilds(this.guildID) + .templates(this.code) + .delete() + .then(() => this); + } + + /** + * Syncs this template to the current state of the guild. + * @returns {Promise} + */ + sync() { + return this.client.api + .guilds(this.guildID) + .templates(this.code) + .put() + .then(data => this._patch(data)); + } + + /** + * The timestamp of when this template was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return this.createdAt.getTime(); + } + + /** + * The timestamp of when this template was last synced to the guild + * @type {number} + * @readonly + */ + get updatedTimestamp() { + return this.updatedAt.getTime(); + } + + /** + * The guild that this template belongs to + * @type {?Guild} + * @readonly + */ + get guild() { + return this.client.guilds.cache.get(this.guildID) || null; + } + + /** + * The URL of this template + * @type {string} + * @readonly + */ + get url() { + return `${this.client.options.http.template}/${this.code}`; + } + + /** + * When concatenated with a string, this automatically returns the templates's code instead of the template object. + * @returns {string} + * @example + * // Logs: Template: FKvmczH2HyUf + * console.log(`Template: ${guildTemplate}!`); + */ + toString() { + return this.code; + } +} + +module.exports = GuildTemplate; diff --git a/node_modules/discord.js/src/structures/Integration.js b/node_modules/discord.js/src/structures/Integration.js new file mode 100644 index 0000000..a48019a --- /dev/null +++ b/node_modules/discord.js/src/structures/Integration.js @@ -0,0 +1,186 @@ +'use strict'; + +const Base = require('./Base'); +const IntegrationApplication = require('./IntegrationApplication'); + +/** + * The information account for an integration + * @typedef {Object} IntegrationAccount + * @property {string} id The id of the account + * @property {string} name The name of the account + */ + +/** + * Represents a guild integration. + */ +class Integration extends Base { + constructor(client, data, guild) { + super(client); + + /** + * The guild this integration belongs to + * @type {Guild} + */ + this.guild = guild; + + /** + * The integration id + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The integration name + * @type {string} + */ + this.name = data.name; + + /** + * The integration type (twitch, youtube, etc) + * @type {string} + */ + this.type = data.type; + + /** + * Whether this integration is enabled + * @type {boolean} + */ + this.enabled = data.enabled; + + /** + * Whether this integration is syncing + * @type {boolean} + */ + this.syncing = data.syncing; + + /** + * The role that this integration uses for subscribers + * @type {Role} + */ + this.role = this.guild.roles.cache.get(data.role_id); + + if (data.user) { + /** + * The user for this integration + * @type {?User} + */ + this.user = this.client.users.add(data.user); + } else { + this.user = null; + } + + /** + * The account integration information + * @type {IntegrationAccount} + */ + this.account = data.account; + + /** + * The last time this integration was last synced + * @type {number} + */ + this.syncedAt = data.synced_at; + this._patch(data); + } + + _patch(data) { + /** + * The behavior of expiring subscribers + * @type {number} + */ + this.expireBehavior = data.expire_behavior; + + /** + * The grace period before expiring subscribers + * @type {number} + */ + this.expireGracePeriod = data.expire_grace_period; + + if ('application' in data) { + if (this.application) { + this.application._patch(data.application); + } else { + /** + * The application for this integration + * @type {?IntegrationApplication} + */ + this.application = new IntegrationApplication(this.client, data.application); + } + } else if (!this.application) { + this.application = null; + } + } + + /** + * Sync this integration + * @returns {Promise} + */ + sync() { + this.syncing = true; + return this.client.api + .guilds(this.guild.id) + .integrations(this.id) + .post() + .then(() => { + this.syncing = false; + this.syncedAt = Date.now(); + return this; + }); + } + + /** + * The data for editing an integration. + * @typedef {Object} IntegrationEditData + * @property {number} [expireBehavior] The new behaviour of expiring subscribers + * @property {number} [expireGracePeriod] The new grace period before expiring subscribers + */ + + /** + * Edits this integration. + * @param {IntegrationEditData} data The data to edit this integration with + * @param {string} reason Reason for editing this integration + * @returns {Promise} + */ + edit(data, reason) { + if ('expireBehavior' in data) { + data.expire_behavior = data.expireBehavior; + data.expireBehavior = null; + } + if ('expireGracePeriod' in data) { + data.expire_grace_period = data.expireGracePeriod; + data.expireGracePeriod = null; + } + // The option enable_emoticons is only available for Twitch at this moment + return this.client.api + .guilds(this.guild.id) + .integrations(this.id) + .patch({ data, reason }) + .then(() => { + this._patch(data); + return this; + }); + } + + /** + * Deletes this integration. + * @returns {Promise} + * @param {string} [reason] Reason for deleting this integration + */ + delete(reason) { + return this.client.api + .guilds(this.guild.id) + .integrations(this.id) + .delete({ reason }) + .then(() => this); + } + + toJSON() { + return super.toJSON({ + role: 'roleID', + guild: 'guildID', + user: 'userID', + }); + } +} + +module.exports = Integration; diff --git a/node_modules/discord.js/src/structures/IntegrationApplication.js b/node_modules/discord.js/src/structures/IntegrationApplication.js new file mode 100644 index 0000000..40f433a --- /dev/null +++ b/node_modules/discord.js/src/structures/IntegrationApplication.js @@ -0,0 +1,25 @@ +'use strict'; + +const Application = require('./interfaces/Application'); + +/** + * Represents an Integration's OAuth2 Application. + * @extends {Application} + */ +class IntegrationApplication extends Application { + _patch(data) { + super._patch(data); + + if (typeof data.bot !== 'undefined') { + /** + * The bot {@link User user} for this application + * @type {?User} + */ + this.bot = this.client.users.add(data.bot); + } else if (!this.bot) { + this.bot = null; + } + } +} + +module.exports = IntegrationApplication; diff --git a/node_modules/discord.js/src/structures/Invite.js b/node_modules/discord.js/src/structures/Invite.js new file mode 100644 index 0000000..6833266 --- /dev/null +++ b/node_modules/discord.js/src/structures/Invite.js @@ -0,0 +1,194 @@ +'use strict'; + +const Base = require('./Base'); +const { Endpoints } = require('../util/Constants'); +const Permissions = require('../util/Permissions'); + +/** + * Represents an invitation to a guild channel. + * The only guaranteed properties are `code`, `channel`, and `url`. Other properties can be missing. + * @extends {Base} + */ +class Invite extends Base { + constructor(client, data) { + super(client); + this._patch(data); + } + + _patch(data) { + /** + * The guild the invite is for + * @type {?Guild} + */ + this.guild = data.guild ? this.client.guilds.add(data.guild, false) : null; + + /** + * The code for this invite + * @type {string} + */ + this.code = data.code; + + /** + * The approximate number of online members of the guild this invite is for + * @type {?number} + */ + this.presenceCount = 'approximate_presence_count' in data ? data.approximate_presence_count : null; + + /** + * The approximate total number of members of the guild this invite is for + * @type {?number} + */ + this.memberCount = 'approximate_member_count' in data ? data.approximate_member_count : null; + + /** + * Whether or not this invite is temporary + * @type {?boolean} + */ + this.temporary = 'temporary' in data ? data.temporary : null; + + /** + * The maximum age of the invite, in seconds, 0 if never expires + * @type {?number} + */ + this.maxAge = 'max_age' in data ? data.max_age : null; + + /** + * How many times this invite has been used + * @type {?number} + */ + this.uses = 'uses' in data ? data.uses : null; + + /** + * The maximum uses of this invite + * @type {?number} + */ + this.maxUses = 'max_uses' in data ? data.max_uses : null; + + /** + * The user who created this invite + * @type {?User} + */ + this.inviter = data.inviter ? this.client.users.add(data.inviter) : null; + + /** + * The target user for this invite + * @type {?User} + */ + this.targetUser = data.target_user ? this.client.users.add(data.target_user) : null; + + /** + * The type of the target user: + * * 1: STREAM + * @typedef {number} TargetUser + */ + + /** + * The target user type + * @type {?TargetUser} + */ + this.targetUserType = typeof data.target_user_type === 'number' ? data.target_user_type : null; + + /** + * The channel the invite is for + * @type {Channel} + */ + this.channel = this.client.channels.add(data.channel, this.guild, false); + + /** + * The timestamp the invite was created at + * @type {?number} + */ + this.createdTimestamp = 'created_at' in data ? new Date(data.created_at).getTime() : null; + } + + /** + * The time the invite was created at + * @type {?Date} + * @readonly + */ + get createdAt() { + return this.createdTimestamp ? new Date(this.createdTimestamp) : null; + } + + /** + * Whether the invite is deletable by the client user + * @type {boolean} + * @readonly + */ + get deletable() { + const guild = this.guild; + if (!guild || !this.client.guilds.cache.has(guild.id)) return false; + if (!guild.me) throw new Error('GUILD_UNCACHED_ME'); + return ( + this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) || + guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD) + ); + } + + /** + * The timestamp the invite will expire at + * @type {?number} + * @readonly + */ + get expiresTimestamp() { + return this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1000 : null; + } + + /** + * The time the invite will expire at + * @type {?Date} + * @readonly + */ + get expiresAt() { + const { expiresTimestamp } = this; + return expiresTimestamp ? new Date(expiresTimestamp) : null; + } + + /** + * The URL to the invite + * @type {string} + * @readonly + */ + get url() { + return Endpoints.invite(this.client.options.http.invite, this.code); + } + + /** + * Deletes this invite. + * @param {string} [reason] Reason for deleting this invite + * @returns {Promise} + */ + delete(reason) { + return this.client.api.invites[this.code].delete({ reason }).then(() => this); + } + + /** + * When concatenated with a string, this automatically concatenates the invite's URL instead of the object. + * @returns {string} + * @example + * // Logs: Invite: https://discord.gg/A1b2C3 + * console.log(`Invite: ${invite}`); + */ + toString() { + return this.url; + } + + toJSON() { + return super.toJSON({ + url: true, + expiresTimestamp: true, + presenceCount: false, + memberCount: false, + uses: false, + channel: 'channelID', + inviter: 'inviterID', + guild: 'guildID', + }); + } + + valueOf() { + return this.code; + } +} + +module.exports = Invite; diff --git a/node_modules/discord.js/src/structures/Message.js b/node_modules/discord.js/src/structures/Message.js new file mode 100644 index 0000000..36c26f2 --- /dev/null +++ b/node_modules/discord.js/src/structures/Message.js @@ -0,0 +1,700 @@ +'use strict'; + +const APIMessage = require('./APIMessage'); +const Base = require('./Base'); +const ClientApplication = require('./ClientApplication'); +const MessageAttachment = require('./MessageAttachment'); +const Embed = require('./MessageEmbed'); +const Mentions = require('./MessageMentions'); +const ReactionCollector = require('./ReactionCollector'); +const { Error, TypeError } = require('../errors'); +const ReactionManager = require('../managers/ReactionManager'); +const Collection = require('../util/Collection'); +const { MessageTypes } = require('../util/Constants'); +const MessageFlags = require('../util/MessageFlags'); +const Permissions = require('../util/Permissions'); +const SnowflakeUtil = require('../util/Snowflake'); +const Util = require('../util/Util'); + +/** + * Represents a message on Discord. + * @extends {Base} + */ +class Message extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the message + * @param {TextChannel|DMChannel|NewsChannel} channel The channel the message was sent in + */ + constructor(client, data, channel) { + super(client); + + /** + * The channel that the message was sent in + * @type {TextChannel|DMChannel|NewsChannel} + */ + this.channel = channel; + + /** + * Whether this message has been deleted + * @type {boolean} + */ + this.deleted = false; + + if (data) this._patch(data); + } + + _patch(data) { + /** + * The ID of the message + * @type {Snowflake} + */ + this.id = data.id; + + if ('type' in data) { + /** + * The type of the message + * @type {?MessageType} + */ + this.type = MessageTypes[data.type]; + + /** + * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications) + * @type {?boolean} + */ + this.system = data.type !== 0; + } else if (typeof this.type !== 'string') { + this.system = null; + this.type = null; + } + + if ('content' in data) { + /** + * The content of the message + * @type {?string} + */ + this.content = data.content; + } else if (typeof this.content !== 'string') { + this.content = null; + } + + if ('author' in data) { + /** + * The author of the message + * @type {?User} + */ + this.author = this.client.users.add(data.author, !data.webhook_id); + } else if (!this.author) { + this.author = null; + } + + if ('pinned' in data) { + /** + * Whether or not this message is pinned + * @type {?boolean} + */ + this.pinned = Boolean(data.pinned); + } else if (typeof this.pinned !== 'boolean') { + this.pinned = null; + } + + if ('tts' in data) { + /** + * Whether or not the message was Text-To-Speech + * @type {?boolean} + */ + this.tts = data.tts; + } else if (typeof this.tts !== 'boolean') { + this.tts = null; + } + + /** + * A random number or string used for checking message delivery + * This is only received after the message was sent successfully, and + * lost if re-fetched + * @type {?string} + */ + this.nonce = 'nonce' in data ? data.nonce : null; + + /** + * A list of embeds in the message - e.g. YouTube Player + * @type {MessageEmbed[]} + */ + this.embeds = (data.embeds || []).map(e => new Embed(e, true)); + + /** + * A collection of attachments in the message - e.g. Pictures - mapped by their ID + * @type {Collection} + */ + this.attachments = new Collection(); + if (data.attachments) { + for (const attachment of data.attachments) { + this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment)); + } + } + + /** + * The timestamp the message was sent at + * @type {number} + */ + this.createdTimestamp = SnowflakeUtil.deconstruct(this.id).timestamp; + + /** + * The timestamp the message was last edited at (if applicable) + * @type {?number} + */ + this.editedTimestamp = 'edited_timestamp' in data ? new Date(data.edited_timestamp).getTime() : null; + + /** + * A manager of the reactions belonging to this message + * @type {ReactionManager} + */ + this.reactions = new ReactionManager(this); + if (data.reactions && data.reactions.length > 0) { + for (const reaction of data.reactions) { + this.reactions.add(reaction); + } + } + + /** + * All valid mentions that the message contains + * @type {MessageMentions} + */ + this.mentions = new Mentions(this, data.mentions, data.mention_roles, data.mention_everyone, data.mention_channels); + + /** + * ID of the webhook that sent the message, if applicable + * @type {?Snowflake} + */ + this.webhookID = data.webhook_id || null; + + /** + * Supplemental application information for group activities + * @type {?ClientApplication} + */ + this.application = data.application ? new ClientApplication(this.client, data.application) : null; + + /** + * Group activity + * @type {?MessageActivity} + */ + this.activity = data.activity + ? { + partyID: data.activity.party_id, + type: data.activity.type, + } + : null; + + /** + * The previous versions of the message, sorted with the most recent first + * @type {Message[]} + * @private + */ + this._edits = []; + + if (this.member && data.member) { + this.member._patch(data.member); + } else if (data.member && this.guild && this.author) { + this.guild.members.add(Object.assign(data.member, { user: this.author })); + } + + /** + * Flags that are applied to the message + * @type {Readonly} + */ + this.flags = new MessageFlags(data.flags).freeze(); + + /** + * Reference data sent in a crossposted message. + * @typedef {Object} MessageReference + * @property {string} channelID ID of the channel the message was crossposted from + * @property {?string} guildID ID of the guild the message was crossposted from + * @property {?string} messageID ID of the message that was crossposted + */ + + /** + * Message reference data + * @type {?MessageReference} + */ + this.reference = data.message_reference + ? { + channelID: data.message_reference.channel_id, + guildID: data.message_reference.guild_id, + messageID: data.message_reference.message_id, + } + : null; + } + + /** + * Whether or not this message is a partial + * @type {boolean} + * @readonly + */ + get partial() { + return typeof this.content !== 'string' || !this.author; + } + + /** + * Updates the message and returns the old message. + * @param {Object} data Raw Discord message update data + * @returns {Message} + * @private + */ + patch(data) { + const clone = this._clone(); + const { messageEditHistoryMaxSize } = this.client.options; + if (messageEditHistoryMaxSize !== 0) { + const editsLimit = messageEditHistoryMaxSize === -1 ? Infinity : messageEditHistoryMaxSize; + if (this._edits.unshift(clone) > editsLimit) this._edits.pop(); + } + + if ('edited_timestamp' in data) this.editedTimestamp = new Date(data.edited_timestamp).getTime(); + if ('content' in data) this.content = data.content; + if ('pinned' in data) this.pinned = data.pinned; + if ('tts' in data) this.tts = data.tts; + if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e, true)); + else this.embeds = this.embeds.slice(); + + if ('attachments' in data) { + this.attachments = new Collection(); + for (const attachment of data.attachments) { + this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment)); + } + } else { + this.attachments = new Collection(this.attachments); + } + + this.mentions = new Mentions( + this, + 'mentions' in data ? data.mentions : this.mentions.users, + 'mention_roles' in data ? data.mention_roles : this.mentions.roles, + 'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone, + 'mention_channels' in data ? data.mention_channels : this.mentions.crosspostedChannels, + ); + + this.flags = new MessageFlags('flags' in data ? data.flags : 0).freeze(); + + return clone; + } + + /** + * Represents the author of the message as a guild member. + * Only available if the message comes from a guild where the author is still a member + * @type {?GuildMember} + * @readonly + */ + get member() { + return this.guild ? this.guild.member(this.author) || null : null; + } + + /** + * The time the message was sent at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The time the message was last edited at (if applicable) + * @type {?Date} + * @readonly + */ + get editedAt() { + return this.editedTimestamp ? new Date(this.editedTimestamp) : null; + } + + /** + * The guild the message was sent in (if in a guild channel) + * @type {?Guild} + * @readonly + */ + get guild() { + return this.channel.guild || null; + } + + /** + * The url to jump to this message + * @type {string} + * @readonly + */ + get url() { + return `https://discord.com/channels/${this.guild ? this.guild.id : '@me'}/${this.channel.id}/${this.id}`; + } + + /** + * The message contents with all mentions replaced by the equivalent text. + * If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted. + * @type {string} + * @readonly + */ + get cleanContent() { + // eslint-disable-next-line eqeqeq + return this.content != null ? Util.cleanContent(this.content, this) : null; + } + + /** + * Creates a reaction collector. + * @param {CollectorFilter} filter The filter to apply + * @param {ReactionCollectorOptions} [options={}] Options to send to the collector + * @returns {ReactionCollector} + * @example + * // Create a reaction collector + * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID'; + * const collector = message.createReactionCollector(filter, { time: 15000 }); + * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`)); + * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + */ + createReactionCollector(filter, options = {}) { + return new ReactionCollector(this, filter, options); + } + + /** + * An object containing the same properties as CollectorOptions, but a few more: + * @typedef {ReactionCollectorOptions} AwaitReactionsOptions + * @property {string[]} [errors] Stop/end reasons that cause the promise to reject + */ + + /** + * Similar to createReactionCollector but in promise form. + * Resolves with a collection of reactions that pass the specified filter. + * @param {CollectorFilter} filter The filter function to use + * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector + * @returns {Promise>} + * @example + * // Create a reaction collector + * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID' + * message.awaitReactions(filter, { time: 15000 }) + * .then(collected => console.log(`Collected ${collected.size} reactions`)) + * .catch(console.error); + */ + awaitReactions(filter, options = {}) { + return new Promise((resolve, reject) => { + const collector = this.createReactionCollector(filter, options); + collector.once('end', (reactions, reason) => { + if (options.errors && options.errors.includes(reason)) reject(reactions); + else resolve(reactions); + }); + }); + } + + /** + * An array of cached versions of the message, including the current version + * Sorted from latest (first) to oldest (last) + * @type {Message[]} + * @readonly + */ + get edits() { + const copy = this._edits.slice(); + copy.unshift(this); + return copy; + } + + /** + * Whether the message is editable by the client user + * @type {boolean} + * @readonly + */ + get editable() { + return this.author.id === this.client.user.id; + } + + /** + * Whether the message is deletable by the client user + * @type {boolean} + * @readonly + */ + get deletable() { + return ( + !this.deleted && + (this.author.id === this.client.user.id || + (this.guild && this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false))) + ); + } + + /** + * Whether the message is pinnable by the client user + * @type {boolean} + * @readonly + */ + get pinnable() { + return ( + this.type === 'DEFAULT' && + (!this.guild || this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false)) + ); + } + + /** + * Whether the message is crosspostable by the client user + * @type {boolean} + * @readonly + */ + get crosspostable() { + return ( + this.channel.type === 'news' && + !this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) && + this.type === 'DEFAULT' && + this.channel.viewable && + this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.SEND_MESSAGES) && + (this.author.id === this.client.user.id || + this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES)) + ); + } + + /** + * Options that can be passed into editMessage. + * @typedef {Object} MessageEditOptions + * @property {string} [content] Content to be edited + * @property {MessageEmbed|Object} [embed] An embed to be added/edited + * @property {string|boolean} [code] Language for optional codeblock formatting to apply + * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content + */ + + /** + * Edits the content of the message. + * @param {StringResolvable|APIMessage} [content] The new content for the message + * @param {MessageEditOptions|MessageEmbed} [options] The options to provide + * @returns {Promise} + * @example + * // Update the content of a message + * message.edit('This is my new content!') + * .then(msg => console.log(`Updated the content of a message to ${msg.content}`)) + * .catch(console.error); + */ + edit(content, options) { + const { data } = + content instanceof APIMessage ? content.resolveData() : APIMessage.create(this, content, options).resolveData(); + return this.client.api.channels[this.channel.id].messages[this.id].patch({ data }).then(d => { + const clone = this._clone(); + clone._patch(d); + return clone; + }); + } + + /** + * Publishes a message in an announcement channel to all channels following it. + * @returns {Promise} + * @example + * // Crosspost a message + * if (message.channel.type === 'news') { + * message.crosspost() + * .then(() => console.log('Crossposted message')) + * .catch(console.error); + * } + */ + async crosspost() { + await this.client.api.channels(this.channel.id).messages(this.id).crosspost.post(); + return this; + } + + /** + * Pins this message to the channel's pinned messages. + * @param {Object} [options] Options for pinning + * @param {string} [options.reason] Reason for pinning + * @returns {Promise} + * @example + * // Pin a message with a reason + * message.pin({ reason: 'important' }) + * .then(console.log) + * .catch(console.error) + */ + pin(options) { + return this.client.api + .channels(this.channel.id) + .pins(this.id) + .put(options) + .then(() => this); + } + + /** + * Unpins this message from the channel's pinned messages. + * @param {Object} [options] Options for unpinning + * @param {string} [options.reason] Reason for unpinning + * @returns {Promise} + * @example + * // Unpin a message with a reason + * message.unpin({ reason: 'no longer relevant' }) + * .then(console.log) + * .catch(console.error) + */ + unpin(options) { + return this.client.api + .channels(this.channel.id) + .pins(this.id) + .delete(options) + .then(() => this); + } + + /** + * Adds a reaction to the message. + * @param {EmojiIdentifierResolvable} emoji The emoji to react with + * @returns {Promise} + * @example + * // React to a message with a unicode emoji + * message.react('🤔') + * .then(console.log) + * .catch(console.error); + * @example + * // React to a message with a custom emoji + * message.react(message.guild.emojis.cache.get('123456789012345678')) + * .then(console.log) + * .catch(console.error); + */ + react(emoji) { + emoji = this.client.emojis.resolveIdentifier(emoji); + if (!emoji) throw new TypeError('EMOJI_TYPE'); + + return this.client.api + .channels(this.channel.id) + .messages(this.id) + .reactions(emoji, '@me') + .put() + .then( + () => + this.client.actions.MessageReactionAdd.handle({ + user: this.client.user, + channel: this.channel, + message: this, + emoji: Util.parseEmoji(emoji), + }).reaction, + ); + } + + /** + * Deletes the message. + * @param {Object} [options] Options + * @param {number} [options.timeout=0] How long to wait to delete the message in milliseconds + * @param {string} [options.reason] Reason for deleting this message, if it does not belong to the client user + * @returns {Promise} + * @example + * // Delete a message + * message.delete({ timeout: 5000 }) + * .then(msg => console.log(`Deleted message from ${msg.author.username} after 5 seconds`)) + * .catch(console.error); + */ + delete(options = {}) { + if (typeof options !== 'object') return Promise.reject(new TypeError('INVALID_TYPE', 'options', 'object', true)); + const { timeout = 0, reason } = options; + if (timeout <= 0) { + return this.channel.messages.delete(this.id, reason).then(() => this); + } else { + return new Promise(resolve => { + this.client.setTimeout(() => { + resolve(this.delete({ reason })); + }, timeout); + }); + } + } + + /** + * Replies to the message. + * @param {StringResolvable|APIMessage} [content=''] The content for the message + * @param {MessageOptions|MessageAdditions} [options={}] The options to provide + * @returns {Promise} + * @example + * // Reply to a message + * message.reply('Hey, I\'m a reply!') + * .then(() => console.log(`Sent a reply to ${message.author.username}`)) + * .catch(console.error); + */ + reply(content, options) { + return this.channel.send( + content instanceof APIMessage + ? content + : APIMessage.transformOptions(content, options, { reply: this.member || this.author }), + ); + } + + /** + * Fetch this message. + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + fetch(force = false) { + return this.channel.messages.fetch(this.id, true, force); + } + + /** + * Fetches the webhook used to create this message. + * @returns {Promise} + */ + fetchWebhook() { + if (!this.webhookID) return Promise.reject(new Error('WEBHOOK_MESSAGE')); + return this.client.fetchWebhook(this.webhookID); + } + + /** + * Suppresses or unsuppresses embeds on a message + * @param {boolean} [suppress=true] If the embeds should be suppressed or not + * @returns {Promise} + */ + suppressEmbeds(suppress = true) { + const flags = new MessageFlags(this.flags.bitfield); + + if (suppress) { + flags.add(MessageFlags.FLAGS.SUPPRESS_EMBEDS); + } else { + flags.remove(MessageFlags.FLAGS.SUPPRESS_EMBEDS); + } + + return this.edit({ flags }); + } + + /** + * Used mainly internally. Whether two messages are identical in properties. If you want to compare messages + * without checking all the properties, use `message.id === message2.id`, which is much more efficient. This + * method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties. + * @param {Message} message The message to compare it to + * @param {Object} rawData Raw data passed through the WebSocket about this message + * @returns {boolean} + */ + equals(message, rawData) { + if (!message) return false; + const embedUpdate = !message.author && !message.attachments; + if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length; + + let equal = + this.id === message.id && + this.author.id === message.author.id && + this.content === message.content && + this.tts === message.tts && + this.nonce === message.nonce && + this.embeds.length === message.embeds.length && + this.attachments.length === message.attachments.length; + + if (equal && rawData) { + equal = + this.mentions.everyone === message.mentions.everyone && + this.createdTimestamp === new Date(rawData.timestamp).getTime() && + this.editedTimestamp === new Date(rawData.edited_timestamp).getTime(); + } + + return equal; + } + + /** + * When concatenated with a string, this automatically concatenates the message's content instead of the object. + * @returns {string} + * @example + * // Logs: Message: This is a message! + * console.log(`Message: ${message}`); + */ + toString() { + return this.content; + } + + toJSON() { + return super.toJSON({ + channel: 'channelID', + author: 'authorID', + application: 'applicationID', + guild: 'guildID', + cleanContent: true, + member: false, + reactions: false, + }); + } +} + +module.exports = Message; diff --git a/node_modules/discord.js/src/structures/MessageAttachment.js b/node_modules/discord.js/src/structures/MessageAttachment.js new file mode 100644 index 0000000..f5fb723 --- /dev/null +++ b/node_modules/discord.js/src/structures/MessageAttachment.js @@ -0,0 +1,98 @@ +'use strict'; + +const Util = require('../util/Util'); + +/** + * Represents an attachment in a message. + */ +class MessageAttachment { + /** + * @param {BufferResolvable|Stream} attachment The file + * @param {string} [name=null] The name of the file, if any + * @param {Object} [data] Extra data + */ + constructor(attachment, name = null, data) { + this.attachment = attachment; + /** + * The name of this attachment + * @type {?string} + */ + this.name = name; + if (data) this._patch(data); + } + + /** + * Sets the file of this attachment. + * @param {BufferResolvable|Stream} attachment The file + * @param {string} [name=null] The name of the file, if any + * @returns {MessageAttachment} This attachment + */ + setFile(attachment, name = null) { + this.attachment = attachment; + this.name = name; + return this; + } + + /** + * Sets the name of this attachment. + * @param {string} name The name of the file + * @returns {MessageAttachment} This attachment + */ + setName(name) { + this.name = name; + return this; + } + + _patch(data) { + /** + * The ID of this attachment + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The size of this attachment in bytes + * @type {number} + */ + this.size = data.size; + + /** + * The URL to this attachment + * @type {string} + */ + this.url = data.url; + + /** + * The Proxy URL to this attachment + * @type {string} + */ + this.proxyURL = data.proxy_url; + + /** + * The height of this attachment (if an image or video) + * @type {?number} + */ + this.height = typeof data.height !== 'undefined' ? data.height : null; + + /** + * The width of this attachment (if an image or video) + * @type {?number} + */ + this.width = typeof data.width !== 'undefined' ? data.width : null; + } + + /** + * Whether or not this attachment has been marked as a spoiler + * @type {boolean} + * @readonly + */ + get spoiler() { + return Util.basename(this.url).startsWith('SPOILER_'); + } + + toJSON() { + return Util.flatten(this); + } +} + +module.exports = MessageAttachment; diff --git a/node_modules/discord.js/src/structures/MessageCollector.js b/node_modules/discord.js/src/structures/MessageCollector.js new file mode 100644 index 0000000..740928d --- /dev/null +++ b/node_modules/discord.js/src/structures/MessageCollector.js @@ -0,0 +1,129 @@ +'use strict'; + +const Collector = require('./interfaces/Collector'); +const { Events } = require('../util/Constants'); + +/** + * @typedef {CollectorOptions} MessageCollectorOptions + * @property {number} max The maximum amount of messages to collect + * @property {number} maxProcessed The maximum amount of messages to process + */ + +/** + * Collects messages on a channel. + * Will automatically stop if the channel (`'channelDelete'`) or guild (`'guildDelete'`) are deleted. + * @extends {Collector} + */ +class MessageCollector extends Collector { + /** + * @param {TextChannel|DMChannel} channel The channel + * @param {CollectorFilter} filter The filter to be applied to this collector + * @param {MessageCollectorOptions} options The options to be applied to this collector + * @emits MessageCollector#message + */ + constructor(channel, filter, options = {}) { + super(channel.client, filter, options); + + /** + * The channel + * @type {TextBasedChannel} + */ + this.channel = channel; + + /** + * Total number of messages that were received in the channel during message collection + * @type {number} + */ + this.received = 0; + + const bulkDeleteListener = messages => { + for (const message of messages.values()) this.handleDispose(message); + }; + this._handleChannelDeletion = this._handleChannelDeletion.bind(this); + this._handleGuildDeletion = this._handleGuildDeletion.bind(this); + + this.client.incrementMaxListeners(); + this.client.on(Events.MESSAGE_CREATE, this.handleCollect); + this.client.on(Events.MESSAGE_DELETE, this.handleDispose); + this.client.on(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); + this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion); + + this.once('end', () => { + this.client.removeListener(Events.MESSAGE_CREATE, this.handleCollect); + this.client.removeListener(Events.MESSAGE_DELETE, this.handleDispose); + this.client.removeListener(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); + this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion); + this.client.decrementMaxListeners(); + }); + } + + /** + * Handles a message for possible collection. + * @param {Message} message The message that could be collected + * @returns {?Snowflake} + * @private + */ + collect(message) { + /** + * Emitted whenever a message is collected. + * @event MessageCollector#collect + * @param {Message} message The message that was collected + */ + if (message.channel.id !== this.channel.id) return null; + this.received++; + return message.id; + } + + /** + * Handles a message for possible disposal. + * @param {Message} message The message that could be disposed of + * @returns {?Snowflake} + */ + dispose(message) { + /** + * Emitted whenever a message is disposed of. + * @event MessageCollector#dispose + * @param {Message} message The message that was disposed of + */ + return message.channel.id === this.channel.id ? message.id : null; + } + + /** + * Checks after un/collection to see if the collector is done. + * @returns {?string} + * @private + */ + endReason() { + if (this.options.max && this.collected.size >= this.options.max) return 'limit'; + if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit'; + return null; + } + + /** + * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'. + * @private + * @param {GuildChannel} channel The channel that was deleted + * @returns {void} + */ + _handleChannelDeletion(channel) { + if (channel.id === this.channel.id) { + this.stop('channelDelete'); + } + } + + /** + * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'. + * @private + * @param {Guild} guild The guild that was deleted + * @returns {void} + */ + _handleGuildDeletion(guild) { + if (this.channel.guild && guild.id === this.channel.guild.id) { + this.stop('guildDelete'); + } + } +} + +module.exports = MessageCollector; diff --git a/node_modules/discord.js/src/structures/MessageEmbed.js b/node_modules/discord.js/src/structures/MessageEmbed.js new file mode 100644 index 0000000..ef007a5 --- /dev/null +++ b/node_modules/discord.js/src/structures/MessageEmbed.js @@ -0,0 +1,461 @@ +'use strict'; + +const { RangeError } = require('../errors'); +const Util = require('../util/Util'); + +/** + * Represents an embed in a message (image/video preview, rich embed, etc.) + */ +class MessageEmbed { + /** + * @name MessageEmbed + * @kind constructor + * @memberof MessageEmbed + * @param {MessageEmbed|Object} [data={}] MessageEmbed to clone or raw embed data + */ + + constructor(data = {}, skipValidation = false) { + this.setup(data, skipValidation); + } + + setup(data, skipValidation) { + /** + * The type of this embed, either: + * * `rich` - a rich embed + * * `image` - an image embed + * * `video` - a video embed + * * `gifv` - a gifv embed + * * `article` - an article embed + * * `link` - a link embed + * @type {string} + */ + this.type = data.type || 'rich'; + + /** + * The title of this embed + * @type {?string} + */ + this.title = 'title' in data ? data.title : null; + + /** + * The description of this embed + * @type {?string} + */ + this.description = 'description' in data ? data.description : null; + + /** + * The URL of this embed + * @type {?string} + */ + this.url = 'url' in data ? data.url : null; + + /** + * The color of this embed + * @type {?number} + */ + this.color = 'color' in data ? Util.resolveColor(data.color) : null; + + /** + * The timestamp of this embed + * @type {?number} + */ + this.timestamp = 'timestamp' in data ? new Date(data.timestamp).getTime() : null; + + /** + * Represents a field of a MessageEmbed + * @typedef {Object} EmbedField + * @property {string} name The name of this field + * @property {string} value The value of this field + * @property {boolean} inline If this field will be displayed inline + */ + + /** + * The fields of this embed + * @type {EmbedField[]} + */ + this.fields = []; + if (data.fields) { + this.fields = skipValidation ? data.fields.map(Util.cloneObject) : this.constructor.normalizeFields(data.fields); + } + + /** + * Represents the thumbnail of a MessageEmbed + * @typedef {Object} MessageEmbedThumbnail + * @property {string} url URL for this thumbnail + * @property {string} proxyURL ProxyURL for this thumbnail + * @property {number} height Height of this thumbnail + * @property {number} width Width of this thumbnail + */ + + /** + * The thumbnail of this embed (if there is one) + * @type {?MessageEmbedThumbnail} + */ + this.thumbnail = data.thumbnail + ? { + url: data.thumbnail.url, + proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url, + height: data.thumbnail.height, + width: data.thumbnail.width, + } + : null; + + /** + * Represents the image of a MessageEmbed + * @typedef {Object} MessageEmbedImage + * @property {string} url URL for this image + * @property {string} proxyURL ProxyURL for this image + * @property {number} height Height of this image + * @property {number} width Width of this image + */ + + /** + * The image of this embed, if there is one + * @type {?MessageEmbedImage} + */ + this.image = data.image + ? { + url: data.image.url, + proxyURL: data.image.proxyURL || data.image.proxy_url, + height: data.image.height, + width: data.image.width, + } + : null; + + /** + * Represents the video of a MessageEmbed + * @typedef {Object} MessageEmbedVideo + * @property {string} url URL of this video + * @property {string} proxyURL ProxyURL for this video + * @property {number} height Height of this video + * @property {number} width Width of this video + */ + + /** + * The video of this embed (if there is one) + * @type {?MessageEmbedVideo} + * @readonly + */ + this.video = data.video + ? { + url: data.video.url, + proxyURL: data.video.proxyURL || data.video.proxy_url, + height: data.video.height, + width: data.video.width, + } + : null; + + /** + * Represents the author field of a MessageEmbed + * @typedef {Object} MessageEmbedAuthor + * @property {string} name The name of this author + * @property {string} url URL of this author + * @property {string} iconURL URL of the icon for this author + * @property {string} proxyIconURL Proxied URL of the icon for this author + */ + + /** + * The author of this embed (if there is one) + * @type {?MessageEmbedAuthor} + */ + this.author = data.author + ? { + name: data.author.name, + url: data.author.url, + iconURL: data.author.iconURL || data.author.icon_url, + proxyIconURL: data.author.proxyIconURL || data.author.proxy_icon_url, + } + : null; + + /** + * Represents the provider of a MessageEmbed + * @typedef {Object} MessageEmbedProvider + * @property {string} name The name of this provider + * @property {string} url URL of this provider + */ + + /** + * The provider of this embed (if there is one) + * @type {?MessageEmbedProvider} + */ + this.provider = data.provider + ? { + name: data.provider.name, + url: data.provider.name, + } + : null; + + /** + * Represents the footer field of a MessageEmbed + * @typedef {Object} MessageEmbedFooter + * @property {string} text The text of this footer + * @property {string} iconURL URL of the icon for this footer + * @property {string} proxyIconURL Proxied URL of the icon for this footer + */ + + /** + * The footer of this embed + * @type {?MessageEmbedFooter} + */ + this.footer = data.footer + ? { + text: data.footer.text, + iconURL: data.footer.iconURL || data.footer.icon_url, + proxyIconURL: data.footer.proxyIconURL || data.footer.proxy_icon_url, + } + : null; + + /** + * The files of this embed + * @type {Array} + */ + this.files = data.files || []; + } + + /** + * The date displayed on this embed + * @type {?Date} + * @readonly + */ + get createdAt() { + return this.timestamp ? new Date(this.timestamp) : null; + } + + /** + * The hexadecimal version of the embed color, with a leading hash + * @type {?string} + * @readonly + */ + get hexColor() { + return this.color ? `#${this.color.toString(16).padStart(6, '0')}` : null; + } + + /** + * The accumulated length for the embed title, description, fields and footer text + * @type {number} + * @readonly + */ + get length() { + return ( + (this.title ? this.title.length : 0) + + (this.description ? this.description.length : 0) + + (this.fields.length >= 1 + ? this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0) + : 0) + + (this.footer ? this.footer.text.length : 0) + ); + } + + /** + * Adds a field to the embed (max 25). + * @param {StringResolvable} name The name of this field + * @param {StringResolvable} value The value of this field + * @param {boolean} [inline=false] If this field will be displayed inline + * @returns {MessageEmbed} + */ + addField(name, value, inline) { + return this.addFields({ name, value, inline }); + } + + /** + * Adds fields to the embed (max 25). + * @param {...EmbedFieldData|EmbedFieldData[]} fields The fields to add + * @returns {MessageEmbed} + */ + addFields(...fields) { + this.fields.push(...this.constructor.normalizeFields(fields)); + return this; + } + + /** + * Removes, replaces, and inserts fields in the embed (max 25). + * @param {number} index The index to start at + * @param {number} deleteCount The number of fields to remove + * @param {...EmbedFieldData|EmbedFieldData[]} [fields] The replacing field objects + * @returns {MessageEmbed} + */ + spliceFields(index, deleteCount, ...fields) { + this.fields.splice(index, deleteCount, ...this.constructor.normalizeFields(...fields)); + return this; + } + + /** + * Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when + * setting an embed image or author/footer icons. Multiple files can be attached. + * @param {Array} files Files to attach + * @returns {MessageEmbed} + */ + attachFiles(files) { + this.files = this.files.concat(files); + return this; + } + + /** + * Sets the author of this embed. + * @param {StringResolvable} name The name of the author + * @param {string} [iconURL] The icon URL of the author + * @param {string} [url] The URL of the author + * @returns {MessageEmbed} + */ + setAuthor(name, iconURL, url) { + this.author = { name: Util.resolveString(name), iconURL, url }; + return this; + } + + /** + * Sets the color of this embed. + * @param {ColorResolvable} color The color of the embed + * @returns {MessageEmbed} + */ + setColor(color) { + this.color = Util.resolveColor(color); + return this; + } + + /** + * Sets the description of this embed. + * @param {StringResolvable} description The description + * @returns {MessageEmbed} + */ + setDescription(description) { + description = Util.resolveString(description); + this.description = description; + return this; + } + + /** + * Sets the footer of this embed. + * @param {StringResolvable} text The text of the footer + * @param {string} [iconURL] The icon URL of the footer + * @returns {MessageEmbed} + */ + setFooter(text, iconURL) { + text = Util.resolveString(text); + this.footer = { text, iconURL }; + return this; + } + + /** + * Sets the image of this embed. + * @param {string} url The URL of the image + * @returns {MessageEmbed} + */ + setImage(url) { + this.image = { url }; + return this; + } + + /** + * Sets the thumbnail of this embed. + * @param {string} url The URL of the thumbnail + * @returns {MessageEmbed} + */ + setThumbnail(url) { + this.thumbnail = { url }; + return this; + } + + /** + * Sets the timestamp of this embed. + * @param {Date|number} [timestamp=Date.now()] The timestamp or date + * @returns {MessageEmbed} + */ + setTimestamp(timestamp = Date.now()) { + if (timestamp instanceof Date) timestamp = timestamp.getTime(); + this.timestamp = timestamp; + return this; + } + + /** + * Sets the title of this embed. + * @param {StringResolvable} title The title + * @returns {MessageEmbed} + */ + setTitle(title) { + title = Util.resolveString(title); + this.title = title; + return this; + } + + /** + * Sets the URL of this embed. + * @param {string} url The URL + * @returns {MessageEmbed} + */ + setURL(url) { + this.url = url; + return this; + } + + /** + * Transforms the embed to a plain object. + * @returns {Object} The raw data of this embed + */ + toJSON() { + return { + title: this.title, + type: 'rich', + description: this.description, + url: this.url, + timestamp: this.timestamp ? new Date(this.timestamp) : null, + color: this.color, + fields: this.fields, + thumbnail: this.thumbnail, + image: this.image, + author: this.author + ? { + name: this.author.name, + url: this.author.url, + icon_url: this.author.iconURL, + } + : null, + footer: this.footer + ? { + text: this.footer.text, + icon_url: this.footer.iconURL, + } + : null, + }; + } + + /** + * Normalizes field input and resolves strings. + * @param {StringResolvable} name The name of the field + * @param {StringResolvable} value The value of the field + * @param {boolean} [inline=false] Set the field to display inline + * @returns {EmbedField} + */ + static normalizeField(name, value, inline = false) { + name = Util.resolveString(name); + if (!name) throw new RangeError('EMBED_FIELD_NAME'); + value = Util.resolveString(value); + if (!value) throw new RangeError('EMBED_FIELD_VALUE'); + return { name, value, inline }; + } + + /** + * @typedef {Object} EmbedFieldData + * @property {StringResolvable} name The name of this field + * @property {StringResolvable} value The value of this field + * @property {boolean} [inline] If this field will be displayed inline + */ + + /** + * Normalizes field input and resolves strings. + * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize + * @returns {EmbedField[]} + */ + static normalizeFields(...fields) { + return fields + .flat(2) + .map(field => + this.normalizeField( + field && field.name, + field && field.value, + field && typeof field.inline === 'boolean' ? field.inline : false, + ), + ); + } +} + +module.exports = MessageEmbed; diff --git a/node_modules/discord.js/src/structures/MessageMentions.js b/node_modules/discord.js/src/structures/MessageMentions.js new file mode 100644 index 0000000..2ed24c0 --- /dev/null +++ b/node_modules/discord.js/src/structures/MessageMentions.js @@ -0,0 +1,225 @@ +'use strict'; + +const Collection = require('../util/Collection'); +const { ChannelTypes } = require('../util/Constants'); +const Util = require('../util/Util'); + +/** + * Keeps track of mentions in a {@link Message}. + */ +class MessageMentions { + constructor(message, users, roles, everyone, crosspostedChannels) { + /** + * The client the message is from + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: message.client }); + + /** + * The guild the message is in + * @type {?Guild} + * @readonly + */ + Object.defineProperty(this, 'guild', { value: message.guild }); + + /** + * The initial message content + * @type {string} + * @readonly + * @private + */ + Object.defineProperty(this, '_content', { value: message.content }); + + /** + * Whether `@everyone` or `@here` were mentioned + * @type {boolean} + */ + this.everyone = Boolean(everyone); + + if (users) { + if (users instanceof Collection) { + /** + * Any users that were mentioned + * Order as received from the API, not as they appear in the message content + * @type {Collection} + */ + this.users = new Collection(users); + } else { + this.users = new Collection(); + for (const mention of users) { + if (mention.member && message.guild) { + message.guild.members.add(Object.assign(mention.member, { user: mention })); + } + const user = message.client.users.add(mention); + this.users.set(user.id, user); + } + } + } else { + this.users = new Collection(); + } + + if (roles) { + if (roles instanceof Collection) { + /** + * Any roles that were mentioned + * Order as received from the API, not as they appear in the message content + * @type {Collection} + */ + this.roles = new Collection(roles); + } else { + this.roles = new Collection(); + for (const mention of roles) { + const role = message.channel.guild.roles.cache.get(mention); + if (role) this.roles.set(role.id, role); + } + } + } else { + this.roles = new Collection(); + } + + /** + * Cached members for {@link MessageMentions#members} + * @type {?Collection} + * @private + */ + this._members = null; + + /** + * Cached channels for {@link MessageMentions#channels} + * @type {?Collection} + * @private + */ + this._channels = null; + + /** + * Crossposted channel data. + * @typedef {Object} CrosspostedChannel + * @property {string} channelID ID of the mentioned channel + * @property {string} guildID ID of the guild that has the channel + * @property {string} type Type of the channel + * @property {string} name The name of the channel + */ + + if (crosspostedChannels) { + if (crosspostedChannels instanceof Collection) { + /** + * A collection of crossposted channels + * Order as received from the API, not as they appear in the message content + * @type {Collection} + */ + this.crosspostedChannels = new Collection(crosspostedChannels); + } else { + this.crosspostedChannels = new Collection(); + const channelTypes = Object.keys(ChannelTypes); + for (const d of crosspostedChannels) { + const type = channelTypes[d.type]; + this.crosspostedChannels.set(d.id, { + channelID: d.id, + guildID: d.guild_id, + type: type ? type.toLowerCase() : 'unknown', + name: d.name, + }); + } + } + } else { + this.crosspostedChannels = new Collection(); + } + } + + /** + * Any members that were mentioned (only in {@link TextChannel}s) + * Order as received from the API, not as they appear in the message content + * @type {?Collection} + * @readonly + */ + get members() { + if (this._members) return this._members; + if (!this.guild) return null; + this._members = new Collection(); + this.users.forEach(user => { + const member = this.guild.member(user); + if (member) this._members.set(member.user.id, member); + }); + return this._members; + } + + /** + * Any channels that were mentioned + * Order as they appear first in the message content + * @type {Collection} + * @readonly + */ + get channels() { + if (this._channels) return this._channels; + this._channels = new Collection(); + let matches; + while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) { + const chan = this.client.channels.cache.get(matches[1]); + if (chan) this._channels.set(chan.id, chan); + } + return this._channels; + } + + /** + * Checks if a user, guild member, role, or channel is mentioned. + * Takes into account user mentions, role mentions, and @everyone/@here mentions. + * @param {UserResolvable|RoleResolvable|GuildChannelResolvable} data User/Role/Channel to check + * @param {Object} [options] Options + * @param {boolean} [options.ignoreDirect=false] - Whether to ignore direct mentions to the item + * @param {boolean} [options.ignoreRoles=false] - Whether to ignore role mentions to a guild member + * @param {boolean} [options.ignoreEveryone=false] - Whether to ignore everyone/here mentions + * @returns {boolean} + */ + has(data, { ignoreDirect = false, ignoreRoles = false, ignoreEveryone = false } = {}) { + if (!ignoreEveryone && this.everyone) return true; + const GuildMember = require('./GuildMember'); + if (!ignoreRoles && data instanceof GuildMember) { + for (const role of this.roles.values()) if (data.roles.cache.has(role.id)) return true; + } + + if (!ignoreDirect) { + const id = + this.client.users.resolveID(data) || + (this.guild && this.guild.roles.resolveID(data)) || + this.client.channels.resolveID(data); + + return this.users.has(id) || this.channels.has(id) || this.roles.has(id); + } + + return false; + } + + toJSON() { + return Util.flatten(this, { + members: true, + channels: true, + }); + } +} + +/** + * Regular expression that globally matches `@everyone` and `@here` + * @type {RegExp} + */ +MessageMentions.EVERYONE_PATTERN = /@(everyone|here)/g; + +/** + * Regular expression that globally matches user mentions like `<@81440962496172032>` + * @type {RegExp} + */ +MessageMentions.USERS_PATTERN = /<@!?(\d{17,19})>/g; + +/** + * Regular expression that globally matches role mentions like `<@&297577916114403338>` + * @type {RegExp} + */ +MessageMentions.ROLES_PATTERN = /<@&(\d{17,19})>/g; + +/** + * Regular expression that globally matches channel mentions like `<#222079895583457280>` + * @type {RegExp} + */ +MessageMentions.CHANNELS_PATTERN = /<#(\d{17,19})>/g; + +module.exports = MessageMentions; diff --git a/node_modules/discord.js/src/structures/MessageReaction.js b/node_modules/discord.js/src/structures/MessageReaction.js new file mode 100644 index 0000000..134ef5f --- /dev/null +++ b/node_modules/discord.js/src/structures/MessageReaction.js @@ -0,0 +1,136 @@ +'use strict'; + +const GuildEmoji = require('./GuildEmoji'); +const ReactionEmoji = require('./ReactionEmoji'); +const ReactionUserManager = require('../managers/ReactionUserManager'); +const Util = require('../util/Util'); + +/** + * Represents a reaction to a message. + */ +class MessageReaction { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the message reaction + * @param {Message} message The message the reaction refers to + */ + constructor(client, data, message) { + /** + * The client that instantiated this message reaction + * @name MessageReaction#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + /** + * The message that this reaction refers to + * @type {Message} + */ + this.message = message; + + /** + * A manager of the users that have given this reaction + * @type {ReactionUserManager} + */ + this.users = new ReactionUserManager(client, undefined, this); + + this._emoji = new ReactionEmoji(this, data.emoji); + + this._patch(data); + } + + _patch(data) { + // eslint-disable-next-line eqeqeq + if (this.count == undefined) { + /** + * The number of people that have given the same reaction + * @type {?number} + */ + this.count = data.count; + } + + /** + * Whether the client has given this reaction + * @type {boolean} + */ + this.me = data.me; + } + + /** + * Removes all users from this reaction. + * @returns {Promise} + */ + async remove() { + await this.client.api + .channels(this.message.channel.id) + .messages(this.message.id) + .reactions(this._emoji.identifier) + .delete(); + return this; + } + + /** + * The emoji of this reaction, either an GuildEmoji object for known custom emojis, or a ReactionEmoji + * object which has fewer properties. Whatever the prototype of the emoji, it will still have + * `name`, `id`, `identifier` and `toString()` + * @type {GuildEmoji|ReactionEmoji} + * @readonly + */ + get emoji() { + if (this._emoji instanceof GuildEmoji) return this._emoji; + // Check to see if the emoji has become known to the client + if (this._emoji.id) { + const emojis = this.message.client.emojis.cache; + if (emojis.has(this._emoji.id)) { + const emoji = emojis.get(this._emoji.id); + this._emoji = emoji; + return emoji; + } + } + return this._emoji; + } + + /** + * Whether or not this reaction is a partial + * @type {boolean} + * @readonly + */ + get partial() { + return this.count === null; + } + + /** + * Fetch this reaction. + * @returns {Promise} + */ + async fetch() { + const message = await this.message.fetch(); + const existing = message.reactions.cache.get(this.emoji.id || this.emoji.name); + // The reaction won't get set when it has been completely removed + this._patch(existing || { count: 0 }); + return this; + } + + toJSON() { + return Util.flatten(this, { emoji: 'emojiID', message: 'messageID' }); + } + + _add(user) { + if (this.partial) return; + this.users.cache.set(user.id, user); + if (!this.me || user.id !== this.message.client.user.id || this.count === 0) this.count++; + if (!this.me) this.me = user.id === this.message.client.user.id; + } + + _remove(user) { + if (this.partial) return; + this.users.cache.delete(user.id); + if (!this.me || user.id !== this.message.client.user.id) this.count--; + if (user.id === this.message.client.user.id) this.me = false; + if (this.count <= 0 && this.users.cache.size === 0) { + this.message.reactions.cache.delete(this.emoji.id || this.emoji.name); + } + } +} + +module.exports = MessageReaction; diff --git a/node_modules/discord.js/src/structures/NewsChannel.js b/node_modules/discord.js/src/structures/NewsChannel.js new file mode 100644 index 0000000..3319719 --- /dev/null +++ b/node_modules/discord.js/src/structures/NewsChannel.js @@ -0,0 +1,38 @@ +'use strict'; + +const TextChannel = require('./TextChannel'); +const { Error } = require('../errors'); + +/** + * Represents a guild news channel on Discord. + * @extends {TextChannel} + */ +class NewsChannel extends TextChannel { + _patch(data) { + super._patch(data); + + // News channels don't have a rate limit per user, remove it + this.rateLimitPerUser = undefined; + } + + /** + * Adds the target to this channel's followers. + * @param {GuildChannelResolvable} channel The channel where the webhook should be created + * @param {string} [reason] Reason for creating the webhook + * @returns {Promise} + * @example + * if (channel.type === 'news') { + * channel.addFollower('222197033908436994', 'Important announcements') + * .then(() => console.log('Added follower')) + * .catch(console.error); + * } + */ + async addFollower(channel, reason) { + const channelID = this.guild.channels.resolveID(channel); + if (!channelID) throw new Error('GUILD_CHANNEL_RESOLVE'); + await this.client.api.channels(this.id).followers.post({ data: { webhook_channel_id: channelID }, reason }); + return this; + } +} + +module.exports = NewsChannel; diff --git a/node_modules/discord.js/src/structures/PartialGroupDMChannel.js b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js new file mode 100644 index 0000000..e398f23 --- /dev/null +++ b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js @@ -0,0 +1,46 @@ +'use strict'; + +const Channel = require('./Channel'); +const { Error } = require('../errors'); + +/** + * Represents a Partial Group DM Channel on Discord. + * @extends {Channel} + */ +class PartialGroupDMChannel extends Channel { + constructor(client, data) { + super(client, data); + + /** + * The name of this Group DM Channel + * @type {string} + */ + this.name = data.name; + + /** + * The hash of the channel icon + * @type {?string} + */ + this.icon = data.icon; + } + + /** + * The URL to this channel's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + iconURL({ format, size } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size); + } + + delete() { + return Promise.reject(new Error('DELETE_GROUP_DM_CHANNEL')); + } + + fetch() { + return Promise.reject(new Error('FETCH_GROUP_DM_CHANNEL')); + } +} + +module.exports = PartialGroupDMChannel; diff --git a/node_modules/discord.js/src/structures/PermissionOverwrites.js b/node_modules/discord.js/src/structures/PermissionOverwrites.js new file mode 100644 index 0000000..bbc7cd1 --- /dev/null +++ b/node_modules/discord.js/src/structures/PermissionOverwrites.js @@ -0,0 +1,189 @@ +'use strict'; + +const Role = require('./Role'); +const { TypeError } = require('../errors'); +const Permissions = require('../util/Permissions'); +const Util = require('../util/Util'); + +/** + * Represents a permission overwrite for a role or member in a guild channel. + */ +class PermissionOverwrites { + constructor(guildChannel, data) { + /** + * The GuildChannel this overwrite is for + * @name PermissionOverwrites#channel + * @type {GuildChannel} + * @readonly + */ + Object.defineProperty(this, 'channel', { value: guildChannel }); + + if (data) this._patch(data); + } + + _patch(data) { + /** + * The ID of this overwrite, either a user ID or a role ID + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The type of a permission overwrite. It can be one of: + * * member + * * role + * @typedef {string} OverwriteType + */ + + /** + * The type of this overwrite + * @type {OverwriteType} + */ + this.type = data.type; + + /** + * The permissions that are denied for the user or role. + * @type {Readonly} + */ + this.deny = new Permissions(data.deny).freeze(); + + /** + * The permissions that are allowed for the user or role. + * @type {Readonly} + */ + this.allow = new Permissions(data.allow).freeze(); + } + + /** + * Updates this permissionOverwrites. + * @param {PermissionOverwriteOptions} options The options for the update + * @param {string} [reason] Reason for creating/editing this overwrite + * @returns {Promise} + * @example + * // Update permission overwrites + * permissionOverwrites.update({ + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) + * .catch(console.error); + */ + update(options, reason) { + const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this); + + return this.channel.client.api + .channels(this.channel.id) + .permissions[this.id].put({ + data: { id: this.id, type: this.type, allow: allow.bitfield, deny: deny.bitfield }, + reason, + }) + .then(() => this); + } + + /** + * Deletes this Permission Overwrite. + * @param {string} [reason] Reason for deleting this overwrite + * @returns {Promise} + */ + delete(reason) { + return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({ reason }).then(() => this); + } + + toJSON() { + return Util.flatten(this); + } + + /** + * An object mapping permission flags to `true` (enabled), `null` (unset) or `false` (disabled). + * ```js + * { + * 'SEND_MESSAGES': true, + * 'EMBED_LINKS': null, + * 'ATTACH_FILES': false, + * } + * ``` + * @typedef {Object} PermissionOverwriteOptions + */ + + /** + * @typedef {object} ResolvedOverwriteOptions + * @property {Permissions} allow The allowed permissions + * @property {Permissions} deny The denied permissions + */ + + /** + * Resolves bitfield permissions overwrites from an object. + * @param {PermissionOverwriteOptions} options The options for the update + * @param {Object} initialPermissions The initial permissions + * @param {PermissionResolvable} initialPermissions.allow Initial allowed permissions + * @param {PermissionResolvable} initialPermissions.deny Initial denied permissions + * @returns {ResolvedOverwriteOptions} + */ + static resolveOverwriteOptions(options, { allow, deny } = {}) { + allow = new Permissions(allow); + deny = new Permissions(deny); + + for (const [perm, value] of Object.entries(options)) { + if (value === true) { + allow.add(Permissions.FLAGS[perm]); + deny.remove(Permissions.FLAGS[perm]); + } else if (value === false) { + allow.remove(Permissions.FLAGS[perm]); + deny.add(Permissions.FLAGS[perm]); + } else if (value === null) { + allow.remove(Permissions.FLAGS[perm]); + deny.remove(Permissions.FLAGS[perm]); + } + } + + return { allow, deny }; + } + + /** + * The raw data for a permission overwrite + * @typedef {Object} RawOverwriteData + * @property {Snowflake} id The id of the overwrite + * @property {number} allow The permissions to allow + * @property {number} deny The permissions to deny + * @property {OverwriteType} type The type of this OverwriteData + */ + + /** + * Data that can be resolved into {@link RawOverwriteData} + * @typedef {PermissionOverwrites|OverwriteData} OverwriteResolvable + */ + + /** + * Data that can be used for a permission overwrite + * @typedef {Object} OverwriteData + * @property {GuildMemberResolvable|RoleResolvable} id Member or role this overwrite is for + * @property {PermissionResolvable} [allow] The permissions to allow + * @property {PermissionResolvable} [deny] The permissions to deny + * @property {OverwriteType} [type] The type of this OverwriteData + */ + + /** + * Resolves an overwrite into {@link RawOverwriteData}. + * @param {OverwriteResolvable} overwrite The overwrite-like data to resolve + * @param {Guild} guild The guild to resolve from + * @returns {RawOverwriteData} + */ + static resolve(overwrite, guild) { + if (overwrite instanceof this) return overwrite.toJSON(); + if (typeof overwrite.id === 'string' && ['role', 'member'].includes(overwrite.type)) { + return { ...overwrite, allow: Permissions.resolve(overwrite.allow), deny: Permissions.resolve(overwrite.deny) }; + } + + const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id); + if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); + const type = userOrRole instanceof Role ? 'role' : 'member'; + + return { + id: userOrRole.id, + type, + allow: Permissions.resolve(overwrite.allow), + deny: Permissions.resolve(overwrite.deny), + }; + } +} + +module.exports = PermissionOverwrites; diff --git a/node_modules/discord.js/src/structures/Presence.js b/node_modules/discord.js/src/structures/Presence.js new file mode 100644 index 0000000..2ae6b8c --- /dev/null +++ b/node_modules/discord.js/src/structures/Presence.js @@ -0,0 +1,336 @@ +'use strict'; + +const Emoji = require('./Emoji'); +const ActivityFlags = require('../util/ActivityFlags'); +const { ActivityTypes } = require('../util/Constants'); +const Util = require('../util/Util'); + +/** + * Activity sent in a message. + * @typedef {Object} MessageActivity + * @property {string} [partyID] Id of the party represented in activity + * @property {number} [type] Type of activity sent + */ + +/** + * The status of this presence: + * * **`online`** - user is online + * * **`idle`** - user is AFK + * * **`offline`** - user is offline or invisible + * * **`dnd`** - user is in Do Not Disturb + * @typedef {string} PresenceStatus + */ + +/** + * The status of this presence: + * * **`online`** - user is online + * * **`idle`** - user is AFK + * * **`dnd`** - user is in Do Not Disturb + * @typedef {string} ClientPresenceStatus + */ + +/** + * Represents a user's presence. + */ +class Presence { + /** + * @param {Client} client The instantiating client + * @param {Object} [data={}] The data for the presence + */ + constructor(client, data = {}) { + /** + * The client that instantiated this + * @name Presence#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + /** + * The user ID of this presence + * @type {Snowflake} + */ + this.userID = data.user.id; + + /** + * The guild of this presence + * @type {?Guild} + */ + this.guild = data.guild || null; + + this.patch(data); + } + + /** + * The user of this presence + * @type {?User} + * @readonly + */ + get user() { + return this.client.users.cache.get(this.userID) || null; + } + + /** + * The member of this presence + * @type {?GuildMember} + * @readonly + */ + get member() { + return this.guild.members.cache.get(this.userID) || null; + } + + patch(data) { + /** + * The status of this presence + * @type {PresenceStatus} + */ + this.status = data.status || this.status || 'offline'; + + if (data.activities) { + /** + * The activities of this presence + * @type {Activity[]} + */ + this.activities = data.activities.map(activity => new Activity(this, activity)); + } else if (data.activity || data.game) { + this.activities = [new Activity(this, data.game || data.activity)]; + } else { + this.activities = []; + } + + /** + * The devices this presence is on + * @type {?Object} + * @property {?ClientPresenceStatus} web The current presence in the web application + * @property {?ClientPresenceStatus} mobile The current presence in the mobile application + * @property {?ClientPresenceStatus} desktop The current presence in the desktop application + */ + this.clientStatus = data.client_status || null; + + return this; + } + + _clone() { + const clone = Object.assign(Object.create(this), this); + if (this.activities) clone.activities = this.activities.map(activity => activity._clone()); + return clone; + } + + /** + * Whether this presence is equal to another. + * @param {Presence} presence The presence to compare with + * @returns {boolean} + */ + equals(presence) { + return ( + this === presence || + (presence && + this.status === presence.status && + this.activities.length === presence.activities.length && + this.activities.every((activity, index) => activity.equals(presence.activities[index])) && + this.clientStatus.web === presence.clientStatus.web && + this.clientStatus.mobile === presence.clientStatus.mobile && + this.clientStatus.desktop === presence.clientStatus.desktop) + ); + } + + toJSON() { + return Util.flatten(this); + } +} + +/** + * Represents an activity that is part of a user's presence. + */ +class Activity { + constructor(presence, data) { + Object.defineProperty(this, 'presence', { value: presence }); + + /** + * The name of the activity being played + * @type {string} + */ + this.name = data.name; + + /** + * The type of the activity status + * @type {ActivityType} + */ + this.type = ActivityTypes[data.type]; + + /** + * If the activity is being streamed, a link to the stream + * @type {?string} + */ + this.url = data.url || null; + + /** + * Details about the activity + * @type {?string} + */ + this.details = data.details || null; + + /** + * State of the activity + * @type {?string} + */ + this.state = data.state || null; + + /** + * Application ID associated with this activity + * @type {?Snowflake} + */ + this.applicationID = data.application_id || null; + + /** + * Timestamps for the activity + * @type {?Object} + * @property {?Date} start When the activity started + * @property {?Date} end When the activity will end + */ + this.timestamps = data.timestamps + ? { + start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null, + end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null, + } + : null; + + /** + * Party of the activity + * @type {?Object} + * @property {?string} id ID of the party + * @property {number[]} size Size of the party as `[current, max]` + */ + this.party = data.party || null; + + /** + * Assets for rich presence + * @type {?RichPresenceAssets} + */ + this.assets = data.assets ? new RichPresenceAssets(this, data.assets) : null; + + this.syncID = data.sync_id; + + /** + * Flags that describe the activity + * @type {Readonly} + */ + this.flags = new ActivityFlags(data.flags).freeze(); + + /** + * Emoji for a custom activity + * @type {?Emoji} + */ + this.emoji = data.emoji ? new Emoji(presence.client, data.emoji) : null; + + /** + * Creation date of the activity + * @type {number} + */ + this.createdTimestamp = new Date(data.created_at).getTime(); + } + + /** + * Whether this activity is equal to another activity. + * @param {Activity} activity The activity to compare with + * @returns {boolean} + */ + equals(activity) { + return ( + this === activity || + (activity && this.name === activity.name && this.type === activity.type && this.url === activity.url) + ); + } + + /** + * The time the activity was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * When concatenated with a string, this automatically returns the activities' name instead of the Activity object. + * @returns {string} + */ + toString() { + return this.name; + } + + _clone() { + return Object.assign(Object.create(this), this); + } +} + +/** + * Assets for a rich presence + */ +class RichPresenceAssets { + constructor(activity, assets) { + Object.defineProperty(this, 'activity', { value: activity }); + + /** + * Hover text for the large image + * @type {?string} + */ + this.largeText = assets.large_text || null; + + /** + * Hover text for the small image + * @type {?string} + */ + this.smallText = assets.small_text || null; + + /** + * ID of the large image asset + * @type {?Snowflake} + */ + this.largeImage = assets.large_image || null; + + /** + * ID of the small image asset + * @type {?Snowflake} + */ + this.smallImage = assets.small_image || null; + } + + /** + * Gets the URL of the small image asset + * @param {Object} [options] Options for the image url + * @param {string} [options.format] Format of the image + * @param {number} [options.size] Size of the image + * @returns {?string} The small image URL + */ + smallImageURL({ format, size } = {}) { + if (!this.smallImage) return null; + return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, { + format, + size, + }); + } + + /** + * Gets the URL of the large image asset + * @param {Object} [options] Options for the image url + * @param {string} [options.format] Format of the image + * @param {number} [options.size] Size of the image + * @returns {?string} The large image URL + */ + largeImageURL({ format, size } = {}) { + if (!this.largeImage) return null; + if (/^spotify:/.test(this.largeImage)) { + return `https://i.scdn.co/image/${this.largeImage.slice(8)}`; + } else if (/^twitch:/.test(this.largeImage)) { + return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${this.largeImage.slice(7)}.png`; + } + return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.largeImage, { + format, + size, + }); + } +} + +exports.Presence = Presence; +exports.Activity = Activity; +exports.RichPresenceAssets = RichPresenceAssets; diff --git a/node_modules/discord.js/src/structures/ReactionCollector.js b/node_modules/discord.js/src/structures/ReactionCollector.js new file mode 100644 index 0000000..e0fa316 --- /dev/null +++ b/node_modules/discord.js/src/structures/ReactionCollector.js @@ -0,0 +1,188 @@ +'use strict'; + +const Collector = require('./interfaces/Collector'); +const Collection = require('../util/Collection'); +const { Events } = require('../util/Constants'); + +/** + * @typedef {CollectorOptions} ReactionCollectorOptions + * @property {number} max The maximum total amount of reactions to collect + * @property {number} maxEmojis The maximum number of emojis to collect + * @property {number} maxUsers The maximum number of users to react + */ + +/** + * Collects reactions on messages. + * Will automatically stop if the message (`'messageDelete'`), + * channel (`'channelDelete'`), or guild (`'guildDelete'`) are deleted. + * @extends {Collector} + */ +class ReactionCollector extends Collector { + /** + * @param {Message} message The message upon which to collect reactions + * @param {CollectorFilter} filter The filter to apply to this collector + * @param {ReactionCollectorOptions} [options={}] The options to apply to this collector + */ + constructor(message, filter, options = {}) { + super(message.client, filter, options); + + /** + * The message upon which to collect reactions + * @type {Message} + */ + this.message = message; + + /** + * The users which have reacted to this message + * @type {Collection} + */ + this.users = new Collection(); + + /** + * The total number of reactions collected + * @type {number} + */ + this.total = 0; + + this.empty = this.empty.bind(this); + this._handleChannelDeletion = this._handleChannelDeletion.bind(this); + this._handleGuildDeletion = this._handleGuildDeletion.bind(this); + this._handleMessageDeletion = this._handleMessageDeletion.bind(this); + + this.client.incrementMaxListeners(); + this.client.on(Events.MESSAGE_REACTION_ADD, this.handleCollect); + this.client.on(Events.MESSAGE_REACTION_REMOVE, this.handleDispose); + this.client.on(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty); + this.client.on(Events.MESSAGE_DELETE, this._handleMessageDeletion); + this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion); + + this.once('end', () => { + this.client.removeListener(Events.MESSAGE_REACTION_ADD, this.handleCollect); + this.client.removeListener(Events.MESSAGE_REACTION_REMOVE, this.handleDispose); + this.client.removeListener(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty); + this.client.removeListener(Events.MESSAGE_DELETE, this._handleMessageDeletion); + this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion); + this.client.decrementMaxListeners(); + }); + + this.on('collect', (reaction, user) => { + this.total++; + this.users.set(user.id, user); + }); + + this.on('remove', (reaction, user) => { + this.total--; + if (!this.collected.some(r => r.users.cache.has(user.id))) this.users.delete(user.id); + }); + } + + /** + * Handles an incoming reaction for possible collection. + * @param {MessageReaction} reaction The reaction to possibly collect + * @returns {?Snowflake|string} + * @private + */ + collect(reaction) { + /** + * Emitted whenever a reaction is collected. + * @event ReactionCollector#collect + * @param {MessageReaction} reaction The reaction that was collected + * @param {User} user The user that added the reaction + */ + if (reaction.message.id !== this.message.id) return null; + return ReactionCollector.key(reaction); + } + + /** + * Handles a reaction deletion for possible disposal. + * @param {MessageReaction} reaction The reaction to possibly dispose of + * @param {User} user The user that removed the reaction + * @returns {?Snowflake|string} + */ + dispose(reaction, user) { + /** + * Emitted when the reaction had all the users removed and the `dispose` option is set to true. + * @event ReactionCollector#dispose + * @param {MessageReaction} reaction The reaction that was disposed of + * @param {User} user The user that removed the reaction + */ + if (reaction.message.id !== this.message.id) return null; + + /** + * Emitted when the reaction had one user removed and the `dispose` option is set to true. + * @event ReactionCollector#remove + * @param {MessageReaction} reaction The reaction that was removed + * @param {User} user The user that removed the reaction + */ + if (this.collected.has(ReactionCollector.key(reaction)) && this.users.has(user.id)) { + this.emit('remove', reaction, user); + } + return reaction.count ? null : ReactionCollector.key(reaction); + } + + /** + * Empties this reaction collector. + */ + empty() { + this.total = 0; + this.collected.clear(); + this.users.clear(); + this.checkEnd(); + } + + endReason() { + if (this.options.max && this.total >= this.options.max) return 'limit'; + if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit'; + if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit'; + return null; + } + + /** + * Handles checking if the message has been deleted, and if so, stops the collector with the reason 'messageDelete'. + * @private + * @param {Message} message The message that was deleted + * @returns {void} + */ + _handleMessageDeletion(message) { + if (message.id === this.message.id) { + this.stop('messageDelete'); + } + } + + /** + * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'. + * @private + * @param {GuildChannel} channel The channel that was deleted + * @returns {void} + */ + _handleChannelDeletion(channel) { + if (channel.id === this.message.channel.id) { + this.stop('channelDelete'); + } + } + + /** + * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'. + * @private + * @param {Guild} guild The guild that was deleted + * @returns {void} + */ + _handleGuildDeletion(guild) { + if (this.message.guild && guild.id === this.message.guild.id) { + this.stop('guildDelete'); + } + } + + /** + * Gets the collector key for a reaction. + * @param {MessageReaction} reaction The message reaction to get the key for + * @returns {Snowflake|string} + */ + static key(reaction) { + return reaction.emoji.id || reaction.emoji.name; + } +} + +module.exports = ReactionCollector; diff --git a/node_modules/discord.js/src/structures/ReactionEmoji.js b/node_modules/discord.js/src/structures/ReactionEmoji.js new file mode 100644 index 0000000..5c4bc13 --- /dev/null +++ b/node_modules/discord.js/src/structures/ReactionEmoji.js @@ -0,0 +1,31 @@ +'use strict'; + +const Emoji = require('./Emoji'); +const Util = require('../util/Util'); + +/** + * Represents a limited emoji set used for both custom and unicode emojis. Custom emojis + * will use this class opposed to the Emoji class when the client doesn't know enough + * information about them. + * @extends {Emoji} + */ +class ReactionEmoji extends Emoji { + constructor(reaction, emoji) { + super(reaction.message.client, emoji); + /** + * The message reaction this emoji refers to + * @type {MessageReaction} + */ + this.reaction = reaction; + } + + toJSON() { + return Util.flatten(this, { identifier: true }); + } + + valueOf() { + return this.id; + } +} + +module.exports = ReactionEmoji; diff --git a/node_modules/discord.js/src/structures/Role.js b/node_modules/discord.js/src/structures/Role.js new file mode 100644 index 0000000..94ee2f0 --- /dev/null +++ b/node_modules/discord.js/src/structures/Role.js @@ -0,0 +1,403 @@ +'use strict'; + +const Base = require('./Base'); +const { Error, TypeError } = require('../errors'); +const Permissions = require('../util/Permissions'); +const Snowflake = require('../util/Snowflake'); +const Util = require('../util/Util'); + +/** + * Represents a role on Discord. + * @extends {Base} + */ +class Role extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the role + * @param {Guild} guild The guild the role is part of + */ + constructor(client, data, guild) { + super(client); + + /** + * The guild that the role belongs to + * @type {Guild} + */ + this.guild = guild; + + if (data) this._patch(data); + } + + _patch(data) { + /** + * The ID of the role (unique to the guild it is part of) + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The name of the role + * @type {string} + */ + this.name = data.name; + + /** + * The base 10 color of the role + * @type {number} + */ + this.color = data.color; + + /** + * If true, users that are part of this role will appear in a separate category in the users list + * @type {boolean} + */ + this.hoist = data.hoist; + + /** + * The raw position of the role from the API + * @type {number} + */ + this.rawPosition = data.position; + + /** + * The permissions of the role + * @type {Readonly} + */ + this.permissions = new Permissions(data.permissions).freeze(); + + /** + * Whether or not the role is managed by an external service + * @type {boolean} + */ + this.managed = data.managed; + + /** + * Whether or not the role can be mentioned by anyone + * @type {boolean} + */ + this.mentionable = data.mentionable; + + /** + * Whether the role has been deleted + * @type {boolean} + */ + this.deleted = false; + } + + /** + * The timestamp the role was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the role was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The hexadecimal version of the role color, with a leading hashtag + * @type {string} + * @readonly + */ + get hexColor() { + return `#${this.color.toString(16).padStart(6, '0')}`; + } + + /** + * The cached guild members that have this role + * @type {Collection} + * @readonly + */ + get members() { + return this.guild.members.cache.filter(m => m.roles.cache.has(this.id)); + } + + /** + * Whether the role is editable by the client user + * @type {boolean} + * @readonly + */ + get editable() { + if (this.managed) return false; + const clientMember = this.guild.member(this.client.user); + if (!clientMember.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return false; + return clientMember.roles.highest.comparePositionTo(this) > 0; + } + + /** + * The position of the role in the role manager + * @type {number} + * @readonly + */ + get position() { + const sorted = this.guild._sortedRoles(); + return sorted.array().indexOf(sorted.get(this.id)); + } + + /** + * Compares this role's position to another role's. + * @param {RoleResolvable} role Role to compare to this one + * @returns {number} Negative number if this role's position is lower (other role's is higher), + * positive number if this one is higher (other's is lower), 0 if equal + */ + comparePositionTo(role) { + role = this.guild.roles.resolve(role); + if (!role) throw new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'); + return this.constructor.comparePositions(this, role); + } + + /** + * The data for a role. + * @typedef {Object} RoleData + * @property {string} [name] The name of the role + * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number + * @property {boolean} [hoist] Whether or not the role should be hoisted + * @property {number} [position] The position of the role + * @property {PermissionResolvable} [permissions] The permissions of the role + * @property {boolean} [mentionable] Whether or not the role should be mentionable + */ + + /** + * Edits the role. + * @param {RoleData} data The new data for the role + * @param {string} [reason] Reason for editing this role + * @returns {Promise} + * @example + * // Edit a role + * role.edit({ name: 'new role' }) + * .then(updated => console.log(`Edited role name to ${updated.name}`)) + * .catch(console.error); + */ + async edit(data, reason) { + if (typeof data.permissions !== 'undefined') data.permissions = Permissions.resolve(data.permissions); + else data.permissions = this.permissions.bitfield; + if (typeof data.position !== 'undefined') { + await Util.setPosition( + this, + data.position, + false, + this.guild._sortedRoles(), + this.client.api.guilds(this.guild.id).roles, + reason, + ).then(updatedRoles => { + this.client.actions.GuildRolesPositionUpdate.handle({ + guild_id: this.guild.id, + roles: updatedRoles, + }); + }); + } + return this.client.api.guilds[this.guild.id].roles[this.id] + .patch({ + data: { + name: data.name || this.name, + color: data.color !== null ? Util.resolveColor(data.color || this.color) : null, + hoist: typeof data.hoist !== 'undefined' ? data.hoist : this.hoist, + permissions: data.permissions, + mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable, + }, + reason, + }) + .then(role => { + const clone = this._clone(); + clone._patch(role); + return clone; + }); + } + + /** + * Returns `channel.permissionsFor(role)`. Returns permissions for a role in a guild channel, + * taking into account permission overwrites. + * @param {ChannelResolvable} channel The guild channel to use as context + * @returns {Readonly} + */ + permissionsIn(channel) { + channel = this.guild.channels.resolve(channel); + if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE'); + return channel.rolePermissions(this); + } + + /** + * Sets a new name for the role. + * @param {string} name The new name of the role + * @param {string} [reason] Reason for changing the role's name + * @returns {Promise} + * @example + * // Set the name of the role + * role.setName('new role') + * .then(updated => console.log(`Updated role name to ${updated.name}`)) + * .catch(console.error); + */ + setName(name, reason) { + return this.edit({ name }, reason); + } + + /** + * Sets a new color for the role. + * @param {ColorResolvable} color The color of the role + * @param {string} [reason] Reason for changing the role's color + * @returns {Promise} + * @example + * // Set the color of a role + * role.setColor('#FF0000') + * .then(updated => console.log(`Set color of role to ${updated.color}`)) + * .catch(console.error); + */ + setColor(color, reason) { + return this.edit({ color }, reason); + } + + /** + * Sets whether or not the role should be hoisted. + * @param {boolean} hoist Whether or not to hoist the role + * @param {string} [reason] Reason for setting whether or not the role should be hoisted + * @returns {Promise} + * @example + * // Set the hoist of the role + * role.setHoist(true) + * .then(updated => console.log(`Role hoisted: ${updated.hoist}`)) + * .catch(console.error); + */ + setHoist(hoist, reason) { + return this.edit({ hoist }, reason); + } + + /** + * Sets the permissions of the role. + * @param {PermissionResolvable} permissions The permissions of the role + * @param {string} [reason] Reason for changing the role's permissions + * @returns {Promise} + * @example + * // Set the permissions of the role + * role.setPermissions(['KICK_MEMBERS', 'BAN_MEMBERS']) + * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`)) + * .catch(console.error); + * @example + * // Remove all permissions from a role + * role.setPermissions(0) + * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`)) + * .catch(console.error); + */ + setPermissions(permissions, reason) { + return this.edit({ permissions }, reason); + } + + /** + * Sets whether this role is mentionable. + * @param {boolean} mentionable Whether this role should be mentionable + * @param {string} [reason] Reason for setting whether or not this role should be mentionable + * @returns {Promise} + * @example + * // Make the role mentionable + * role.setMentionable(true) + * .then(updated => console.log(`Role updated ${updated.name}`)) + * .catch(console.error); + */ + setMentionable(mentionable, reason) { + return this.edit({ mentionable }, reason); + } + + /** + * Sets the position of the role. + * @param {number} position The position of the role + * @param {Object} [options] Options for setting position + * @param {boolean} [options.relative=false] Change the position relative to its current value + * @param {string} [options.reason] Reason for changing the position + * @returns {Promise} + * @example + * // Set the position of the role + * role.setPosition(1) + * .then(updated => console.log(`Role position: ${updated.position}`)) + * .catch(console.error); + */ + setPosition(position, { relative, reason } = {}) { + return Util.setPosition( + this, + position, + relative, + this.guild._sortedRoles(), + this.client.api.guilds(this.guild.id).roles, + reason, + ).then(updatedRoles => { + this.client.actions.GuildRolesPositionUpdate.handle({ + guild_id: this.guild.id, + roles: updatedRoles, + }); + return this; + }); + } + + /** + * Deletes the role. + * @param {string} [reason] Reason for deleting this role + * @returns {Promise} + * @example + * // Delete a role + * role.delete('The role needed to go') + * .then(deleted => console.log(`Deleted role ${deleted.name}`)) + * .catch(console.error); + */ + delete(reason) { + return this.client.api.guilds[this.guild.id].roles[this.id].delete({ reason }).then(() => { + this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: this.id }); + return this; + }); + } + + /** + * Whether this role equals another role. It compares all properties, so for most operations + * it is advisable to just compare `role.id === role2.id` as it is much faster and is often + * what most users need. + * @param {Role} role Role to compare with + * @returns {boolean} + */ + equals(role) { + return ( + role && + this.id === role.id && + this.name === role.name && + this.color === role.color && + this.hoist === role.hoist && + this.position === role.position && + this.permissions.bitfield === role.permissions.bitfield && + this.managed === role.managed + ); + } + + /** + * When concatenated with a string, this automatically returns the role's mention instead of the Role object. + * @returns {string} + * @example + * // Logs: Role: <@&123456789012345678> + * console.log(`Role: ${role}`); + */ + toString() { + if (this.id === this.guild.id) return '@everyone'; + return `<@&${this.id}>`; + } + + toJSON() { + return super.toJSON({ createdTimestamp: true }); + } + + /** + * Compares the positions of two roles. + * @param {Role} role1 First role to compare + * @param {Role} role2 Second role to compare + * @returns {number} Negative number if the first role's position is lower (second role's is higher), + * positive number if the first's is higher (second's is lower), 0 if equal + */ + static comparePositions(role1, role2) { + if (role1.position === role2.position) return role2.id - role1.id; + return role1.position - role2.position; + } +} + +module.exports = Role; diff --git a/node_modules/discord.js/src/structures/StoreChannel.js b/node_modules/discord.js/src/structures/StoreChannel.js new file mode 100644 index 0000000..1c518a7 --- /dev/null +++ b/node_modules/discord.js/src/structures/StoreChannel.js @@ -0,0 +1,32 @@ +'use strict'; + +const GuildChannel = require('./GuildChannel'); + +/** + * Represents a guild store channel on Discord. + * @extends {GuildChannel} + */ +class StoreChannel extends GuildChannel { + /** + * @param {*} guild The guild the store channel is part of + * @param {*} data The data for the store channel + */ + constructor(guild, data) { + super(guild, data); + + /** + * If the guild considers this channel NSFW + * @type {boolean} + * @readonly + */ + this.nsfw = Boolean(data.nsfw); + } + + _patch(data) { + super._patch(data); + + if (typeof data.nsfw !== 'undefined') this.nsfw = Boolean(data.nsfw); + } +} + +module.exports = StoreChannel; diff --git a/node_modules/discord.js/src/structures/Team.js b/node_modules/discord.js/src/structures/Team.js new file mode 100644 index 0000000..a28c5a2 --- /dev/null +++ b/node_modules/discord.js/src/structures/Team.js @@ -0,0 +1,109 @@ +'use strict'; + +const Base = require('./Base'); +const TeamMember = require('./TeamMember'); +const Collection = require('../util/Collection'); +const Snowflake = require('../util/Snowflake'); + +/** + * Represents a Client OAuth2 Application Team. + * @extends {Base} + */ +class Team extends Base { + constructor(client, data) { + super(client); + this._patch(data); + } + + _patch(data) { + /** + * The ID of the Team + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The name of the Team + * @type {string} + */ + this.name = data.name; + + /** + * The Team's icon hash + * @type {?string} + */ + this.icon = data.icon || null; + + /** + * The Team's owner id + * @type {?string} + */ + this.ownerID = data.owner_user_id || null; + + /** + * The Team's members + * @type {Collection} + */ + this.members = new Collection(); + + for (const memberData of data.members) { + const member = new TeamMember(this, memberData); + this.members.set(member.id, member); + } + } + + /** + * The owner of this team + * @type {?TeamMember} + * @readonly + */ + get owner() { + return this.members.get(this.ownerID) || null; + } + + /** + * The timestamp the team was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the team was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * A link to the teams's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} URL to the icon + */ + iconURL({ format, size } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.TeamIcon(this.id, this.icon, { format, size }); + } + + /** + * When concatenated with a string, this automatically returns the Team's name instead of the + * Team object. + * @returns {string} + * @example + * // Logs: Team name: My Team + * console.log(`Team name: ${team}`); + */ + toString() { + return this.name; + } + + toJSON() { + return super.toJSON({ createdTimestamp: true }); + } +} + +module.exports = Team; diff --git a/node_modules/discord.js/src/structures/TeamMember.js b/node_modules/discord.js/src/structures/TeamMember.js new file mode 100644 index 0000000..ba7ecd2 --- /dev/null +++ b/node_modules/discord.js/src/structures/TeamMember.js @@ -0,0 +1,65 @@ +'use strict'; + +const Base = require('./Base'); +const { MembershipStates } = require('../util/Constants'); + +/** + * Represents a Client OAuth2 Application Team Member. + * @extends {Base} + */ +class TeamMember extends Base { + constructor(team, data) { + super(team.client); + + /** + * The Team this member is part of + * @type {Team} + */ + this.team = team; + + this._patch(data); + } + + _patch(data) { + /** + * The permissions this Team Member has with regard to the team + * @type {string[]} + */ + this.permissions = data.permissions; + + /** + * The permissions this Team Member has with regard to the team + * @type {MembershipStates} + */ + this.membershipState = MembershipStates[data.membership_state]; + + /** + * The user for this Team Member + * @type {User} + */ + this.user = this.client.users.add(data.user); + } + + /** + * The ID of the Team Member + * @type {Snowflake} + * @readonly + */ + get id() { + return this.user.id; + } + + /** + * When concatenated with a string, this automatically returns the team members's mention instead of the + * TeamMember object. + * @returns {string} + * @example + * // Logs: Team Member's mention: <@123456789012345678> + * console.log(`Team Member's mention: ${teamMember}`); + */ + toString() { + return this.user.toString(); + } +} + +module.exports = TeamMember; diff --git a/node_modules/discord.js/src/structures/TextChannel.js b/node_modules/discord.js/src/structures/TextChannel.js new file mode 100644 index 0000000..b92e0c7 --- /dev/null +++ b/node_modules/discord.js/src/structures/TextChannel.js @@ -0,0 +1,153 @@ +'use strict'; + +const GuildChannel = require('./GuildChannel'); +const Webhook = require('./Webhook'); +const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const MessageManager = require('../managers/MessageManager'); +const Collection = require('../util/Collection'); +const DataResolver = require('../util/DataResolver'); + +/** + * Represents a guild text channel on Discord. + * @extends {GuildChannel} + * @implements {TextBasedChannel} + */ +class TextChannel extends GuildChannel { + /** + * @param {Guild} guild The guild the text channel is part of + * @param {Object} data The data for the text channel + */ + constructor(guild, data) { + super(guild, data); + /** + * A manager of the messages sent to this channel + * @type {MessageManager} + */ + this.messages = new MessageManager(this); + + /** + * If the guild considers this channel NSFW + * @type {boolean} + * @readonly + */ + this.nsfw = Boolean(data.nsfw); + this._typing = new Map(); + } + + _patch(data) { + super._patch(data); + + /** + * The topic of the text channel + * @type {?string} + */ + this.topic = data.topic; + + if (typeof data.nsfw !== 'undefined') this.nsfw = Boolean(data.nsfw); + + /** + * The ID of the last message sent in this channel, if one was sent + * @type {?Snowflake} + */ + this.lastMessageID = data.last_message_id; + + /** + * The ratelimit per user for this channel in seconds + * @type {number} + */ + this.rateLimitPerUser = data.rate_limit_per_user || 0; + + /** + * The timestamp when the last pinned message was pinned, if there was one + * @type {?number} + */ + this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null; + + if (data.messages) for (const message of data.messages) this.messages.add(message); + } + + /** + * Sets the rate limit per user for this channel. + * @param {number} rateLimitPerUser The new ratelimit in seconds + * @param {string} [reason] Reason for changing the channel's ratelimits + * @returns {Promise} + */ + setRateLimitPerUser(rateLimitPerUser, reason) { + return this.edit({ rateLimitPerUser }, reason); + } + + /** + * Sets whether this channel is flagged as NSFW. + * @param {boolean} nsfw Whether the channel should be considered NSFW + * @param {string} [reason] Reason for changing the channel's NSFW flag + * @returns {Promise} + */ + setNSFW(nsfw, reason) { + return this.edit({ nsfw }, reason); + } + + /** + * Fetches all webhooks for the channel. + * @returns {Promise>} + * @example + * // Fetch webhooks + * channel.fetchWebhooks() + * .then(hooks => console.log(`This channel has ${hooks.size} hooks`)) + * .catch(console.error); + */ + fetchWebhooks() { + return this.client.api.channels[this.id].webhooks.get().then(data => { + const hooks = new Collection(); + for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook)); + return hooks; + }); + } + + /** + * Creates a webhook for the channel. + * @param {string} name The name of the webhook + * @param {Object} [options] Options for creating the webhook + * @param {BufferResolvable|Base64Resolvable} [options.avatar] Avatar for the webhook + * @param {string} [options.reason] Reason for creating the webhook + * @returns {Promise} webhook The created webhook + * @example + * // Create a webhook for the current channel + * channel.createWebhook('Snek', { + * avatar: 'https://i.imgur.com/mI8XcpG.jpg', + * reason: 'Needed a cool new Webhook' + * }) + * .then(console.log) + * .catch(console.error) + */ + async createWebhook(name, { avatar, reason } = {}) { + if (typeof avatar === 'string' && !avatar.startsWith('data:')) { + avatar = await DataResolver.resolveImage(avatar); + } + return this.client.api.channels[this.id].webhooks + .post({ + data: { + name, + avatar, + }, + reason, + }) + .then(data => new Webhook(this.client, data)); + } + + // These are here only for documentation purposes - they are implemented by TextBasedChannel + /* eslint-disable no-empty-function */ + get lastMessage() {} + get lastPinAt() {} + send() {} + startTyping() {} + stopTyping() {} + get typing() {} + get typingCount() {} + createMessageCollector() {} + awaitMessages() {} + bulkDelete() {} +} + +TextBasedChannel.applyToClass(TextChannel, true); + +module.exports = TextChannel; diff --git a/node_modules/discord.js/src/structures/User.js b/node_modules/discord.js/src/structures/User.js new file mode 100644 index 0000000..d2766f1 --- /dev/null +++ b/node_modules/discord.js/src/structures/User.js @@ -0,0 +1,343 @@ +'use strict'; + +const Base = require('./Base'); +const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const { Error } = require('../errors'); +const Snowflake = require('../util/Snowflake'); +const UserFlags = require('../util/UserFlags'); + +let Structures; + +/** + * Represents a user on Discord. + * @implements {TextBasedChannel} + * @extends {Base} + */ +class User extends Base { + /** + * @param {Client} client The instantiating client + * @param {Object} data The data for the user + */ + constructor(client, data) { + super(client); + + /** + * The ID of the user + * @type {Snowflake} + */ + this.id = data.id; + + this.system = null; + this.locale = null; + this.flags = null; + + this._patch(data); + } + + _patch(data) { + if ('username' in data) { + /** + * The username of the user + * @type {?string} + */ + this.username = data.username; + } else if (typeof this.username !== 'string') { + this.username = null; + } + + if ('bot' in data || typeof this.bot !== 'boolean') { + /** + * Whether or not the user is a bot + * @type {boolean} + */ + this.bot = Boolean(data.bot); + } + + if ('discriminator' in data) { + /** + * A discriminator based on username for the user + * @type {?string} + */ + this.discriminator = data.discriminator; + } else if (typeof this.discriminator !== 'string') { + this.discriminator = null; + } + + if ('avatar' in data) { + /** + * The ID of the user's avatar + * @type {?string} + */ + this.avatar = data.avatar; + } else if (typeof this.avatar !== 'string') { + this.avatar = null; + } + + if ('system' in data) { + /** + * Whether the user is an Official Discord System user (part of the urgent message system) + * @type {?boolean} + */ + this.system = Boolean(data.system); + } + + if ('locale' in data) { + /** + * The locale of the user's client (ISO 639-1) + * @type {?string} + */ + this.locale = data.locale; + } + + if ('public_flags' in data) { + /** + * The flags for this user + * @type {?UserFlags} + */ + this.flags = new UserFlags(data.public_flags); + } + + /** + * The ID of the last message sent by the user, if one was sent + * @type {?Snowflake} + */ + this.lastMessageID = null; + + /** + * The ID of the channel for the last message sent by the user, if one was sent + * @type {?Snowflake} + */ + this.lastMessageChannelID = null; + } + + /** + * Whether this User is a partial + * @type {boolean} + * @readonly + */ + get partial() { + return typeof this.username !== 'string'; + } + + /** + * The timestamp the user was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the user was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The Message object of the last message sent by the user, if one was sent + * @type {?Message} + * @readonly + */ + get lastMessage() { + const channel = this.client.channels.cache.get(this.lastMessageChannelID); + return (channel && channel.messages.cache.get(this.lastMessageID)) || null; + } + + /** + * The presence of this user + * @type {Presence} + * @readonly + */ + get presence() { + for (const guild of this.client.guilds.cache.values()) { + if (guild.presences.cache.has(this.id)) return guild.presences.cache.get(this.id); + } + if (!Structures) Structures = require('../util/Structures'); + const Presence = Structures.get('Presence'); + return new Presence(this.client, { user: { id: this.id } }); + } + + /** + * A link to the user's avatar. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + avatarURL({ format, size, dynamic } = {}) { + if (!this.avatar) return null; + return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size, dynamic); + } + + /** + * A link to the user's default avatar + * @type {string} + * @readonly + */ + get defaultAvatarURL() { + return this.client.rest.cdn.DefaultAvatar(this.discriminator % 5); + } + + /** + * A link to the user's avatar if they have one. + * Otherwise a link to their default avatar will be returned. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {string} + */ + displayAvatarURL(options) { + return this.avatarURL(options) || this.defaultAvatarURL; + } + + /** + * The Discord "tag" (e.g. `hydrabolt#0001`) for this user + * @type {?string} + * @readonly + */ + get tag() { + return typeof this.username === 'string' ? `${this.username}#${this.discriminator}` : null; + } + + /** + * Checks whether the user is typing in a channel. + * @param {ChannelResolvable} channel The channel to check in + * @returns {boolean} + */ + typingIn(channel) { + channel = this.client.channels.resolve(channel); + return channel._typing.has(this.id); + } + + /** + * Gets the time that the user started typing. + * @param {ChannelResolvable} channel The channel to get the time in + * @returns {?Date} + */ + typingSinceIn(channel) { + channel = this.client.channels.resolve(channel); + return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null; + } + + /** + * Gets the amount of time the user has been typing in a channel for (in milliseconds), or -1 if they're not typing. + * @param {ChannelResolvable} channel The channel to get the time in + * @returns {number} + */ + typingDurationIn(channel) { + channel = this.client.channels.resolve(channel); + return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1; + } + + /** + * The DM between the client's user and this user + * @type {?DMChannel} + * @readonly + */ + get dmChannel() { + return this.client.channels.cache.find(c => c.type === 'dm' && c.recipient.id === this.id) || null; + } + + /** + * Creates a DM channel between the client and the user. + * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @returns {Promise} + */ + async createDM(force = false) { + if (!force) { + const { dmChannel } = this; + if (dmChannel && !dmChannel.partial) return dmChannel; + } + + const data = await this.client.api.users(this.client.user.id).channels.post({ + data: { + recipient_id: this.id, + }, + }); + return this.client.actions.ChannelCreate.handle(data).channel; + } + + /** + * Deletes a DM channel (if one exists) between the client and the user. Resolves with the channel if successful. + * @returns {Promise} + */ + async deleteDM() { + const { dmChannel } = this; + if (!dmChannel) throw new Error('USER_NO_DMCHANNEL'); + const data = await this.client.api.channels(dmChannel.id).delete(); + return this.client.actions.ChannelDelete.handle(data).channel; + } + + /** + * Checks if the user is equal to another. It compares ID, username, discriminator, avatar, and bot flags. + * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. + * @param {User} user User to compare with + * @returns {boolean} + */ + equals(user) { + let equal = + user && + this.id === user.id && + this.username === user.username && + this.discriminator === user.discriminator && + this.avatar === user.avatar; + + return equal; + } + + /** + * Fetches this user's flags. + * @param {boolean} [force=false] Whether to skip the cache check and request the AP + * @returns {Promise} + */ + async fetchFlags(force = false) { + if (this.flags && !force) return this.flags; + const data = await this.client.api.users(this.id).get(); + this._patch(data); + return this.flags; + } + + /** + * Fetches this user. + * @param {boolean} [force=false] Whether to skip the cache check and request the AP + * @returns {Promise} + */ + fetch(force = false) { + return this.client.users.fetch(this.id, true, force); + } + + /** + * When concatenated with a string, this automatically returns the user's mention instead of the User object. + * @returns {string} + * @example + * // Logs: Hello from <@123456789012345678>! + * console.log(`Hello from ${user}!`); + */ + toString() { + return `<@${this.id}>`; + } + + toJSON(...props) { + const json = super.toJSON( + { + createdTimestamp: true, + defaultAvatarURL: true, + tag: true, + lastMessage: false, + lastMessageID: false, + }, + ...props, + ); + json.avatarURL = this.avatarURL(); + json.displayAvatarURL = this.displayAvatarURL(); + return json; + } + + // These are here only for documentation purposes - they are implemented by TextBasedChannel + /* eslint-disable no-empty-function */ + send() {} +} + +TextBasedChannel.applyToClass(User); + +module.exports = User; diff --git a/node_modules/discord.js/src/structures/VoiceChannel.js b/node_modules/discord.js/src/structures/VoiceChannel.js new file mode 100644 index 0000000..2b9eb9e --- /dev/null +++ b/node_modules/discord.js/src/structures/VoiceChannel.js @@ -0,0 +1,150 @@ +'use strict'; + +const GuildChannel = require('./GuildChannel'); +const { Error } = require('../errors'); +const Collection = require('../util/Collection'); +const { browser } = require('../util/Constants'); +const Permissions = require('../util/Permissions'); + +/** + * Represents a guild voice channel on Discord. + * @extends {GuildChannel} + */ +class VoiceChannel extends GuildChannel { + _patch(data) { + super._patch(data); + /** + * The bitrate of this voice channel + * @type {number} + */ + this.bitrate = data.bitrate; + + /** + * The maximum amount of users allowed in this channel - 0 means unlimited. + * @type {number} + */ + this.userLimit = data.user_limit; + } + + /** + * The members in this voice channel + * @type {Collection} + * @readonly + */ + get members() { + const coll = new Collection(); + for (const state of this.guild.voiceStates.cache.values()) { + if (state.channelID === this.id && state.member) { + coll.set(state.id, state.member); + } + } + return coll; + } + + /** + * Checks if the voice channel is full + * @type {boolean} + * @readonly + */ + get full() { + return this.userLimit > 0 && this.members.size >= this.userLimit; + } + + /** + * Whether the channel is deletable by the client user + * @type {boolean} + * @readonly + */ + get deletable() { + return super.deletable && this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false); + } + + /** + * Whether the channel is editable by the client user + * @type {boolean} + * @readonly + */ + get editable() { + return this.manageable && this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false); + } + + /** + * Whether the channel is joinable by the client user + * @type {boolean} + * @readonly + */ + get joinable() { + if (browser) return false; + if (!this.viewable) return false; + if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) return false; + if (this.full && !this.permissionsFor(this.client.user).has(Permissions.FLAGS.MOVE_MEMBERS, false)) return false; + return true; + } + + /** + * Checks if the client has permission to send audio to the voice channel + * @type {boolean} + * @readonly + */ + get speakable() { + return this.permissionsFor(this.client.user).has(Permissions.FLAGS.SPEAK, false); + } + + /** + * Sets the bitrate of the channel. + * @param {number} bitrate The new bitrate + * @param {string} [reason] Reason for changing the channel's bitrate + * @returns {Promise} + * @example + * // Set the bitrate of a voice channel + * voiceChannel.setBitrate(48000) + * .then(vc => console.log(`Set bitrate to ${vc.bitrate}bps for ${vc.name}`)) + * .catch(console.error); + */ + setBitrate(bitrate, reason) { + return this.edit({ bitrate }, reason); + } + + /** + * Sets the user limit of the channel. + * @param {number} userLimit The new user limit + * @param {string} [reason] Reason for changing the user limit + * @returns {Promise} + * @example + * // Set the user limit of a voice channel + * voiceChannel.setUserLimit(42) + * .then(vc => console.log(`Set user limit to ${vc.userLimit} for ${vc.name}`)) + * .catch(console.error); + */ + setUserLimit(userLimit, reason) { + return this.edit({ userLimit }, reason); + } + + /** + * Attempts to join this voice channel. + * @returns {Promise} + * @example + * // Join a voice channel + * voiceChannel.join() + * .then(connection => console.log('Connected!')) + * .catch(console.error); + */ + join() { + if (browser) return Promise.reject(new Error('VOICE_NO_BROWSER')); + return this.client.voice.joinChannel(this); + } + + /** + * Leaves this voice channel. + * @example + * // Leave a voice channel + * voiceChannel.leave(); + */ + leave() { + if (browser) return; + const connection = this.client.voice.connections.get(this.guild.id); + if (connection && connection.channel.id === this.id) connection.disconnect(); + } +} + +module.exports = VoiceChannel; diff --git a/node_modules/discord.js/src/structures/VoiceRegion.js b/node_modules/discord.js/src/structures/VoiceRegion.js new file mode 100644 index 0000000..9626195 --- /dev/null +++ b/node_modules/discord.js/src/structures/VoiceRegion.js @@ -0,0 +1,52 @@ +'use strict'; + +const Util = require('../util/Util'); + +/** + * Represents a Discord voice region for guilds. + */ +class VoiceRegion { + constructor(data) { + /** + * The ID of the region + * @type {string} + */ + this.id = data.id; + + /** + * Name of the region + * @type {string} + */ + this.name = data.name; + + /** + * Whether the region is VIP-only + * @type {boolean} + */ + this.vip = data.vip; + + /** + * Whether the region is deprecated + * @type {boolean} + */ + this.deprecated = data.deprecated; + + /** + * Whether the region is optimal + * @type {boolean} + */ + this.optimal = data.optimal; + + /** + * Whether the region is custom + * @type {boolean} + */ + this.custom = data.custom; + } + + toJSON() { + return Util.flatten(this); + } +} + +module.exports = VoiceRegion; diff --git a/node_modules/discord.js/src/structures/VoiceState.js b/node_modules/discord.js/src/structures/VoiceState.js new file mode 100644 index 0000000..731c7ef --- /dev/null +++ b/node_modules/discord.js/src/structures/VoiceState.js @@ -0,0 +1,213 @@ +'use strict'; + +const Base = require('./Base'); +const { Error, TypeError } = require('../errors'); +const { browser } = require('../util/Constants'); + +/** + * Represents the voice state for a Guild Member. + */ +class VoiceState extends Base { + /** + * @param {Guild} guild The guild the voice state is part of + * @param {Object} data The data for the voice state + */ + constructor(guild, data) { + super(guild.client); + /** + * The guild of this voice state + * @type {Guild} + */ + this.guild = guild; + /** + * The ID of the member of this voice state + * @type {Snowflake} + */ + this.id = data.user_id; + this._patch(data); + } + + _patch(data) { + /** + * Whether this member is deafened server-wide + * @type {?boolean} + */ + this.serverDeaf = 'deaf' in data ? data.deaf : null; + /** + * Whether this member is muted server-wide + * @type {?boolean} + */ + this.serverMute = 'mute' in data ? data.mute : null; + /** + * Whether this member is self-deafened + * @type {?boolean} + */ + this.selfDeaf = 'self_deaf' in data ? data.self_deaf : null; + /** + * Whether this member is self-muted + * @type {?boolean} + */ + this.selfMute = 'self_mute' in data ? data.self_mute : null; + /** + * Whether this member's camera is enabled + * @type {?boolean} + */ + this.selfVideo = 'self_video' in data ? data.self_video : null; + /** + * The session ID of this member's connection + * @type {?string} + */ + this.sessionID = 'session_id' in data ? data.session_id : null; + /** + * Whether this member is streaming using "Go Live" + * @type {boolean} + */ + this.streaming = data.self_stream || false; + /** + * The ID of the voice channel that this member is in + * @type {?Snowflake} + */ + this.channelID = data.channel_id || null; + return this; + } + + /** + * The member that this voice state belongs to + * @type {?GuildMember} + * @readonly + */ + get member() { + return this.guild.members.cache.get(this.id) || null; + } + + /** + * The channel that the member is connected to + * @type {?VoiceChannel} + * @readonly + */ + get channel() { + return this.guild.channels.cache.get(this.channelID) || null; + } + + /** + * If this is a voice state of the client user, then this will refer to the active VoiceConnection for this guild + * @type {?VoiceConnection} + * @readonly + */ + get connection() { + if (browser || this.id !== this.client.user.id) return null; + return this.client.voice.connections.get(this.guild.id) || null; + } + + /** + * Whether this member is either self-deafened or server-deafened + * @type {?boolean} + * @readonly + */ + get deaf() { + return this.serverDeaf || this.selfDeaf; + } + + /** + * Whether this member is either self-muted or server-muted + * @type {?boolean} + * @readonly + */ + get mute() { + return this.serverMute || this.selfMute; + } + + /** + * Whether this member is currently speaking. A boolean if the information is available (aka + * the bot is connected to any voice channel in the guild), otherwise this is null + * @type {?boolean} + * @readonly + */ + get speaking() { + return this.channel && this.channel.connection ? Boolean(this.channel.connection._speaking.get(this.id)) : null; + } + + /** + * Mutes/unmutes the member of this voice state. + * @param {boolean} mute Whether or not the member should be muted + * @param {string} [reason] Reason for muting or unmuting + * @returns {Promise} + */ + setMute(mute, reason) { + return this.member ? this.member.edit({ mute }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + } + + /** + * Deafens/undeafens the member of this voice state. + * @param {boolean} deaf Whether or not the member should be deafened + * @param {string} [reason] Reason for deafening or undeafening + * @returns {Promise} + */ + setDeaf(deaf, reason) { + return this.member ? this.member.edit({ deaf }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + } + + /** + * Kicks the member from the voice channel. + * @param {string} [reason] Reason for kicking member from the channel + * @returns {Promise} + */ + kick(reason) { + return this.setChannel(null, reason); + } + + /** + * Moves the member to a different channel, or disconnects them from the one they're in. + * @param {ChannelResolvable|null} [channel] Channel to move the member to, or `null` if you want to disconnect them + * from voice. + * @param {string} [reason] Reason for moving member to another channel or disconnecting + * @returns {Promise} + */ + setChannel(channel, reason) { + return this.member + ? this.member.edit({ channel }, reason) + : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + } + + /** + * Self-mutes/unmutes the bot for this voice state. + * @param {boolean} mute Whether or not the bot should be self-muted + * @returns {Promise} true if the voice state was successfully updated, otherwise false + */ + async setSelfMute(mute) { + if (this.id !== this.client.user.id) throw new Error('VOICE_STATE_NOT_OWN'); + if (typeof mute !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'mute'); + if (!this.connection) return false; + this.selfMute = mute; + await this.connection.sendVoiceStateUpdate(); + return true; + } + + /** + * Self-deafens/undeafens the bot for this voice state. + * @param {boolean} deaf Whether or not the bot should be self-deafened + * @returns {Promise} true if the voice state was successfully updated, otherwise false + */ + async setSelfDeaf(deaf) { + if (this.id !== this.client.user.id) return new Error('VOICE_STATE_NOT_OWN'); + if (typeof deaf !== 'boolean') return new TypeError('VOICE_STATE_INVALID_TYPE', 'deaf'); + if (!this.connection) return false; + this.selfDeaf = deaf; + await this.connection.sendVoiceStateUpdate(); + return true; + } + + toJSON() { + return super.toJSON({ + id: true, + serverDeaf: true, + serverMute: true, + selfDeaf: true, + selfMute: true, + sessionID: true, + channelID: 'channel', + }); + } +} + +module.exports = VoiceState; diff --git a/node_modules/discord.js/src/structures/Webhook.js b/node_modules/discord.js/src/structures/Webhook.js new file mode 100644 index 0000000..d0cf7c6 --- /dev/null +++ b/node_modules/discord.js/src/structures/Webhook.js @@ -0,0 +1,273 @@ +'use strict'; + +const APIMessage = require('./APIMessage'); +const Channel = require('./Channel'); +const { WebhookTypes } = require('../util/Constants'); +const DataResolver = require('../util/DataResolver'); +const Snowflake = require('../util/Snowflake'); + +/** + * Represents a webhook. + */ +class Webhook { + constructor(client, data) { + /** + * The client that instantiated the webhook + * @name Webhook#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + if (data) this._patch(data); + } + + _patch(data) { + /** + * The name of the webhook + * @type {string} + */ + this.name = data.name; + + /** + * The token for the webhook + * @name Webhook#token + * @type {?string} + */ + Object.defineProperty(this, 'token', { value: data.token || null, writable: true, configurable: true }); + + /** + * The avatar for the webhook + * @type {?string} + */ + this.avatar = data.avatar; + + /** + * The ID of the webhook + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The type of the webhook + * @type {WebhookTypes} + */ + this.type = WebhookTypes[data.type]; + + /** + * The guild the webhook belongs to + * @type {Snowflake} + */ + this.guildID = data.guild_id; + + /** + * The channel the webhook belongs to + * @type {Snowflake} + */ + this.channelID = data.channel_id; + + if (data.user) { + /** + * The owner of the webhook + * @type {?User|Object} + */ + this.owner = this.client.users ? this.client.users.cache.get(data.user.id) : data.user; + } else { + this.owner = null; + } + } + + /** + * Options that can be passed into send. + * @typedef {Object} WebhookMessageOptions + * @property {string} [username=this.name] Username override for the message + * @property {string} [avatarURL] Avatar URL override for the message + * @property {boolean} [tts=false] Whether or not the message should be spoken aloud + * @property {string} [nonce=''] The nonce for the message + * @property {Object[]} [embeds] An array of embeds for the message + * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content + * (see [here](https://discord.com/developers/docs/resources/channel#embed-object) for more details) + * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or + * everyone/here mentions should be sanitized to prevent unexpected mentions + * @property {FileOptions[]|string[]} [files] Files to send with the message + * @property {string|boolean} [code] Language for optional codeblock formatting to apply + * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if + * it exceeds the character limit. If an object is provided, these are the options for splitting the message. + */ + + /** + * Sends a message with this webhook. + * @param {StringResolvable|APIMessage} [content=''] The content to send + * @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide + * @returns {Promise} + * @example + * // Send a basic message + * webhook.send('hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + * @example + * // Send a remote file + * webhook.send({ + * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] + * }) + * .then(console.log) + * .catch(console.error); + * @example + * // Send a local file + * webhook.send({ + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg' + * }] + * }) + * .then(console.log) + * .catch(console.error); + * @example + * // Send an embed with a local image inside + * webhook.send('This is an embed', { + * embeds: [{ + * thumbnail: { + * url: 'attachment://file.jpg' + * } + * }], + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg' + * }] + * }) + * .then(console.log) + * .catch(console.error); + */ + async send(content, options) { + let apiMessage; + + if (content instanceof APIMessage) { + apiMessage = content.resolveData(); + } else { + apiMessage = APIMessage.create(this, content, options).resolveData(); + if (Array.isArray(apiMessage.data.content)) { + return Promise.all(apiMessage.split().map(this.send.bind(this))); + } + } + + const { data, files } = await apiMessage.resolveFiles(); + return this.client.api + .webhooks(this.id, this.token) + .post({ + data, + files, + query: { wait: true }, + auth: false, + }) + .then(d => { + const channel = this.client.channels ? this.client.channels.cache.get(d.channel_id) : undefined; + if (!channel) return d; + return channel.messages.add(d, false); + }); + } + + /** + * Sends a raw slack message with this webhook. + * @param {Object} body The raw body to send + * @returns {Promise} + * @example + * // Send a slack message + * webhook.sendSlackMessage({ + * 'username': 'Wumpus', + * 'attachments': [{ + * 'pretext': 'this looks pretty cool', + * 'color': '#F0F', + * 'footer_icon': 'http://snek.s3.amazonaws.com/topSnek.png', + * 'footer': 'Powered by sneks', + * 'ts': Date.now() / 1000 + * }] + * }).catch(console.error); + */ + sendSlackMessage(body) { + return this.client.api + .webhooks(this.id, this.token) + .slack.post({ + query: { wait: true }, + auth: false, + data: body, + }) + .then(data => data.toString() === 'ok'); + } + + /** + * Edits the webhook. + * @param {Object} options Options + * @param {string} [options.name=this.name] New name for this webhook + * @param {BufferResolvable} [options.avatar] New avatar for this webhook + * @param {ChannelResolvable} [options.channel] New channel for this webhook + * @param {string} [reason] Reason for editing this webhook + * @returns {Promise} + */ + async edit({ name = this.name, avatar, channel }, reason) { + if (avatar && typeof avatar === 'string' && !avatar.startsWith('data:')) { + avatar = await DataResolver.resolveImage(avatar); + } + if (channel) channel = channel instanceof Channel ? channel.id : channel; + const data = await this.client.api.webhooks(this.id, channel ? undefined : this.token).patch({ + data: { name, avatar, channel_id: channel }, + reason, + }); + + this.name = data.name; + this.avatar = data.avatar; + this.channelID = data.channel_id; + return this; + } + + /** + * Deletes the webhook. + * @param {string} [reason] Reason for deleting this webhook + * @returns {Promise} + */ + delete(reason) { + return this.client.api.webhooks(this.id, this.token).delete({ reason }); + } + /** + * The timestamp the webhook was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the webhook was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The url of this webhook + * @type {string} + * @readonly + */ + get url() { + return this.client.options.http.api + this.client.api.webhooks(this.id, this.token); + } + + /** + * A link to the webhook's avatar. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + avatarURL({ format, size } = {}) { + if (!this.avatar) return null; + return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size); + } + + static applyToClass(structure) { + for (const prop of ['send', 'sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt', 'url']) { + Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop)); + } + } +} + +module.exports = Webhook; diff --git a/node_modules/discord.js/src/structures/interfaces/Application.js b/node_modules/discord.js/src/structures/interfaces/Application.js new file mode 100644 index 0000000..9781bfa --- /dev/null +++ b/node_modules/discord.js/src/structures/interfaces/Application.js @@ -0,0 +1,125 @@ +'use strict'; + +const { ClientApplicationAssetTypes, Endpoints } = require('../../util/Constants'); +const Snowflake = require('../../util/Snowflake'); +const Base = require('../Base'); + +const AssetTypes = Object.keys(ClientApplicationAssetTypes); + +/** + * Represents an OAuth2 Application. + * @abstract + */ +class Application extends Base { + constructor(client, data) { + super(client); + this._patch(data); + } + + _patch(data) { + /** + * The ID of the app + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The name of the app + * @type {string} + */ + this.name = data.name; + + /** + * The app's description + * @type {string} + */ + this.description = data.description; + + /** + * The app's icon hash + * @type {string} + */ + this.icon = data.icon; + } + + /** + * The timestamp the app was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the app was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * A link to the application's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} URL to the icon + */ + iconURL({ format, size } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.AppIcon(this.id, this.icon, { format, size }); + } + + /** + * A link to this application's cover image. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} URL to the cover image + */ + coverImage({ format, size } = {}) { + if (!this.cover) return null; + return Endpoints.CDN(this.client.options.http.cdn).AppIcon(this.id, this.cover, { format, size }); + } + + /** + * Asset data. + * @typedef {Object} ApplicationAsset + * @property {Snowflake} id The asset ID + * @property {string} name The asset name + * @property {string} type The asset type + */ + + /** + * Gets the clients rich presence assets. + * @returns {Promise>} + */ + fetchAssets() { + return this.client.api.oauth2 + .applications(this.id) + .assets.get() + .then(assets => + assets.map(a => ({ + id: a.id, + name: a.name, + type: AssetTypes[a.type - 1], + })), + ); + } + + /** + * When concatenated with a string, this automatically returns the application's name instead of the + * Oauth2Application object. + * @returns {string} + * @example + * // Logs: Application name: My App + * console.log(`Application name: ${application}`); + */ + toString() { + return this.name; + } + + toJSON() { + return super.toJSON({ createdTimestamp: true }); + } +} + +module.exports = Application; diff --git a/node_modules/discord.js/src/structures/interfaces/Collector.js b/node_modules/discord.js/src/structures/interfaces/Collector.js new file mode 100644 index 0000000..969b3d2 --- /dev/null +++ b/node_modules/discord.js/src/structures/interfaces/Collector.js @@ -0,0 +1,281 @@ +'use strict'; + +const EventEmitter = require('events'); +const Collection = require('../../util/Collection'); +const Util = require('../../util/Util'); + +/** + * Filter to be applied to the collector. + * @typedef {Function} CollectorFilter + * @param {...*} args Any arguments received by the listener + * @param {Collection} collection The items collected by this collector + * @returns {boolean|Promise} + */ + +/** + * Options to be applied to the collector. + * @typedef {Object} CollectorOptions + * @property {number} [time] How long to run the collector for in milliseconds + * @property {number} [idle] How long to stop the collector after inactivity in milliseconds + * @property {boolean} [dispose=false] Whether to dispose data when it's deleted + */ + +/** + * Abstract class for defining a new Collector. + * @abstract + */ +class Collector extends EventEmitter { + constructor(client, filter, options = {}) { + super(); + + /** + * The client that instantiated this Collector + * @name Collector#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The filter applied to this collector + * @type {CollectorFilter} + */ + this.filter = filter; + + /** + * The options of this collector + * @type {CollectorOptions} + */ + this.options = options; + + /** + * The items collected by this collector + * @type {Collection} + */ + this.collected = new Collection(); + + /** + * Whether this collector has finished collecting + * @type {boolean} + */ + this.ended = false; + + /** + * Timeout for cleanup + * @type {?Timeout} + * @private + */ + this._timeout = null; + + /** + * Timeout for cleanup due to inactivity + * @type {?Timeout} + * @private + */ + this._idletimeout = null; + + this.handleCollect = this.handleCollect.bind(this); + this.handleDispose = this.handleDispose.bind(this); + + if (options.time) this._timeout = this.client.setTimeout(() => this.stop('time'), options.time); + if (options.idle) this._idletimeout = this.client.setTimeout(() => this.stop('idle'), options.idle); + } + + /** + * Call this to handle an event as a collectable element. Accepts any event data as parameters. + * @param {...*} args The arguments emitted by the listener + * @emits Collector#collect + */ + async handleCollect(...args) { + const collect = this.collect(...args); + + if (collect && (await this.filter(...args, this.collected))) { + this.collected.set(collect, args[0]); + + /** + * Emitted whenever an element is collected. + * @event Collector#collect + * @param {...*} args The arguments emitted by the listener + */ + this.emit('collect', ...args); + + if (this._idletimeout) { + this.client.clearTimeout(this._idletimeout); + this._idletimeout = this.client.setTimeout(() => this.stop('idle'), this.options.idle); + } + } + this.checkEnd(); + } + + /** + * Call this to remove an element from the collection. Accepts any event data as parameters. + * @param {...*} args The arguments emitted by the listener + * @emits Collector#dispose + */ + handleDispose(...args) { + if (!this.options.dispose) return; + + const dispose = this.dispose(...args); + if (!dispose || !this.filter(...args) || !this.collected.has(dispose)) return; + this.collected.delete(dispose); + + /** + * Emitted whenever an element is disposed of. + * @event Collector#dispose + * @param {...*} args The arguments emitted by the listener + */ + this.emit('dispose', ...args); + this.checkEnd(); + } + + /** + * Returns a promise that resolves with the next collected element; + * rejects with collected elements if the collector finishes without receiving a next element + * @type {Promise} + * @readonly + */ + get next() { + return new Promise((resolve, reject) => { + if (this.ended) { + reject(this.collected); + return; + } + + const cleanup = () => { + this.removeListener('collect', onCollect); + this.removeListener('end', onEnd); + }; + + const onCollect = item => { + cleanup(); + resolve(item); + }; + + const onEnd = () => { + cleanup(); + reject(this.collected); // eslint-disable-line prefer-promise-reject-errors + }; + + this.on('collect', onCollect); + this.on('end', onEnd); + }); + } + + /** + * Stops this collector and emits the `end` event. + * @param {string} [reason='user'] The reason this collector is ending + * @emits Collector#end + */ + stop(reason = 'user') { + if (this.ended) return; + + if (this._timeout) { + this.client.clearTimeout(this._timeout); + this._timeout = null; + } + if (this._idletimeout) { + this.client.clearTimeout(this._idletimeout); + this._idletimeout = null; + } + this.ended = true; + + /** + * Emitted when the collector is finished collecting. + * @event Collector#end + * @param {Collection} collected The elements collected by the collector + * @param {string} reason The reason the collector ended + */ + this.emit('end', this.collected, reason); + } + + /** + * Resets the collectors timeout and idle timer. + * @param {Object} [options] Options + * @param {number} [options.time] How long to run the collector for in milliseconds + * @param {number} [options.idle] How long to stop the collector after inactivity in milliseconds + */ + resetTimer({ time, idle } = {}) { + if (this._timeout) { + this.client.clearTimeout(this._timeout); + this._timeout = this.client.setTimeout(() => this.stop('time'), time || this.options.time); + } + if (this._idletimeout) { + this.client.clearTimeout(this._idletimeout); + this._idletimeout = this.client.setTimeout(() => this.stop('idle'), idle || this.options.idle); + } + } + + /** + * Checks whether the collector should end, and if so, ends it. + */ + checkEnd() { + const reason = this.endReason(); + if (reason) this.stop(reason); + } + + /** + * Allows collectors to be consumed with for-await-of loops + * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of} + */ + async *[Symbol.asyncIterator]() { + const queue = []; + const onCollect = item => queue.push(item); + this.on('collect', onCollect); + + try { + while (queue.length || !this.ended) { + if (queue.length) { + yield queue.shift(); + } else { + // eslint-disable-next-line no-await-in-loop + await new Promise(resolve => { + const tick = () => { + this.removeListener('collect', tick); + this.removeListener('end', tick); + return resolve(); + }; + this.on('collect', tick); + this.on('end', tick); + }); + } + } + } finally { + this.removeListener('collect', onCollect); + } + } + + toJSON() { + return Util.flatten(this); + } + + /* eslint-disable no-empty-function, valid-jsdoc */ + /** + * Handles incoming events from the `handleCollect` function. Returns null if the event should not + * be collected, or returns an object describing the data that should be stored. + * @see Collector#handleCollect + * @param {...*} args Any args the event listener emits + * @returns {?{key, value}} Data to insert into collection, if any + * @abstract + */ + collect() {} + + /** + * Handles incoming events from the `handleDispose`. Returns null if the event should not + * be disposed, or returns the key that should be removed. + * @see Collector#handleDispose + * @param {...*} args Any args the event listener emits + * @returns {?*} Key to remove from the collection, if any + * @abstract + */ + dispose() {} + + /** + * The reason this collector has ended or will end with. + * @returns {?string} Reason to end the collector, if any + * @abstract + */ + endReason() {} + /* eslint-enable no-empty-function, valid-jsdoc */ +} + +module.exports = Collector; diff --git a/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js new file mode 100644 index 0000000..f5269e9 --- /dev/null +++ b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -0,0 +1,393 @@ +'use strict'; + +/* eslint-disable import/order */ +const MessageCollector = require('../MessageCollector'); +const APIMessage = require('../APIMessage'); +const Snowflake = require('../../util/Snowflake'); +const Collection = require('../../util/Collection'); +const { RangeError, TypeError } = require('../../errors'); + +/** + * Interface for classes that have text-channel-like features. + * @interface + */ +class TextBasedChannel { + constructor() { + /** + * A manager of the messages sent to this channel + * @type {MessageManager} + */ + this.messages = new MessageManager(this); + + /** + * The ID of the last message in the channel, if one was sent + * @type {?Snowflake} + */ + this.lastMessageID = null; + + /** + * The timestamp when the last pinned message was pinned, if there was one + * @type {?number} + */ + this.lastPinTimestamp = null; + } + + /** + * The Message object of the last message in the channel, if one was sent + * @type {?Message} + * @readonly + */ + get lastMessage() { + return this.messages.cache.get(this.lastMessageID) || null; + } + + /** + * The date when the last pinned message was pinned, if there was one + * @type {?Date} + * @readonly + */ + get lastPinAt() { + return this.lastPinTimestamp ? new Date(this.lastPinTimestamp) : null; + } + + /** + * Options provided when sending or editing a message. + * @typedef {Object} MessageOptions + * @property {boolean} [tts=false] Whether or not the message should be spoken aloud + * @property {string} [nonce=''] The nonce for the message + * @property {string} [content=''] The content for the message + * @property {MessageEmbed|Object} [embed] An embed for the message + * (see [here](https://discord.com/developers/docs/resources/channel#embed-object) for more details) + * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content + * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or + * everyone/here mentions should be sanitized to prevent unexpected mentions + * @property {FileOptions[]|BufferResolvable[]} [files] Files to send with the message + * @property {string|boolean} [code] Language for optional codeblock formatting to apply + * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if + * it exceeds the character limit. If an object is provided, these are the options for splitting the message + * @property {UserResolvable} [reply] User to reply to (prefixes the message with a mention, except in DMs) + */ + + /** + * Options provided to control parsing of mentions by Discord + * @typedef {Object} MessageMentionOptions + * @property {MessageMentionTypes[]} [parse] Types of mentions to be parsed + * @property {Snowflake[]} [users] Snowflakes of Users to be parsed as mentions + * @property {Snowflake[]} [roles] Snowflakes of Roles to be parsed as mentions + */ + + /** + * Types of mentions to enable in MessageMentionOptions. + * - `roles` + * - `users` + * - `everyone` + * @typedef {string} MessageMentionTypes + */ + + /** + * The type of mentions to disable. + * - `none` + * - `all` + * - `everyone` + * @typedef {string} DisableMentionType + */ + + /** + * @typedef {Object} FileOptions + * @property {BufferResolvable} attachment File to attach + * @property {string} [name='file.jpg'] Filename of the attachment + */ + + /** + * Options for splitting a message. + * @typedef {Object} SplitOptions + * @property {number} [maxLength=2000] Maximum character length per message piece + * @property {string} [char='\n'] Character to split the message with + * @property {string} [prepend=''] Text to prepend to every piece except the first + * @property {string} [append=''] Text to append to every piece except the last + */ + + /** + * Sends a message to this channel. + * @param {StringResolvable|APIMessage} [content=''] The content to send + * @param {MessageOptions|MessageAdditions} [options={}] The options to provide + * @returns {Promise} + * @example + * // Send a basic message + * channel.send('hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + * @example + * // Send a remote file + * channel.send({ + * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] + * }) + * .then(console.log) + * .catch(console.error); + * @example + * // Send a local file + * channel.send({ + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg' + * }] + * }) + * .then(console.log) + * .catch(console.error); + * @example + * // Send an embed with a local image inside + * channel.send('This is an embed', { + * embed: { + * thumbnail: { + * url: 'attachment://file.jpg' + * } + * }, + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg' + * }] + * }) + * .then(console.log) + * .catch(console.error); + */ + async send(content, options) { + const User = require('../User'); + const GuildMember = require('../GuildMember'); + + if (this instanceof User || this instanceof GuildMember) { + return this.createDM().then(dm => dm.send(content, options)); + } + + let apiMessage; + + if (content instanceof APIMessage) { + apiMessage = content.resolveData(); + } else { + apiMessage = APIMessage.create(this, content, options).resolveData(); + if (Array.isArray(apiMessage.data.content)) { + return Promise.all(apiMessage.split().map(this.send.bind(this))); + } + } + + const { data, files } = await apiMessage.resolveFiles(); + return this.client.api.channels[this.id].messages + .post({ data, files }) + .then(d => this.client.actions.MessageCreate.handle(d).message); + } + + /** + * Starts a typing indicator in the channel. + * @param {number} [count=1] The number of times startTyping should be considered to have been called + * @returns {Promise} Resolves once the bot stops typing gracefully, or rejects when an error occurs + * @example + * // Start typing in a channel, or increase the typing count by one + * channel.startTyping(); + * @example + * // Start typing in a channel with a typing count of five, or set it to five + * channel.startTyping(5); + */ + startTyping(count) { + if (typeof count !== 'undefined' && count < 1) throw new RangeError('TYPING_COUNT'); + if (this.client.user._typing.has(this.id)) { + const entry = this.client.user._typing.get(this.id); + entry.count = count || entry.count + 1; + return entry.promise; + } + + const entry = {}; + entry.promise = new Promise((resolve, reject) => { + const endpoint = this.client.api.channels[this.id].typing; + Object.assign(entry, { + count: count || 1, + interval: this.client.setInterval(() => { + endpoint.post().catch(error => { + this.client.clearInterval(entry.interval); + this.client.user._typing.delete(this.id); + reject(error); + }); + }, 9000), + resolve, + }); + endpoint.post().catch(error => { + this.client.clearInterval(entry.interval); + this.client.user._typing.delete(this.id); + reject(error); + }); + this.client.user._typing.set(this.id, entry); + }); + return entry.promise; + } + + /** + * Stops the typing indicator in the channel. + * The indicator will only stop if this is called as many times as startTyping(). + * It can take a few seconds for the client user to stop typing. + * @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop + * @example + * // Reduce the typing count by one and stop typing if it reached 0 + * channel.stopTyping(); + * @example + * // Force typing to fully stop regardless of typing count + * channel.stopTyping(true); + */ + stopTyping(force = false) { + if (this.client.user._typing.has(this.id)) { + const entry = this.client.user._typing.get(this.id); + entry.count--; + if (entry.count <= 0 || force) { + this.client.clearInterval(entry.interval); + this.client.user._typing.delete(this.id); + entry.resolve(); + } + } + } + + /** + * Whether or not the typing indicator is being shown in the channel + * @type {boolean} + * @readonly + */ + get typing() { + return this.client.user._typing.has(this.id); + } + + /** + * Number of times `startTyping` has been called + * @type {number} + * @readonly + */ + get typingCount() { + if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; + return 0; + } + + /** + * Creates a Message Collector. + * @param {CollectorFilter} filter The filter to create the collector with + * @param {MessageCollectorOptions} [options={}] The options to pass to the collector + * @returns {MessageCollector} + * @example + * // Create a message collector + * const filter = m => m.content.includes('discord'); + * const collector = channel.createMessageCollector(filter, { time: 15000 }); + * collector.on('collect', m => console.log(`Collected ${m.content}`)); + * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + */ + createMessageCollector(filter, options = {}) { + return new MessageCollector(this, filter, options); + } + + /** + * An object containing the same properties as CollectorOptions, but a few more: + * @typedef {MessageCollectorOptions} AwaitMessagesOptions + * @property {string[]} [errors] Stop/end reasons that cause the promise to reject + */ + + /** + * Similar to createMessageCollector but in promise form. + * Resolves with a collection of messages that pass the specified filter. + * @param {CollectorFilter} filter The filter function to use + * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector + * @returns {Promise>} + * @example + * // Await !vote messages + * const filter = m => m.content.startsWith('!vote'); + * // Errors: ['time'] treats ending because of the time limit as an error + * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] }) + * .then(collected => console.log(collected.size)) + * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`)); + */ + awaitMessages(filter, options = {}) { + return new Promise((resolve, reject) => { + const collector = this.createMessageCollector(filter, options); + collector.once('end', (collection, reason) => { + if (options.errors && options.errors.includes(reason)) { + reject(collection); + } else { + resolve(collection); + } + }); + }); + } + + /** + * Bulk deletes given messages that are newer than two weeks. + * @param {Collection|MessageResolvable[]|number} messages + * Messages or number of messages to delete + * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically + * @returns {Promise>} Deleted messages + * @example + * // Bulk delete messages + * channel.bulkDelete(5) + * .then(messages => console.log(`Bulk deleted ${messages.size} messages`)) + * .catch(console.error); + */ + async bulkDelete(messages, filterOld = false) { + if (Array.isArray(messages) || messages instanceof Collection) { + let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m); + if (filterOld) { + messageIDs = messageIDs.filter(id => Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000); + } + if (messageIDs.length === 0) return new Collection(); + if (messageIDs.length === 1) { + await this.client.api.channels(this.id).messages(messageIDs[0]).delete(); + const message = this.client.actions.MessageDelete.getMessage( + { + message_id: messageIDs[0], + }, + this, + ); + return message ? new Collection([[message.id, message]]) : new Collection(); + } + await this.client.api.channels[this.id].messages['bulk-delete'].post({ data: { messages: messageIDs } }); + return messageIDs.reduce( + (col, id) => + col.set( + id, + this.client.actions.MessageDeleteBulk.getMessage( + { + message_id: id, + }, + this, + ), + ), + new Collection(), + ); + } + if (!isNaN(messages)) { + const msgs = await this.messages.fetch({ limit: messages }); + return this.bulkDelete(msgs, filterOld); + } + throw new TypeError('MESSAGE_BULK_DELETE_TYPE'); + } + + static applyToClass(structure, full = false, ignore = []) { + const props = ['send']; + if (full) { + props.push( + 'lastMessage', + 'lastPinAt', + 'bulkDelete', + 'startTyping', + 'stopTyping', + 'typing', + 'typingCount', + 'createMessageCollector', + 'awaitMessages', + ); + } + for (const prop of props) { + if (ignore.includes(prop)) continue; + Object.defineProperty( + structure.prototype, + prop, + Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop), + ); + } + } +} + +module.exports = TextBasedChannel; + +// Fixes Circular +const MessageManager = require('../../managers/MessageManager'); diff --git a/node_modules/discord.js/src/util/ActivityFlags.js b/node_modules/discord.js/src/util/ActivityFlags.js new file mode 100644 index 0000000..237ec12 --- /dev/null +++ b/node_modules/discord.js/src/util/ActivityFlags.js @@ -0,0 +1,38 @@ +'use strict'; + +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with an {@link Activity#flags} bitfield. + * @extends {BitField} + */ +class ActivityFlags extends BitField {} + +/** + * @name ActivityFlags + * @kind constructor + * @memberof ActivityFlags + * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Numeric activity flags. All available properties: + * * `INSTANCE` + * * `JOIN` + * * `SPECTATE` + * * `JOIN_REQUEST` + * * `SYNC` + * * `PLAY` + * @type {Object} + * @see {@link https://discord.com/developers/docs/topics/gateway#activity-object-activity-flags} + */ +ActivityFlags.FLAGS = { + INSTANCE: 1 << 0, + JOIN: 1 << 1, + SPECTATE: 1 << 2, + JOIN_REQUEST: 1 << 3, + SYNC: 1 << 4, + PLAY: 1 << 5, +}; + +module.exports = ActivityFlags; diff --git a/node_modules/discord.js/src/util/BitField.js b/node_modules/discord.js/src/util/BitField.js new file mode 100644 index 0000000..4d03aa6 --- /dev/null +++ b/node_modules/discord.js/src/util/BitField.js @@ -0,0 +1,164 @@ +'use strict'; + +const { RangeError } = require('../errors'); + +/** + * Data structure that makes it easy to interact with a bitfield. + */ +class BitField { + /** + * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + */ + constructor(bits) { + /** + * Bitfield of the packed bits + * @type {number} + */ + this.bitfield = this.constructor.resolve(bits); + } + + /** + * Checks whether the bitfield has a bit, or any of multiple bits. + * @param {BitFieldResolvable} bit Bit(s) to check for + * @returns {boolean} + */ + any(bit) { + return (this.bitfield & this.constructor.resolve(bit)) !== 0; + } + + /** + * Checks if this bitfield equals another + * @param {BitFieldResolvable} bit Bit(s) to check for + * @returns {boolean} + */ + equals(bit) { + return this.bitfield === this.constructor.resolve(bit); + } + + /** + * Checks whether the bitfield has a bit, or multiple bits. + * @param {BitFieldResolvable} bit Bit(s) to check for + * @returns {boolean} + */ + has(bit) { + if (Array.isArray(bit)) return bit.every(p => this.has(p)); + bit = this.constructor.resolve(bit); + return (this.bitfield & bit) === bit; + } + + /** + * Gets all given bits that are missing from the bitfield. + * @param {BitFieldResolvable} bits Bit(s) to check for + * @param {...*} hasParams Additional parameters for the has method, if any + * @returns {string[]} + */ + missing(bits, ...hasParams) { + if (!Array.isArray(bits)) bits = new this.constructor(bits).toArray(false); + return bits.filter(p => !this.has(p, ...hasParams)); + } + + /** + * Freezes these bits, making them immutable. + * @returns {Readonly} These bits + */ + freeze() { + return Object.freeze(this); + } + + /** + * Adds bits to these ones. + * @param {...BitFieldResolvable} [bits] Bits to add + * @returns {BitField} These bits or new BitField if the instance is frozen. + */ + add(...bits) { + let total = 0; + for (const bit of bits) { + total |= this.constructor.resolve(bit); + } + if (Object.isFrozen(this)) return new this.constructor(this.bitfield | total); + this.bitfield |= total; + return this; + } + + /** + * Removes bits from these. + * @param {...BitFieldResolvable} [bits] Bits to remove + * @returns {BitField} These bits or new BitField if the instance is frozen. + */ + remove(...bits) { + let total = 0; + for (const bit of bits) { + total |= this.constructor.resolve(bit); + } + if (Object.isFrozen(this)) return new this.constructor(this.bitfield & ~total); + this.bitfield &= ~total; + return this; + } + + /** + * Gets an object mapping field names to a {@link boolean} indicating whether the + * bit is available. + * @param {...*} hasParams Additional parameters for the has method, if any + * @returns {Object} + */ + serialize(...hasParams) { + const serialized = {}; + for (const [flag, bit] of Object.entries(this.constructor.FLAGS)) serialized[flag] = this.has(bit, ...hasParams); + return serialized; + } + + /** + * Gets an {@link Array} of bitfield names based on the bits available. + * @param {...*} hasParams Additional parameters for the has method, if any + * @returns {string[]} + */ + toArray(...hasParams) { + return Object.keys(this.constructor.FLAGS).filter(bit => this.has(bit, ...hasParams)); + } + + toJSON() { + return this.bitfield; + } + + valueOf() { + return this.bitfield; + } + + *[Symbol.iterator]() { + yield* this.toArray(); + } + + /** + * Data that can be resolved to give a bitfield. This can be: + * * A string (see {@link BitField.FLAGS}) + * * A bit number + * * An instance of BitField + * * An Array of BitFieldResolvable + * @typedef {string|number|BitField|BitFieldResolvable[]} BitFieldResolvable + */ + + /** + * Resolves bitfields to their numeric form. + * @param {BitFieldResolvable} [bit=0] - bit(s) to resolve + * @returns {number} + */ + static resolve(bit = 0) { + if (typeof bit === 'number' && bit >= 0) return bit; + if (bit instanceof BitField) return bit.bitfield; + if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0); + if (typeof bit === 'string' && typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit]; + const error = new RangeError('BITFIELD_INVALID'); + error.bit = bit; + throw error; + } +} + +/** + * Numeric bitfield flags. + * Defined in extension classes + * @type {Object} + * @abstract + */ +BitField.FLAGS = {}; + +module.exports = BitField; diff --git a/node_modules/discord.js/src/util/Collection.js b/node_modules/discord.js/src/util/Collection.js new file mode 100644 index 0000000..3219fb8 --- /dev/null +++ b/node_modules/discord.js/src/util/Collection.js @@ -0,0 +1,17 @@ +'use strict'; + +const BaseCollection = require('@discordjs/collection'); +const Util = require('./Util'); + +class Collection extends BaseCollection { + toJSON() { + return this.map(e => (typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e))); + } +} + +module.exports = Collection; + +/** + * @external Collection + * @see {@link https://discord.js.org/#/docs/collection/master/class/Collection} + */ diff --git a/node_modules/discord.js/src/util/Constants.js b/node_modules/discord.js/src/util/Constants.js new file mode 100644 index 0000000..8269992 --- /dev/null +++ b/node_modules/discord.js/src/util/Constants.js @@ -0,0 +1,678 @@ +'use strict'; + +const Package = (exports.Package = require('../../package.json')); +const { Error, RangeError } = require('../errors'); +const browser = (exports.browser = typeof window !== 'undefined'); + +/** + * Options for a client. + * @typedef {Object} ClientOptions + * @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified, + * the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the + * recommended amount of shards from Discord and spawn that amount + * @property {number} [shardCount=1] The total amount of shards used by all processes of this bot + * (e.g. recommended shard count, shard count of the ShardingManager) + * @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel + * (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb + * indefinitely) + * @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered + * sweepable (in seconds, 0 for forever) + * @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than + * the message cache lifetime (in seconds, 0 for never) + * @property {number} [messageEditHistoryMaxSize=-1] Maximum number of previous versions to hold for an edited message + * (-1 or Infinity for unlimited - don't do this without sweeping, otherwise memory usage may climb indefinitely.) + * @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as + * upon joining a guild (should be avoided whenever possible) + * @property {DisableMentionType} [disableMentions='none'] Default value for {@link MessageOptions#disableMentions} + * @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions} + * @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when + * they're missing all the data for a particular structure. See the "Partials" topic listed in the sidebar for some + * important usage information, as partials require you to put checks in place when handling data. + * @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their + * corresponding websocket events + * @property {number} [restTimeOffset=500] Extra time in milliseconds to wait before continuing to make REST + * requests (higher values will reduce rate-limiting errors on bad connections) + * @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds + * @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds + * (or 0 for never) + * @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries) + * @property {PresenceData} [presence] Presence data to use upon login + * @property {WebsocketOptions} [ws] Options for the WebSocket + * @property {HTTPOptions} [http] HTTP options + */ +exports.DefaultOptions = { + shardCount: 1, + messageCacheMaxSize: 200, + messageCacheLifetime: 0, + messageSweepInterval: 0, + messageEditHistoryMaxSize: -1, + fetchAllMembers: false, + disableMentions: 'none', + partials: [], + restWsBridgeTimeout: 5000, + restRequestTimeout: 15000, + retryLimit: 1, + restTimeOffset: 500, + restSweepInterval: 60, + presence: {}, + + /** + * WebSocket options (these are left as snake_case to match the API) + * @typedef {Object} WebsocketOptions + * @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be + * sent in the initial guild member list, must be between 50 and 250 + * @property {IntentsResolvable} [intents] Intents to enable for this connection + */ + ws: { + large_threshold: 50, + compress: false, + properties: { + $os: browser ? 'browser' : process.platform, + $browser: 'discord.js', + $device: 'discord.js', + }, + version: 6, + }, + + /** + * HTTP options + * @typedef {Object} HTTPOptions + * @property {number} [version=7] API version to use + * @property {string} [api='https://discord.com/api'] Base url of the API + * @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN + * @property {string} [invite='https://discord.gg'] Base url of invites + * @property {string} [template='https://discord.new'] Base url of templates + */ + http: { + version: 7, + api: 'https://discord.com/api', + cdn: 'https://cdn.discordapp.com', + invite: 'https://discord.gg', + template: 'https://discord.new', + }, +}; + +exports.UserAgent = browser + ? null + : `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`; + +exports.WSCodes = { + 1000: 'WS_CLOSE_REQUESTED', + 4004: 'TOKEN_INVALID', + 4010: 'SHARDING_INVALID', + 4011: 'SHARDING_REQUIRED', + 4013: 'INVALID_INTENTS', + 4014: 'DISALLOWED_INTENTS', +}; + +const AllowedImageFormats = ['webp', 'png', 'jpg', 'jpeg', 'gif']; + +const AllowedImageSizes = Array.from({ length: 9 }, (e, i) => 2 ** (i + 4)); + +function makeImageUrl(root, { format = 'webp', size } = {}) { + if (format && !AllowedImageFormats.includes(format)) throw new Error('IMAGE_FORMAT', format); + if (size && !AllowedImageSizes.includes(size)) throw new RangeError('IMAGE_SIZE', size); + return `${root}.${format}${size ? `?size=${size}` : ''}`; +} +/** + * Options for Image URLs. + * @typedef {Object} ImageURLOptions + * @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided, + * defaults to `webp`. + * @property {boolean} [dynamic] If true, the format will dynamically change to `gif` for + * animated avatars; the default is false. + * @property {number} [size] One of `16`, `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096` + */ + +exports.Endpoints = { + CDN(root) { + return { + Emoji: (emojiID, format = 'png') => `${root}/emojis/${emojiID}.${format}`, + Asset: name => `${root}/assets/${name}`, + DefaultAvatar: discriminator => `${root}/embed/avatars/${discriminator}.png`, + Avatar: (userID, hash, format = 'webp', size, dynamic = false) => { + if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; + return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size }); + }, + Banner: (guildID, hash, format = 'webp', size) => + makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }), + Icon: (guildID, hash, format = 'webp', size, dynamic = false) => { + if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; + return makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size }); + }, + AppIcon: (clientID, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/app-icons/${clientID}/${hash}`, { size, format }), + AppAsset: (clientID, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/app-assets/${clientID}/${hash}`, { size, format }), + GDMIcon: (channelID, hash, format = 'webp', size) => + makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }), + Splash: (guildID, hash, format = 'webp', size) => + makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }), + DiscoverySplash: (guildID, hash, format = 'webp', size) => + makeImageUrl(`${root}/discovery-splashes/${guildID}/${hash}`, { size, format }), + TeamIcon: (teamID, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }), + }; + }, + invite: (root, code) => `${root}/${code}`, + botGateway: '/gateway/bot', +}; + +/** + * The current status of the client. Here are the available statuses: + * * READY: 0 + * * CONNECTING: 1 + * * RECONNECTING: 2 + * * IDLE: 3 + * * NEARLY: 4 + * * DISCONNECTED: 5 + * * WAITING_FOR_GUILDS: 6 + * * IDENTIFYING: 7 + * * RESUMING: 8 + * @typedef {number} Status + */ +exports.Status = { + READY: 0, + CONNECTING: 1, + RECONNECTING: 2, + IDLE: 3, + NEARLY: 4, + DISCONNECTED: 5, + WAITING_FOR_GUILDS: 6, + IDENTIFYING: 7, + RESUMING: 8, +}; + +/** + * The current status of a voice connection. Here are the available statuses: + * * CONNECTED: 0 + * * CONNECTING: 1 + * * AUTHENTICATING: 2 + * * RECONNECTING: 3 + * * DISCONNECTED: 4 + * @typedef {number} VoiceStatus + */ +exports.VoiceStatus = { + CONNECTED: 0, + CONNECTING: 1, + AUTHENTICATING: 2, + RECONNECTING: 3, + DISCONNECTED: 4, +}; + +exports.OPCodes = { + DISPATCH: 0, + HEARTBEAT: 1, + IDENTIFY: 2, + STATUS_UPDATE: 3, + VOICE_STATE_UPDATE: 4, + VOICE_GUILD_PING: 5, + RESUME: 6, + RECONNECT: 7, + REQUEST_GUILD_MEMBERS: 8, + INVALID_SESSION: 9, + HELLO: 10, + HEARTBEAT_ACK: 11, +}; + +exports.VoiceOPCodes = { + IDENTIFY: 0, + SELECT_PROTOCOL: 1, + READY: 2, + HEARTBEAT: 3, + SESSION_DESCRIPTION: 4, + SPEAKING: 5, + HELLO: 8, + CLIENT_CONNECT: 12, + CLIENT_DISCONNECT: 13, +}; + +exports.Events = { + RATE_LIMIT: 'rateLimit', + CLIENT_READY: 'ready', + GUILD_CREATE: 'guildCreate', + GUILD_DELETE: 'guildDelete', + GUILD_UPDATE: 'guildUpdate', + GUILD_UNAVAILABLE: 'guildUnavailable', + GUILD_AVAILABLE: 'guildAvailable', + GUILD_MEMBER_ADD: 'guildMemberAdd', + GUILD_MEMBER_REMOVE: 'guildMemberRemove', + GUILD_MEMBER_UPDATE: 'guildMemberUpdate', + GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable', + GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking', + GUILD_MEMBERS_CHUNK: 'guildMembersChunk', + GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate', + GUILD_ROLE_CREATE: 'roleCreate', + GUILD_ROLE_DELETE: 'roleDelete', + INVITE_CREATE: 'inviteCreate', + INVITE_DELETE: 'inviteDelete', + GUILD_ROLE_UPDATE: 'roleUpdate', + GUILD_EMOJI_CREATE: 'emojiCreate', + GUILD_EMOJI_DELETE: 'emojiDelete', + GUILD_EMOJI_UPDATE: 'emojiUpdate', + GUILD_BAN_ADD: 'guildBanAdd', + GUILD_BAN_REMOVE: 'guildBanRemove', + CHANNEL_CREATE: 'channelCreate', + CHANNEL_DELETE: 'channelDelete', + CHANNEL_UPDATE: 'channelUpdate', + CHANNEL_PINS_UPDATE: 'channelPinsUpdate', + MESSAGE_CREATE: 'message', + MESSAGE_DELETE: 'messageDelete', + MESSAGE_UPDATE: 'messageUpdate', + MESSAGE_BULK_DELETE: 'messageDeleteBulk', + MESSAGE_REACTION_ADD: 'messageReactionAdd', + MESSAGE_REACTION_REMOVE: 'messageReactionRemove', + MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll', + MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji', + USER_UPDATE: 'userUpdate', + PRESENCE_UPDATE: 'presenceUpdate', + VOICE_SERVER_UPDATE: 'voiceServerUpdate', + VOICE_STATE_UPDATE: 'voiceStateUpdate', + VOICE_BROADCAST_SUBSCRIBE: 'subscribe', + VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe', + TYPING_START: 'typingStart', + TYPING_STOP: 'typingStop', + WEBHOOKS_UPDATE: 'webhookUpdate', + ERROR: 'error', + WARN: 'warn', + DEBUG: 'debug', + SHARD_DISCONNECT: 'shardDisconnect', + SHARD_ERROR: 'shardError', + SHARD_RECONNECTING: 'shardReconnecting', + SHARD_READY: 'shardReady', + SHARD_RESUME: 'shardResume', + INVALIDATED: 'invalidated', + RAW: 'raw', +}; + +exports.ShardEvents = { + CLOSE: 'close', + DESTROYED: 'destroyed', + INVALID_SESSION: 'invalidSession', + READY: 'ready', + RESUMED: 'resumed', + ALL_READY: 'allReady', +}; + +/** + * The type of Structure allowed to be a partial: + * * USER + * * CHANNEL (only affects DMChannels) + * * GUILD_MEMBER + * * MESSAGE + * * REACTION + * Partials require you to put checks in place when handling data, read the Partials topic listed in the + * sidebar for more information. + * @typedef {string} PartialType + */ +exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'REACTION']); + +/** + * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events: + * * READY + * * RESUMED + * * GUILD_CREATE + * * GUILD_DELETE + * * GUILD_UPDATE + * * INVITE_CREATE + * * INVITE_DELETE + * * GUILD_MEMBER_ADD + * * GUILD_MEMBER_REMOVE + * * GUILD_MEMBER_UPDATE + * * GUILD_MEMBERS_CHUNK + * * GUILD_INTEGRATIONS_UPDATE + * * GUILD_ROLE_CREATE + * * GUILD_ROLE_DELETE + * * GUILD_ROLE_UPDATE + * * GUILD_BAN_ADD + * * GUILD_BAN_REMOVE + * * GUILD_EMOJIS_UPDATE + * * CHANNEL_CREATE + * * CHANNEL_DELETE + * * CHANNEL_UPDATE + * * CHANNEL_PINS_UPDATE + * * MESSAGE_CREATE + * * MESSAGE_DELETE + * * MESSAGE_UPDATE + * * MESSAGE_DELETE_BULK + * * MESSAGE_REACTION_ADD + * * MESSAGE_REACTION_REMOVE + * * MESSAGE_REACTION_REMOVE_ALL + * * MESSAGE_REACTION_REMOVE_EMOJI + * * USER_UPDATE + * * PRESENCE_UPDATE + * * TYPING_START + * * VOICE_STATE_UPDATE + * * VOICE_SERVER_UPDATE + * * WEBHOOKS_UPDATE + * @typedef {string} WSEventType + */ +exports.WSEvents = keyMirror([ + 'READY', + 'RESUMED', + 'GUILD_CREATE', + 'GUILD_DELETE', + 'GUILD_UPDATE', + 'INVITE_CREATE', + 'INVITE_DELETE', + 'GUILD_MEMBER_ADD', + 'GUILD_MEMBER_REMOVE', + 'GUILD_MEMBER_UPDATE', + 'GUILD_MEMBERS_CHUNK', + 'GUILD_INTEGRATIONS_UPDATE', + 'GUILD_ROLE_CREATE', + 'GUILD_ROLE_DELETE', + 'GUILD_ROLE_UPDATE', + 'GUILD_BAN_ADD', + 'GUILD_BAN_REMOVE', + 'GUILD_EMOJIS_UPDATE', + 'CHANNEL_CREATE', + 'CHANNEL_DELETE', + 'CHANNEL_UPDATE', + 'CHANNEL_PINS_UPDATE', + 'MESSAGE_CREATE', + 'MESSAGE_DELETE', + 'MESSAGE_UPDATE', + 'MESSAGE_DELETE_BULK', + 'MESSAGE_REACTION_ADD', + 'MESSAGE_REACTION_REMOVE', + 'MESSAGE_REACTION_REMOVE_ALL', + 'MESSAGE_REACTION_REMOVE_EMOJI', + 'USER_UPDATE', + 'PRESENCE_UPDATE', + 'TYPING_START', + 'VOICE_STATE_UPDATE', + 'VOICE_SERVER_UPDATE', + 'WEBHOOKS_UPDATE', +]); + +/** + * The type of a message, e.g. `DEFAULT`. Here are the available types: + * * DEFAULT + * * RECIPIENT_ADD + * * RECIPIENT_REMOVE + * * CALL + * * CHANNEL_NAME_CHANGE + * * CHANNEL_ICON_CHANGE + * * PINS_ADD + * * GUILD_MEMBER_JOIN + * * USER_PREMIUM_GUILD_SUBSCRIPTION + * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 + * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 + * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 + * * CHANNEL_FOLLOW_ADD + * * GUILD_DISCOVERY_DISQUALIFIED + * * GUILD_DISCOVERY_REQUALIFIED + * @typedef {string} MessageType + */ +exports.MessageTypes = [ + 'DEFAULT', + 'RECIPIENT_ADD', + 'RECIPIENT_REMOVE', + 'CALL', + 'CHANNEL_NAME_CHANGE', + 'CHANNEL_ICON_CHANGE', + 'PINS_ADD', + 'GUILD_MEMBER_JOIN', + 'USER_PREMIUM_GUILD_SUBSCRIPTION', + 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1', + 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2', + 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3', + 'CHANNEL_FOLLOW_ADD', + null, + 'GUILD_DISCOVERY_DISQUALIFIED', + 'GUILD_DISCOVERY_REQUALIFIED', +]; + +/** + * Bots cannot set a `CUSTOM_STATUS`, it is only for custom statuses received from users + * The type of an activity of a users presence, e.g. `PLAYING`. Here are the available types: + * * PLAYING + * * STREAMING + * * LISTENING + * * WATCHING + * * CUSTOM_STATUS + * * COMPETING + * @typedef {string} ActivityType + */ +exports.ActivityTypes = ['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM_STATUS', 'COMPETING']; + +exports.ChannelTypes = { + TEXT: 0, + DM: 1, + VOICE: 2, + GROUP: 3, + CATEGORY: 4, + NEWS: 5, + STORE: 6, +}; + +exports.ClientApplicationAssetTypes = { + SMALL: 1, + BIG: 2, +}; + +exports.Colors = { + DEFAULT: 0x000000, + WHITE: 0xffffff, + AQUA: 0x1abc9c, + GREEN: 0x2ecc71, + BLUE: 0x3498db, + YELLOW: 0xffff00, + PURPLE: 0x9b59b6, + LUMINOUS_VIVID_PINK: 0xe91e63, + GOLD: 0xf1c40f, + ORANGE: 0xe67e22, + RED: 0xe74c3c, + GREY: 0x95a5a6, + NAVY: 0x34495e, + DARK_AQUA: 0x11806a, + DARK_GREEN: 0x1f8b4c, + DARK_BLUE: 0x206694, + DARK_PURPLE: 0x71368a, + DARK_VIVID_PINK: 0xad1457, + DARK_GOLD: 0xc27c0e, + DARK_ORANGE: 0xa84300, + DARK_RED: 0x992d22, + DARK_GREY: 0x979c9f, + DARKER_GREY: 0x7f8c8d, + LIGHT_GREY: 0xbcc0c0, + DARK_NAVY: 0x2c3e50, + BLURPLE: 0x7289da, + GREYPLE: 0x99aab5, + DARK_BUT_NOT_BLACK: 0x2c2f33, + NOT_QUITE_BLACK: 0x23272a, +}; + +/** + * The value set for the explicit content filter levels for a guild: + * * DISABLED + * * MEMBERS_WITHOUT_ROLES + * * ALL_MEMBERS + * @typedef {string} ExplicitContentFilterLevel + */ +exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS']; + +/** + * The value set for the verification levels for a guild: + * * NONE + * * LOW + * * MEDIUM + * * HIGH + * * VERY_HIGH + * @typedef {string} VerificationLevel + */ +exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; + +/** + * An error encountered while performing an API request. Here are the potential errors: + * * UNKNOWN_ACCOUNT + * * UNKNOWN_APPLICATION + * * UNKNOWN_CHANNEL + * * UNKNOWN_GUILD + * * UNKNOWN_INTEGRATION + * * UNKNOWN_INVITE + * * UNKNOWN_MEMBER + * * UNKNOWN_MESSAGE + * * UNKNOWN_OVERWRITE + * * UNKNOWN_PROVIDER + * * UNKNOWN_ROLE + * * UNKNOWN_TOKEN + * * UNKNOWN_USER + * * UNKNOWN_EMOJI + * * UNKNOWN_WEBHOOK + * * UNKNOWN_BAN + * * UNKNOWN_GUILD_TEMPLATE + * * BOT_PROHIBITED_ENDPOINT + * * BOT_ONLY_ENDPOINT + * * CHANNEL_HIT_WRITE_RATELIMIT + * * MAXIMUM_GUILDS + * * MAXIMUM_FRIENDS + * * MAXIMUM_PINS + * * MAXIMUM_ROLES + * * MAXIMUM_WEBHOOKS + * * MAXIMUM_REACTIONS + * * MAXIMUM_CHANNELS + * * MAXIMUM_ATTACHMENTS + * * MAXIMUM_INVITES + * * GUILD_ALREADY_HAS_TEMPLATE + * * UNAUTHORIZED + * * ACCOUNT_VERIFICATION_REQUIRED + * * REQUEST_ENTITY_TOO_LARGE + * * FEATURE_TEMPORARILY_DISABLED + * * USER_BANNED + * * ALREADY_CROSSPOSTED + * * MISSING_ACCESS + * * INVALID_ACCOUNT_TYPE + * * CANNOT_EXECUTE_ON_DM + * * EMBED_DISABLED + * * CANNOT_EDIT_MESSAGE_BY_OTHER + * * CANNOT_SEND_EMPTY_MESSAGE + * * CANNOT_MESSAGE_USER + * * CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL + * * CHANNEL_VERIFICATION_LEVEL_TOO_HIGH + * * OAUTH2_APPLICATION_BOT_ABSENT + * * MAXIMUM_OAUTH2_APPLICATIONS + * * INVALID_OAUTH_STATE + * * MISSING_PERMISSIONS + * * INVALID_AUTHENTICATION_TOKEN + * * NOTE_TOO_LONG + * * INVALID_BULK_DELETE_QUANTITY + * * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL + * * INVALID_OR_TAKEN_INVITE_CODE + * * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE + * * INVALID_OAUTH_TOKEN + * * BULK_DELETE_MESSAGE_TOO_OLD + * * INVALID_FORM_BODY + * * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT + * * INVALID_API_VERSION + * * CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL + * * REACTION_BLOCKED + * * RESOURCE_OVERLOADED + * @typedef {string} APIError + */ +exports.APIErrors = { + UNKNOWN_ACCOUNT: 10001, + UNKNOWN_APPLICATION: 10002, + UNKNOWN_CHANNEL: 10003, + UNKNOWN_GUILD: 10004, + UNKNOWN_INTEGRATION: 10005, + UNKNOWN_INVITE: 10006, + UNKNOWN_MEMBER: 10007, + UNKNOWN_MESSAGE: 10008, + UNKNOWN_OVERWRITE: 10009, + UNKNOWN_PROVIDER: 10010, + UNKNOWN_ROLE: 10011, + UNKNOWN_TOKEN: 10012, + UNKNOWN_USER: 10013, + UNKNOWN_EMOJI: 10014, + UNKNOWN_WEBHOOK: 10015, + UNKNOWN_BAN: 10026, + UNKNOWN_GUILD_TEMPLATE: 10057, + BOT_PROHIBITED_ENDPOINT: 20001, + BOT_ONLY_ENDPOINT: 20002, + CHANNEL_HIT_WRITE_RATELIMIT: 20028, + MAXIMUM_GUILDS: 30001, + MAXIMUM_FRIENDS: 30002, + MAXIMUM_PINS: 30003, + MAXIMUM_ROLES: 30005, + MAXIMUM_WEBHOOKS: 30007, + MAXIMUM_REACTIONS: 30010, + MAXIMUM_CHANNELS: 30013, + MAXIMUM_ATTACHMENTS: 30015, + MAXIMUM_INVITES: 30016, + GUILD_ALREADY_HAS_TEMPLATE: 30031, + UNAUTHORIZED: 40001, + ACCOUNT_VERIFICATION_REQUIRED: 40002, + REQUEST_ENTITY_TOO_LARGE: 40005, + FEATURE_TEMPORARILY_DISABLED: 40006, + USER_BANNED: 40007, + ALREADY_CROSSPOSTED: 40033, + MISSING_ACCESS: 50001, + INVALID_ACCOUNT_TYPE: 50002, + CANNOT_EXECUTE_ON_DM: 50003, + EMBED_DISABLED: 50004, + CANNOT_EDIT_MESSAGE_BY_OTHER: 50005, + CANNOT_SEND_EMPTY_MESSAGE: 50006, + CANNOT_MESSAGE_USER: 50007, + CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008, + CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009, + OAUTH2_APPLICATION_BOT_ABSENT: 50010, + MAXIMUM_OAUTH2_APPLICATIONS: 50011, + INVALID_OAUTH_STATE: 50012, + MISSING_PERMISSIONS: 50013, + INVALID_AUTHENTICATION_TOKEN: 50014, + NOTE_TOO_LONG: 50015, + INVALID_BULK_DELETE_QUANTITY: 50016, + CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019, + INVALID_OR_TAKEN_INVITE_CODE: 50020, + CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021, + INVALID_OAUTH_TOKEN: 50025, + BULK_DELETE_MESSAGE_TOO_OLD: 50034, + INVALID_FORM_BODY: 50035, + INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036, + INVALID_API_VERSION: 50041, + CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074, + REACTION_BLOCKED: 90001, + RESOURCE_OVERLOADED: 130000, +}; + +/** + * The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types: + * * ALL + * * MENTIONS + * @typedef {string} DefaultMessageNotifications + */ +exports.DefaultMessageNotifications = ['ALL', 'MENTIONS']; + +/** + * The value set for a team members's membership state: + * * INVITED + * * ACCEPTED + * @typedef {string} MembershipStates + */ +exports.MembershipStates = [ + // They start at 1 + null, + 'INVITED', + 'ACCEPTED', +]; + +/** + * The value set for a webhook's type: + * * Incoming + * * Channel Follower + * @typedef {string} WebhookTypes + */ +exports.WebhookTypes = [ + // They start at 1 + null, + 'Incoming', + 'Channel Follower', +]; + +function keyMirror(arr) { + let tmp = Object.create(null); + for (const value of arr) tmp[value] = value; + return tmp; +} diff --git a/node_modules/discord.js/src/util/DataResolver.js b/node_modules/discord.js/src/util/DataResolver.js new file mode 100644 index 0000000..fbddbd5 --- /dev/null +++ b/node_modules/discord.js/src/util/DataResolver.js @@ -0,0 +1,153 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const stream = require('stream'); +const fetch = require('node-fetch'); +const { Error: DiscordError, TypeError } = require('../errors'); +const { browser } = require('../util/Constants'); +const Util = require('../util/Util'); + +/** + * The DataResolver identifies different objects and tries to resolve a specific piece of information from them. + * @private + */ +class DataResolver { + constructor() { + throw new Error(`The ${this.constructor.name} class may not be instantiated.`); + } + + /** + * Data that can be resolved to give an invite code. This can be: + * * An invite code + * * An invite URL + * @typedef {string} InviteResolvable + */ + + /** + * Data that can be resolved to give an template code. This can be: + * * A template code + * * A template URL + * @typedef {string} GuildTemplateResolvable + */ + + /** + * Resolves the string to a code based on the passed regex. + * @param {string} data The string to resolve + * @param {RegExp} regex The RegExp used to extract the code + * @returns {string} + */ + static resolveCode(data, regex) { + const match = regex.exec(data); + return match ? match[1] || data : data; + } + + /** + * Resolves InviteResolvable to an invite code. + * @param {InviteResolvable} data The invite resolvable to resolve + * @returns {string} + */ + static resolveInviteCode(data) { + return this.resolveCode(data, /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i); + } + + /** + * Resolves GuildTemplateResolvable to a template code. + * @param {GuildTemplateResolvable} data The template resolvable to resolve + * @returns {string} + */ + static resolveGuildTemplateCode(data) { + return this.resolveCode(data, /discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/i); + } + + /** + * Resolves a Base64Resolvable, a string, or a BufferResolvable to a Base 64 image. + * @param {BufferResolvable|Base64Resolvable} image The image to be resolved + * @returns {Promise} + */ + static async resolveImage(image) { + if (!image) return null; + if (typeof image === 'string' && image.startsWith('data:')) { + return image; + } + const file = await this.resolveFileAsBuffer(image); + return DataResolver.resolveBase64(file); + } + + /** + * Data that resolves to give a Base64 string, typically for image uploading. This can be: + * * A Buffer + * * A base64 string + * @typedef {Buffer|string} Base64Resolvable + */ + + /** + * Resolves a Base64Resolvable to a Base 64 image. + * @param {Base64Resolvable} data The base 64 resolvable you want to resolve + * @returns {?string} + */ + static resolveBase64(data) { + if (Buffer.isBuffer(data)) return `data:image/jpg;base64,${data.toString('base64')}`; + return data; + } + + /** + * Data that can be resolved to give a Buffer. This can be: + * * A Buffer + * * The path to a local file + * * A URL + * @typedef {string|Buffer} BufferResolvable + */ + + /** + * @external Stream + * @see {@link https://nodejs.org/api/stream.html} + */ + + /** + * Resolves a BufferResolvable to a Buffer or a Stream. + * @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve + * @returns {Promise} + */ + static async resolveFile(resource) { + if (!browser && Buffer.isBuffer(resource)) return resource; + if (browser && resource instanceof ArrayBuffer) return Util.convertToBuffer(resource); + // eslint-disable-next-line no-undef + if (browser && resource instanceof Blob) return resource; + if (resource instanceof stream.Readable) return resource; + + if (typeof resource === 'string') { + if (/^https?:\/\//.test(resource)) { + const res = await fetch(resource); + return browser ? res.blob() : res.body; + } else if (!browser) { + return new Promise((resolve, reject) => { + const file = path.resolve(resource); + fs.stat(file, (err, stats) => { + if (err) return reject(err); + if (!stats.isFile()) return reject(new DiscordError('FILE_NOT_FOUND', file)); + return resolve(fs.createReadStream(file)); + }); + }); + } + } + + throw new TypeError('REQ_RESOURCE_TYPE'); + } + + /** + * Resolves a BufferResolvable to a Buffer. + * @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve + * @returns {Promise} + */ + static async resolveFileAsBuffer(resource) { + const file = await this.resolveFile(resource); + if (Buffer.isBuffer(file)) return file; + + const buffers = []; + for await (const data of file) buffers.push(data); + return Buffer.concat(buffers); + } +} + +module.exports = DataResolver; diff --git a/node_modules/discord.js/src/util/Intents.js b/node_modules/discord.js/src/util/Intents.js new file mode 100644 index 0000000..e627c8b --- /dev/null +++ b/node_modules/discord.js/src/util/Intents.js @@ -0,0 +1,83 @@ +'use strict'; +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to calculate intents. + * @extends {BitField} + */ +class Intents extends BitField {} + +/** + * @name Intents + * @kind constructor + * @memberof Intents + * @param {IntentsResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Data that can be resolved to give a permission number. This can be: + * * A string (see {@link Intents.FLAGS}) + * * An intents flag + * * An instance of Intents + * * An array of IntentsResolvable + * @typedef {string|number|Intents|IntentsResolvable[]} IntentsResolvable + */ + +/** + * Numeric websocket intents. All available properties: + * * `GUILDS` + * * `GUILD_MEMBERS` + * * `GUILD_BANS` + * * `GUILD_EMOJIS` + * * `GUILD_INTEGRATIONS` + * * `GUILD_WEBHOOKS` + * * `GUILD_INVITES` + * * `GUILD_VOICE_STATES` + * * `GUILD_PRESENCES` + * * `GUILD_MESSAGES` + * * `GUILD_MESSAGE_REACTIONS` + * * `GUILD_MESSAGE_TYPING` + * * `DIRECT_MESSAGES` + * * `DIRECT_MESSAGE_REACTIONS` + * * `DIRECT_MESSAGE_TYPING` + * @type {Object} + * @see {@link https://discord.com/developers/docs/topics/gateway#list-of-intents} + */ +Intents.FLAGS = { + GUILDS: 1 << 0, + GUILD_MEMBERS: 1 << 1, + GUILD_BANS: 1 << 2, + GUILD_EMOJIS: 1 << 3, + GUILD_INTEGRATIONS: 1 << 4, + GUILD_WEBHOOKS: 1 << 5, + GUILD_INVITES: 1 << 6, + GUILD_VOICE_STATES: 1 << 7, + GUILD_PRESENCES: 1 << 8, + GUILD_MESSAGES: 1 << 9, + GUILD_MESSAGE_REACTIONS: 1 << 10, + GUILD_MESSAGE_TYPING: 1 << 11, + DIRECT_MESSAGES: 1 << 12, + DIRECT_MESSAGE_REACTIONS: 1 << 13, + DIRECT_MESSAGE_TYPING: 1 << 14, +}; + +/** + * Bitfield representing all privileged intents + * @type {number} + * @see {@link https://discord.com/developers/docs/topics/gateway#privileged-intents} + */ +Intents.PRIVILEGED = Intents.FLAGS.GUILD_MEMBERS | Intents.FLAGS.GUILD_PRESENCES; + +/** + * Bitfield representing all intents combined + * @type {number} + */ +Intents.ALL = Object.values(Intents.FLAGS).reduce((acc, p) => acc | p, 0); + +/** + * Bitfield representing all non-privileged intents + * @type {number} + */ +Intents.NON_PRIVILEGED = Intents.ALL & ~Intents.PRIVILEGED; + +module.exports = Intents; diff --git a/node_modules/discord.js/src/util/LimitedCollection.js b/node_modules/discord.js/src/util/LimitedCollection.js new file mode 100644 index 0000000..caa4978 --- /dev/null +++ b/node_modules/discord.js/src/util/LimitedCollection.js @@ -0,0 +1,34 @@ +'use strict'; + +const Collection = require('./Collection.js'); + +/** + * A Collection which holds a max amount of entries. The first key is deleted if the Collection has + * reached max size. + * @extends {Collection} + * @param {number} [maxSize=0] The maximum size of the Collection + * @param {Iterable} [iterable=null] Optional entries passed to the Map constructor. + * @private + */ +class LimitedCollection extends Collection { + constructor(maxSize = 0, iterable = null) { + super(iterable); + /** + * The max size of the Collection. + * @type {number} + */ + this.maxSize = maxSize; + } + + set(key, value) { + if (this.maxSize === 0) return this; + if (this.size >= this.maxSize && !this.has(key)) this.delete(this.firstKey()); + return super.set(key, value); + } + + static get [Symbol.species]() { + return Collection; + } +} + +module.exports = LimitedCollection; diff --git a/node_modules/discord.js/src/util/MessageFlags.js b/node_modules/discord.js/src/util/MessageFlags.js new file mode 100644 index 0000000..536cbd8 --- /dev/null +++ b/node_modules/discord.js/src/util/MessageFlags.js @@ -0,0 +1,36 @@ +'use strict'; + +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with an {@link Message#flags} bitfield. + * @extends {BitField} + */ +class MessageFlags extends BitField {} + +/** + * @name MessageFlags + * @kind constructor + * @memberof MessageFlags + * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Numeric message flags. All available properties: + * * `CROSSPOSTED` + * * `IS_CROSSPOST` + * * `SUPPRESS_EMBEDS` + * * `SOURCE_MESSAGE_DELETED` + * * `URGENT` + * @type {Object} + * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-flags} + */ +MessageFlags.FLAGS = { + CROSSPOSTED: 1 << 0, + IS_CROSSPOST: 1 << 1, + SUPPRESS_EMBEDS: 1 << 2, + SOURCE_MESSAGE_DELETED: 1 << 3, + URGENT: 1 << 4, +}; + +module.exports = MessageFlags; diff --git a/node_modules/discord.js/src/util/Permissions.js b/node_modules/discord.js/src/util/Permissions.js new file mode 100644 index 0000000..98a2838 --- /dev/null +++ b/node_modules/discord.js/src/util/Permissions.js @@ -0,0 +1,131 @@ +'use strict'; + +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of + * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member + * that override their default permissions. + * @extends {BitField} + */ +class Permissions extends BitField { + /** + * @name Permissions + * @kind constructor + * @memberof Permissions + * @param {PermissionResolvable} [bits=0] Bit(s) to read from + */ + + /** + * Data that can be resolved to give a permission number. This can be: + * * A string (see {@link Permissions.FLAGS}) + * * A permission number + * * An instance of Permissions + * * An Array of PermissionResolvable + * @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable + */ + + /** + * Checks whether the bitfield has a permission, or any of multiple permissions. + * @param {PermissionResolvable} permission Permission(s) to check for + * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override + * @returns {boolean} + */ + any(permission, checkAdmin = true) { + return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.any(permission); + } + + /** + * Checks whether the bitfield has a permission, or multiple permissions. + * @param {PermissionResolvable} permission Permission(s) to check for + * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override + * @returns {boolean} + */ + has(permission, checkAdmin = true) { + return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.has(permission); + } +} + +/** + * Numeric permission flags. All available properties: + * * `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites) + * * `CREATE_INSTANT_INVITE` (create invitations to the guild) + * * `KICK_MEMBERS` + * * `BAN_MEMBERS` + * * `MANAGE_CHANNELS` (edit and reorder channels) + * * `MANAGE_GUILD` (edit the guild information, region, etc.) + * * `ADD_REACTIONS` (add new reactions to messages) + * * `VIEW_AUDIT_LOG` + * * `PRIORITY_SPEAKER` + * * `STREAM` + * * `VIEW_CHANNEL` + * * `SEND_MESSAGES` + * * `SEND_TTS_MESSAGES` + * * `MANAGE_MESSAGES` (delete messages and reactions) + * * `EMBED_LINKS` (links posted will have a preview embedded) + * * `ATTACH_FILES` + * * `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord) + * * `MENTION_EVERYONE` + * * `USE_EXTERNAL_EMOJIS` (use emojis from different guilds) + * * `VIEW_GUILD_INSIGHTS` + * * `CONNECT` (connect to a voice channel) + * * `SPEAK` (speak in a voice channel) + * * `MUTE_MEMBERS` (mute members across all voice channels) + * * `DEAFEN_MEMBERS` (deafen members across all voice channels) + * * `MOVE_MEMBERS` (move members between voice channels) + * * `USE_VAD` (use voice activity detection) + * * `CHANGE_NICKNAME` + * * `MANAGE_NICKNAMES` (change other members' nicknames) + * * `MANAGE_ROLES` + * * `MANAGE_WEBHOOKS` + * * `MANAGE_EMOJIS` + * @type {Object} + * @see {@link https://discord.com/developers/docs/topics/permissions} + */ +Permissions.FLAGS = { + CREATE_INSTANT_INVITE: 1 << 0, + KICK_MEMBERS: 1 << 1, + BAN_MEMBERS: 1 << 2, + ADMINISTRATOR: 1 << 3, + MANAGE_CHANNELS: 1 << 4, + MANAGE_GUILD: 1 << 5, + ADD_REACTIONS: 1 << 6, + VIEW_AUDIT_LOG: 1 << 7, + PRIORITY_SPEAKER: 1 << 8, + STREAM: 1 << 9, + VIEW_CHANNEL: 1 << 10, + SEND_MESSAGES: 1 << 11, + SEND_TTS_MESSAGES: 1 << 12, + MANAGE_MESSAGES: 1 << 13, + EMBED_LINKS: 1 << 14, + ATTACH_FILES: 1 << 15, + READ_MESSAGE_HISTORY: 1 << 16, + MENTION_EVERYONE: 1 << 17, + USE_EXTERNAL_EMOJIS: 1 << 18, + VIEW_GUILD_INSIGHTS: 1 << 19, + CONNECT: 1 << 20, + SPEAK: 1 << 21, + MUTE_MEMBERS: 1 << 22, + DEAFEN_MEMBERS: 1 << 23, + MOVE_MEMBERS: 1 << 24, + USE_VAD: 1 << 25, + CHANGE_NICKNAME: 1 << 26, + MANAGE_NICKNAMES: 1 << 27, + MANAGE_ROLES: 1 << 28, + MANAGE_WEBHOOKS: 1 << 29, + MANAGE_EMOJIS: 1 << 30, +}; + +/** + * Bitfield representing every permission combined + * @type {number} + */ +Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0); + +/** + * Bitfield representing the default permissions for users + * @type {number} + */ +Permissions.DEFAULT = 104324673; + +module.exports = Permissions; diff --git a/node_modules/discord.js/src/util/Snowflake.js b/node_modules/discord.js/src/util/Snowflake.js new file mode 100644 index 0000000..bf1309c --- /dev/null +++ b/node_modules/discord.js/src/util/Snowflake.js @@ -0,0 +1,93 @@ +'use strict'; + +const Util = require('../util/Util'); + +// Discord epoch (2015-01-01T00:00:00.000Z) +const EPOCH = 1420070400000; +let INCREMENT = 0; + +/** + * A container for useful snowflake-related methods. + */ +class SnowflakeUtil { + constructor() { + throw new Error(`The ${this.constructor.name} class may not be instantiated.`); + } + + /** + * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z + * ``` + * If we have a snowflake '266241948824764416' we can represent it as binary: + * + * 64 22 17 12 0 + * 000000111011000111100001101001000101000000 00001 00000 000000000000 + * number of ms since Discord epoch worker pid increment + * ``` + * @typedef {string} Snowflake + */ + + /** + * Generates a Discord snowflake. + * This hardcodes the worker ID as 1 and the process ID as 0. + * @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate + * @returns {Snowflake} The generated snowflake + */ + static generate(timestamp = Date.now()) { + if (timestamp instanceof Date) timestamp = timestamp.getTime(); + if (typeof timestamp !== 'number' || isNaN(timestamp)) { + throw new TypeError( + `"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`, + ); + } + if (INCREMENT >= 4095) INCREMENT = 0; + const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++) + .toString(2) + .padStart(12, '0')}`; + return Util.binaryToID(BINARY); + } + + /** + * A deconstructed snowflake. + * @typedef {Object} DeconstructedSnowflake + * @property {number} timestamp Timestamp the snowflake was created + * @property {Date} date Date the snowflake was created + * @property {number} workerID Worker ID in the snowflake + * @property {number} processID Process ID in the snowflake + * @property {number} increment Increment in the snowflake + * @property {string} binary Binary representation of the snowflake + */ + + /** + * Deconstructs a Discord snowflake. + * @param {Snowflake} snowflake Snowflake to deconstruct + * @returns {DeconstructedSnowflake} Deconstructed snowflake + */ + static deconstruct(snowflake) { + const BINARY = Util.idToBinary(snowflake).toString(2).padStart(64, '0'); + const res = { + timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH, + workerID: parseInt(BINARY.substring(42, 47), 2), + processID: parseInt(BINARY.substring(47, 52), 2), + increment: parseInt(BINARY.substring(52, 64), 2), + binary: BINARY, + }; + Object.defineProperty(res, 'date', { + get: function get() { + return new Date(this.timestamp); + }, + enumerable: true, + }); + return res; + } + + /** + * Discord's epoch value (2015-01-01T00:00:00.000Z). + * @type {number} + * @readonly + */ + static get EPOCH() { + return EPOCH; + } +} + +module.exports = SnowflakeUtil; diff --git a/node_modules/discord.js/src/util/Speaking.js b/node_modules/discord.js/src/util/Speaking.js new file mode 100644 index 0000000..5fda560 --- /dev/null +++ b/node_modules/discord.js/src/util/Speaking.js @@ -0,0 +1,33 @@ +'use strict'; + +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with a {@link VoiceConnection#speaking} + * and {@link guildMemberSpeaking} event bitfields. + * @extends {BitField} + */ +class Speaking extends BitField {} + +/** + * @name Speaking + * @kind constructor + * @memberof Speaking + * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Numeric speaking flags. All available properties: + * * `SPEAKING` + * * `SOUNDSHARE` + * * `PRIORITY_SPEAKING` + * @type {Object} + * @see {@link https://discord.com/developers/docs/topics/voice-connections#speaking} + */ +Speaking.FLAGS = { + SPEAKING: 1 << 0, + SOUNDSHARE: 1 << 1, + PRIORITY_SPEAKING: 1 << 2, +}; + +module.exports = Speaking; diff --git a/node_modules/discord.js/src/util/Structures.js b/node_modules/discord.js/src/util/Structures.js new file mode 100644 index 0000000..0c6ab35 --- /dev/null +++ b/node_modules/discord.js/src/util/Structures.js @@ -0,0 +1,112 @@ +'use strict'; + +/** + * An extendable structure: + * * **`GuildEmoji`** + * * **`DMChannel`** + * * **`TextChannel`** + * * **`VoiceChannel`** + * * **`CategoryChannel`** + * * **`NewsChannel`** + * * **`StoreChannel`** + * * **`GuildMember`** + * * **`Guild`** + * * **`Message`** + * * **`MessageReaction`** + * * **`Presence`** + * * **`ClientPresence`** + * * **`VoiceState`** + * * **`Role`** + * * **`User`** + * @typedef {string} ExtendableStructure + */ + +/** + * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}. + */ +class Structures { + constructor() { + throw new Error(`The ${this.constructor.name} class may not be instantiated.`); + } + + /** + * Retrieves a structure class. + * @param {string} structure Name of the structure to retrieve + * @returns {Function} + */ + static get(structure) { + if (typeof structure === 'string') return structures[structure]; + throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`); + } + + /** + * Extends a structure. + * Make sure to extend all structures before instantiating your client. + * Extending after doing so may not work as expected. + * @param {ExtendableStructure} structure Name of the structure class to extend + * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the + * extended class/prototype + * @returns {Function} Extended class/prototype returned from the extender + * @example + * const { Structures } = require('discord.js'); + * + * Structures.extend('Guild', Guild => { + * class CoolGuild extends Guild { + * constructor(client, data) { + * super(client, data); + * this.cool = true; + * } + * } + * + * return CoolGuild; + * }); + */ + static extend(structure, extender) { + if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`); + if (typeof extender !== 'function') { + const received = `(received ${typeof extender})`; + throw new TypeError( + `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`, + ); + } + + const extended = extender(structures[structure]); + if (typeof extended !== 'function') { + const received = `(received ${typeof extended})`; + throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`); + } + + if (!(extended.prototype instanceof structures[structure])) { + const prototype = Object.getPrototypeOf(extended); + const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`; + throw new Error( + 'The class/prototype returned from the extender function must extend the existing structure class/prototype' + + ` (received function ${received}; expected extension of ${structures[structure].name}).`, + ); + } + + structures[structure] = extended; + return extended; + } +} + +const structures = { + GuildEmoji: require('../structures/GuildEmoji'), + DMChannel: require('../structures/DMChannel'), + TextChannel: require('../structures/TextChannel'), + VoiceChannel: require('../structures/VoiceChannel'), + CategoryChannel: require('../structures/CategoryChannel'), + NewsChannel: require('../structures/NewsChannel'), + StoreChannel: require('../structures/StoreChannel'), + GuildMember: require('../structures/GuildMember'), + Guild: require('../structures/Guild'), + Message: require('../structures/Message'), + MessageReaction: require('../structures/MessageReaction'), + Presence: require('../structures/Presence').Presence, + ClientPresence: require('../structures/ClientPresence'), + VoiceState: require('../structures/VoiceState'), + Role: require('../structures/Role'), + User: require('../structures/User'), +}; + +module.exports = Structures; diff --git a/node_modules/discord.js/src/util/SystemChannelFlags.js b/node_modules/discord.js/src/util/SystemChannelFlags.js new file mode 100644 index 0000000..4d08b76 --- /dev/null +++ b/node_modules/discord.js/src/util/SystemChannelFlags.js @@ -0,0 +1,40 @@ +'use strict'; + +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with a {@link Guild#systemChannelFlags} bitfield. + * Note that all event message types are enabled by default, + * and by setting their corresponding flags you are disabling them + * @extends {BitField} + */ +class SystemChannelFlags extends BitField {} + +/** + * @name SystemChannelFlags + * @kind constructor + * @memberof SystemChannelFlags + * @param {SystemChannelFlagsResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Data that can be resolved to give a sytem channel flag bitfield. This can be: + * * A string (see {@link SystemChannelFlags.FLAGS}) + * * A sytem channel flag + * * An instance of SystemChannelFlags + * * An Array of SystemChannelFlagsResolvable + * @typedef {string|number|SystemChannelFlags|SystemChannelFlagsResolvable[]} SystemChannelFlagsResolvable + */ + +/** + * Numeric system channel flags. All available properties: + * * `WELCOME_MESSAGE_DISABLED` + * * `BOOST_MESSAGE_DISABLED` + * @type {Object} + */ +SystemChannelFlags.FLAGS = { + WELCOME_MESSAGE_DISABLED: 1 << 0, + BOOST_MESSAGE_DISABLED: 1 << 1, +}; + +module.exports = SystemChannelFlags; diff --git a/node_modules/discord.js/src/util/UserFlags.js b/node_modules/discord.js/src/util/UserFlags.js new file mode 100644 index 0000000..82c03ed --- /dev/null +++ b/node_modules/discord.js/src/util/UserFlags.js @@ -0,0 +1,55 @@ +'use strict'; +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to interact with a {@link User#flags} bitfield. + * @extends {BitField} + */ +class UserFlags extends BitField {} + +/** + * @name UserFlags + * @kind constructor + * @memberof UserFlags + * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + */ + +/** + * Numeric user flags. All available properties: + * * `DISCORD_EMPLOYEE` + * * `PARTNERED_SERVER_OWNER` + * * `DISCORD_PARTNER` **(deprecated)** + * * `HYPESQUAD_EVENTS` + * * `BUGHUNTER_LEVEL_1` + * * `HOUSE_BRAVERY` + * * `HOUSE_BRILLIANCE` + * * `HOUSE_BALANCE` + * * `EARLY_SUPPORTER` + * * `TEAM_USER` + * * `SYSTEM` + * * `BUGHUNTER_LEVEL_2` + * * `VERIFIED_BOT` + * * `EARLY_VERIFIED_BOT_DEVELOPER` + * * `VERIFIED_DEVELOPER` **(deprecated)** + * @type {Object} + * @see {@link https://discord.com/developers/docs/resources/user#user-object-user-flags} + */ +UserFlags.FLAGS = { + DISCORD_EMPLOYEE: 1 << 0, + PARTNERED_SERVER_OWNER: 1 << 1, + DISCORD_PARTNER: 1 << 1, + HYPESQUAD_EVENTS: 1 << 2, + BUGHUNTER_LEVEL_1: 1 << 3, + HOUSE_BRAVERY: 1 << 6, + HOUSE_BRILLIANCE: 1 << 7, + HOUSE_BALANCE: 1 << 8, + EARLY_SUPPORTER: 1 << 9, + TEAM_USER: 1 << 10, + SYSTEM: 1 << 12, + BUGHUNTER_LEVEL_2: 1 << 14, + VERIFIED_BOT: 1 << 16, + EARLY_VERIFIED_DEVELOPER: 1 << 17, + VERIFIED_DEVELOPER: 1 << 17, +}; + +module.exports = UserFlags; diff --git a/node_modules/discord.js/src/util/Util.js b/node_modules/discord.js/src/util/Util.js new file mode 100644 index 0000000..d1909fd --- /dev/null +++ b/node_modules/discord.js/src/util/Util.js @@ -0,0 +1,625 @@ +'use strict'; + +const { parse } = require('path'); +const fetch = require('node-fetch'); +const { Colors, DefaultOptions, Endpoints } = require('./Constants'); +const { Error: DiscordError, RangeError, TypeError } = require('../errors'); +const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k); +const isObject = d => typeof d === 'object' && d !== null; + +/** + * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object. + */ +class Util { + constructor() { + throw new Error(`The ${this.constructor.name} class may not be instantiated.`); + } + + /** + * Flatten an object. Any properties that are collections will get converted to an array of keys. + * @param {Object} obj The object to flatten. + * @param {...Object} [props] Specific properties to include/exclude. + * @returns {Object} + */ + static flatten(obj, ...props) { + if (!isObject(obj)) return obj; + + const objProps = Object.keys(obj) + .filter(k => !k.startsWith('_')) + .map(k => ({ [k]: true })); + + props = objProps.length ? Object.assign(...objProps, ...props) : Object.assign({}, ...props); + + const out = {}; + + for (let [prop, newProp] of Object.entries(props)) { + if (!newProp) continue; + newProp = newProp === true ? prop : newProp; + + const element = obj[prop]; + const elemIsObj = isObject(element); + const valueOf = elemIsObj && typeof element.valueOf === 'function' ? element.valueOf() : null; + + // If it's a Collection, make the array of keys + if (element instanceof require('./Collection')) out[newProp] = Array.from(element.keys()); + // If the valueOf is a Collection, use its array of keys + else if (valueOf instanceof require('./Collection')) out[newProp] = Array.from(valueOf.keys()); + // If it's an array, flatten each element + else if (Array.isArray(element)) out[newProp] = element.map(e => Util.flatten(e)); + // If it's an object with a primitive `valueOf`, use that value + else if (typeof valueOf !== 'object') out[newProp] = valueOf; + // If it's a primitive + else if (!elemIsObj) out[newProp] = element; + } + + return out; + } + + /** + * Splits a string into multiple chunks at a designated character that do not exceed a specific length. + * @param {StringResolvable} text Content to split + * @param {SplitOptions} [options] Options controlling the behavior of the split + * @returns {string[]} + */ + static splitMessage(text, { maxLength = 2000, char = '\n', prepend = '', append = '' } = {}) { + text = Util.resolveString(text); + if (text.length <= maxLength) return [text]; + const splitText = text.split(char); + if (splitText.some(chunk => chunk.length > maxLength)) throw new RangeError('SPLIT_MAX_LEN'); + const messages = []; + let msg = ''; + for (const chunk of splitText) { + if (msg && (msg + char + chunk + append).length > maxLength) { + messages.push(msg + append); + msg = prepend; + } + msg += (msg && msg !== prepend ? char : '') + chunk; + } + return messages.concat(msg).filter(m => m); + } + + /** + * Escapes any Discord-flavour markdown in a string. + * @param {string} text Content to escape + * @param {Object} [options={}] What types of markdown to escape + * @param {boolean} [options.codeBlock=true] Whether to escape code blocks or not + * @param {boolean} [options.inlineCode=true] Whether to escape inline code or not + * @param {boolean} [options.bold=true] Whether to escape bolds or not + * @param {boolean} [options.italic=true] Whether to escape italics or not + * @param {boolean} [options.underline=true] Whether to escape underlines or not + * @param {boolean} [options.strikethrough=true] Whether to escape strikethroughs or not + * @param {boolean} [options.spoiler=true] Whether to escape spoilers or not + * @param {boolean} [options.codeBlockContent=true] Whether to escape text inside code blocks or not + * @param {boolean} [options.inlineCodeContent=true] Whether to escape text inside inline code or not + * @returns {string} + */ + static escapeMarkdown( + text, + { + codeBlock = true, + inlineCode = true, + bold = true, + italic = true, + underline = true, + strikethrough = true, + spoiler = true, + codeBlockContent = true, + inlineCodeContent = true, + } = {}, + ) { + if (!codeBlockContent) { + return text + .split('```') + .map((subString, index, array) => { + if (index % 2 && index !== array.length - 1) return subString; + return Util.escapeMarkdown(subString, { + inlineCode, + bold, + italic, + underline, + strikethrough, + spoiler, + inlineCodeContent, + }); + }) + .join(codeBlock ? '\\`\\`\\`' : '```'); + } + if (!inlineCodeContent) { + return text + .split(/(?<=^|[^`])`(?=[^`]|$)/g) + .map((subString, index, array) => { + if (index % 2 && index !== array.length - 1) return subString; + return Util.escapeMarkdown(subString, { + codeBlock, + bold, + italic, + underline, + strikethrough, + spoiler, + }); + }) + .join(inlineCode ? '\\`' : '`'); + } + if (inlineCode) text = Util.escapeInlineCode(text); + if (codeBlock) text = Util.escapeCodeBlock(text); + if (italic) text = Util.escapeItalic(text); + if (bold) text = Util.escapeBold(text); + if (underline) text = Util.escapeUnderline(text); + if (strikethrough) text = Util.escapeStrikethrough(text); + if (spoiler) text = Util.escapeSpoiler(text); + return text; + } + + /** + * Escapes code block markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeCodeBlock(text) { + return text.replace(/```/g, '\\`\\`\\`'); + } + + /** + * Escapes inline code markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeInlineCode(text) { + return text.replace(/(?<=^|[^`])`(?=[^`]|$)/g, '\\`'); + } + + /** + * Escapes italic markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeItalic(text) { + let i = 0; + text = text.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g, (_, match) => { + if (match === '**') return ++i % 2 ? `\\*${match}` : `${match}\\*`; + return `\\*${match}`; + }); + i = 0; + return text.replace(/(?<=^|[^_])_([^_]|__|$)/g, (_, match) => { + if (match === '__') return ++i % 2 ? `\\_${match}` : `${match}\\_`; + return `\\_${match}`; + }); + } + + /** + * Escapes bold markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeBold(text) { + let i = 0; + return text.replace(/\*\*(\*)?/g, (_, match) => { + if (match) return ++i % 2 ? `${match}\\*\\*` : `\\*\\*${match}`; + return '\\*\\*'; + }); + } + + /** + * Escapes underline markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeUnderline(text) { + let i = 0; + return text.replace(/__(_)?/g, (_, match) => { + if (match) return ++i % 2 ? `${match}\\_\\_` : `\\_\\_${match}`; + return '\\_\\_'; + }); + } + + /** + * Escapes strikethrough markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeStrikethrough(text) { + return text.replace(/~~/g, '\\~\\~'); + } + + /** + * Escapes spoiler markdown in a string. + * @param {string} text Content to escape + * @returns {string} + */ + static escapeSpoiler(text) { + return text.replace(/\|\|/g, '\\|\\|'); + } + + /** + * Gets the recommended shard count from Discord. + * @param {string} token Discord auth token + * @param {number} [guildsPerShard=1000] Number of guilds per shard + * @returns {Promise} The recommended number of shards + */ + static fetchRecommendedShards(token, guildsPerShard = 1000) { + if (!token) throw new DiscordError('TOKEN_MISSING'); + return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, { + method: 'GET', + headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` }, + }) + .then(res => { + if (res.ok) return res.json(); + if (res.status === 401) throw new DiscordError('TOKEN_INVALID'); + throw res; + }) + .then(data => data.shards * (1000 / guildsPerShard)); + } + + /** + * Parses emoji info out of a string. The string must be one of: + * * A UTF-8 emoji (no ID) + * * A URL-encoded UTF-8 emoji (no ID) + * * A Discord custom emoji (`<:name:id>` or ``) + * @param {string} text Emoji string to parse + * @returns {Object} Object with `animated`, `name`, and `id` properties + * @private + */ + static parseEmoji(text) { + if (text.includes('%')) text = decodeURIComponent(text); + if (!text.includes(':')) return { animated: false, name: text, id: null }; + const m = text.match(/?/); + if (!m) return null; + return { animated: Boolean(m[1]), name: m[2], id: m[3] || null }; + } + + /** + * Shallow-copies an object with its class/prototype intact. + * @param {Object} obj Object to clone + * @returns {Object} + * @private + */ + static cloneObject(obj) { + return Object.assign(Object.create(obj), obj); + } + + /** + * Sets default properties on an object that aren't already specified. + * @param {Object} def Default properties + * @param {Object} given Object to assign defaults to + * @returns {Object} + * @private + */ + static mergeDefault(def, given) { + if (!given) return def; + for (const key in def) { + if (!has(given, key) || given[key] === undefined) { + given[key] = def[key]; + } else if (given[key] === Object(given[key])) { + given[key] = Util.mergeDefault(def[key], given[key]); + } + } + + return given; + } + + /** + * Converts an ArrayBuffer or string to a Buffer. + * @param {ArrayBuffer|string} ab ArrayBuffer to convert + * @returns {Buffer} + * @private + */ + static convertToBuffer(ab) { + if (typeof ab === 'string') ab = Util.str2ab(ab); + return Buffer.from(ab); + } + + /** + * Converts a string to an ArrayBuffer. + * @param {string} str String to convert + * @returns {ArrayBuffer} + * @private + */ + static str2ab(str) { + const buffer = new ArrayBuffer(str.length * 2); + const view = new Uint16Array(buffer); + for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i); + return buffer; + } + + /** + * Makes an Error from a plain info object. + * @param {Object} obj Error info + * @param {string} obj.name Error type + * @param {string} obj.message Message for the error + * @param {string} obj.stack Stack for the error + * @returns {Error} + * @private + */ + static makeError(obj) { + const err = new Error(obj.message); + err.name = obj.name; + err.stack = obj.stack; + return err; + } + + /** + * Makes a plain error info object from an Error. + * @param {Error} err Error to get info from + * @returns {Object} + * @private + */ + static makePlainError(err) { + return { + name: err.name, + message: err.message, + stack: err.stack, + }; + } + + /** + * Moves an element in an array *in place*. + * @param {Array<*>} array Array to modify + * @param {*} element Element to move + * @param {number} newIndex Index or offset to move the element to + * @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index + * @returns {number} + * @private + */ + static moveElementInArray(array, element, newIndex, offset = false) { + const index = array.indexOf(element); + newIndex = (offset ? index : 0) + newIndex; + if (newIndex > -1 && newIndex < array.length) { + const removedElement = array.splice(index, 1)[0]; + array.splice(newIndex, 0, removedElement); + } + return array.indexOf(element); + } + + /** + * Data that can be resolved to give a string. This can be: + * * A string + * * An array (joined with a new line delimiter to give a string) + * * Any value + * @typedef {string|Array|*} StringResolvable + */ + + /** + * Resolves a StringResolvable to a string. + * @param {StringResolvable} data The string resolvable to resolve + * @returns {string} + */ + static resolveString(data) { + if (typeof data === 'string') return data; + if (Array.isArray(data)) return data.join('\n'); + return String(data); + } + + /** + * Can be a number, hex string, an RGB array like: + * ```js + * [255, 0, 255] // purple + * ``` + * or one of the following strings: + * - `DEFAULT` + * - `WHITE` + * - `AQUA` + * - `GREEN` + * - `BLUE` + * - `YELLOW` + * - `PURPLE` + * - `LUMINOUS_VIVID_PINK` + * - `GOLD` + * - `ORANGE` + * - `RED` + * - `GREY` + * - `DARKER_GREY` + * - `NAVY` + * - `DARK_AQUA` + * - `DARK_GREEN` + * - `DARK_BLUE` + * - `DARK_PURPLE` + * - `DARK_VIVID_PINK` + * - `DARK_GOLD` + * - `DARK_ORANGE` + * - `DARK_RED` + * - `DARK_GREY` + * - `LIGHT_GREY` + * - `DARK_NAVY` + * - `BLURPLE` + * - `GREYPLE` + * - `DARK_BUT_NOT_BLACK` + * - `NOT_QUITE_BLACK` + * - `RANDOM` + * @typedef {string|number|number[]} ColorResolvable + */ + + /** + * Resolves a ColorResolvable into a color number. + * @param {ColorResolvable} color Color to resolve + * @returns {number} A color + */ + static resolveColor(color) { + if (typeof color === 'string') { + if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1)); + if (color === 'DEFAULT') return 0; + color = Colors[color] || parseInt(color.replace('#', ''), 16); + } else if (Array.isArray(color)) { + color = (color[0] << 16) + (color[1] << 8) + color[2]; + } + + if (color < 0 || color > 0xffffff) throw new RangeError('COLOR_RANGE'); + else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT'); + + return color; + } + + /** + * Sorts by Discord's position and ID. + * @param {Collection} collection Collection of objects to sort + * @returns {Collection} + */ + static discordSort(collection) { + return collection.sorted( + (a, b) => + a.rawPosition - b.rawPosition || + parseInt(b.id.slice(0, -10)) - parseInt(a.id.slice(0, -10)) || + parseInt(b.id.slice(10)) - parseInt(a.id.slice(10)), + ); + } + + /** + * Sets the position of a Channel or Role. + * @param {Channel|Role} item Object to set the position of + * @param {number} position New position for the object + * @param {boolean} relative Whether `position` is relative to its current position + * @param {Collection} sorted A collection of the objects sorted properly + * @param {APIRouter} route Route to call PATCH on + * @param {string} [reason] Reason for the change + * @returns {Promise} Updated item list, with `id` and `position` properties + * @private + */ + static setPosition(item, position, relative, sorted, route, reason) { + let updatedItems = sorted.array(); + Util.moveElementInArray(updatedItems, item, position, relative); + updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i })); + return route.patch({ data: updatedItems, reason }).then(() => updatedItems); + } + + /** + * Alternative to Node's `path.basename`, removing query string after the extension if it exists. + * @param {string} path Path to get the basename of + * @param {string} [ext] File extension to remove + * @returns {string} Basename of the path + * @private + */ + static basename(path, ext) { + let res = parse(path); + return ext && res.ext.startsWith(ext) ? res.name : res.base.split('?')[0]; + } + + /** + * Transforms a snowflake from a decimal string to a bit string. + * @param {Snowflake} num Snowflake to be transformed + * @returns {string} + * @private + */ + static idToBinary(num) { + let bin = ''; + let high = parseInt(num.slice(0, -10)) || 0; + let low = parseInt(num.slice(-10)); + while (low > 0 || high > 0) { + bin = String(low & 1) + bin; + low = Math.floor(low / 2); + if (high > 0) { + low += 5000000000 * (high % 2); + high = Math.floor(high / 2); + } + } + return bin; + } + + /** + * Transforms a snowflake from a bit string to a decimal string. + * @param {string} num Bit string to be transformed + * @returns {Snowflake} + * @private + */ + static binaryToID(num) { + let dec = ''; + + while (num.length > 50) { + const high = parseInt(num.slice(0, -32), 2); + const low = parseInt((high % 10).toString(2) + num.slice(-32), 2); + + dec = (low % 10).toString() + dec; + num = + Math.floor(high / 10).toString(2) + + Math.floor(low / 10) + .toString(2) + .padStart(32, '0'); + } + + num = parseInt(num, 2); + while (num > 0) { + dec = (num % 10).toString() + dec; + num = Math.floor(num / 10); + } + + return dec; + } + + /** + * Breaks user, role and everyone/here mentions by adding a zero width space after every @ character + * @param {string} str The string to sanitize + * @returns {string} + */ + static removeMentions(str) { + return str.replace(/@/g, '@\u200b'); + } + + /** + * The content to have all mentions replaced by the equivalent text. + * @param {string} str The string to be converted + * @param {Message} message The message object to reference + * @returns {string} + */ + static cleanContent(str, message) { + str = str + .replace(/<@!?[0-9]+>/g, input => { + const id = input.replace(/<|!|>|@/g, ''); + if (message.channel.type === 'dm') { + const user = message.client.users.cache.get(id); + return user ? Util.removeMentions(`@${user.username}`) : input; + } + + const member = message.channel.guild.members.cache.get(id); + if (member) { + return Util.removeMentions(`@${member.displayName}`); + } else { + const user = message.client.users.cache.get(id); + return user ? Util.removeMentions(`@${user.username}`) : input; + } + }) + .replace(/<#[0-9]+>/g, input => { + const channel = message.client.channels.cache.get(input.replace(/<|#|>/g, '')); + return channel ? `#${channel.name}` : input; + }) + .replace(/<@&[0-9]+>/g, input => { + if (message.channel.type === 'dm') return input; + const role = message.guild.roles.cache.get(input.replace(/<|@|>|&/g, '')); + return role ? `@${role.name}` : input; + }); + if (message.client.options.disableMentions === 'everyone') { + str = str.replace(/@([^<>@ ]*)/gmsu, (match, target) => { + if (target.match(/^[&!]?\d+$/)) { + return `@${target}`; + } else { + return `@\u200b${target}`; + } + }); + } + if (message.client.options.disableMentions === 'all') { + return Util.removeMentions(str); + } else { + return str; + } + } + + /** + * The content to put in a codeblock with all codeblock fences replaced by the equivalent backticks. + * @param {string} text The string to be converted + * @returns {string} + */ + static cleanCodeBlockContent(text) { + return text.replace(/```/g, '`\u200b``'); + } + + /** + * Creates a Promise that resolves after a specified duration. + * @param {number} ms How long to wait before resolving (in milliseconds) + * @returns {Promise} + * @private + */ + static delayFor(ms) { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); + } +} + +module.exports = Util; diff --git a/node_modules/discord.js/typings/index.d.ts b/node_modules/discord.js/typings/index.d.ts new file mode 100644 index 0000000..e0be3c6 --- /dev/null +++ b/node_modules/discord.js/typings/index.d.ts @@ -0,0 +1,3255 @@ +declare enum ChannelType { + text = 0, + dm = 1, + voice = 2, + group = 3, + category = 4, + news = 5, + store = 6, + unknown = 7, +} + +declare module 'discord.js' { + import BaseCollection from '@discordjs/collection'; + import { ChildProcess } from 'child_process'; + import { EventEmitter } from 'events'; + import { PathLike } from 'fs'; + import { Readable, Stream, Writable } from 'stream'; + import * as WebSocket from 'ws'; + + export const version: string; + + //#region Classes + + export class Activity { + constructor(presence: Presence, data?: object); + public applicationID: Snowflake | null; + public assets: RichPresenceAssets | null; + public readonly createdAt: Date; + public createdTimestamp: number; + public details: string | null; + public emoji: Emoji | null; + public flags: Readonly; + public name: string; + public party: { + id: string | null; + size: [number, number]; + } | null; + public state: string | null; + public timestamps: { + start: Date | null; + end: Date | null; + } | null; + public type: ActivityType; + public url: string | null; + public equals(activity: Activity): boolean; + } + + export class ActivityFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class APIMessage { + constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions); + public data: object | null; + public readonly isUser: boolean; + public readonly isWebhook: boolean; + public files: object[] | null; + public options: MessageOptions | WebhookMessageOptions; + public target: MessageTarget; + + public static create( + target: MessageTarget, + content: APIMessageContentResolvable, + options?: undefined, + extra?: MessageOptions | WebhookMessageOptions, + ): APIMessage; + public static create( + target: MessageTarget, + content: StringResolvable, + options: MessageOptions | WebhookMessageOptions | MessageAdditions, + extra?: MessageOptions | WebhookMessageOptions, + ): APIMessage; + public static partitionMessageAdditions( + items: readonly (MessageEmbed | MessageAttachment)[], + ): [MessageEmbed[], MessageAttachment[]]; + public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise; + public static transformOptions( + content: APIMessageContentResolvable, + options?: undefined, + extra?: MessageOptions | WebhookMessageOptions, + isWebhook?: boolean, + ): MessageOptions | WebhookMessageOptions; + public static transformOptions( + content: StringResolvable, + options: MessageOptions | WebhookMessageOptions | MessageAdditions, + extra?: MessageOptions | WebhookMessageOptions, + isWebhook?: boolean, + ): MessageOptions | WebhookMessageOptions; + + public makeContent(): string | string[] | undefined; + public resolve(): Promise; + public resolveData(): this; + public resolveFiles(): Promise; + public split(): APIMessage[]; + } + + export abstract class Application { + constructor(client: Client, data: object); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public description: string; + public icon: string; + public id: Snowflake; + public name: string; + public coverImage(options?: ImageURLOptions): string; + public fetchAssets(): Promise; + public iconURL(options?: ImageURLOptions): string; + public toJSON(): object; + public toString(): string; + } + + export class Base { + constructor(client: Client); + public readonly client: Client; + public toJSON(...props: { [key: string]: boolean | string }[]): object; + public valueOf(): string; + } + + export class BaseClient extends EventEmitter { + constructor(options?: ClientOptions); + private _timeouts: Set; + private _intervals: Set; + private _immediates: Set; + private readonly api: object; + private rest: object; + private decrementMaxListeners(): void; + private incrementMaxListeners(): void; + + public options: ClientOptions; + public clearInterval(interval: NodeJS.Timeout): void; + public clearTimeout(timeout: NodeJS.Timeout): void; + public clearImmediate(timeout: NodeJS.Immediate): void; + public destroy(): void; + public setInterval(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timeout; + public setTimeout(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timeout; + public setImmediate(fn: (...args: any[]) => void, ...args: any[]): NodeJS.Immediate; + public toJSON(...props: { [key: string]: boolean | string }[]): object; + } + + export class BaseGuildEmoji extends Emoji { + constructor(client: Client, data: object, guild: Guild); + private _roles: string[]; + + public available: boolean | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public guild: Guild | GuildPreview; + public id: Snowflake; + public managed: boolean | null; + public requiresColons: boolean | null; + } + + class BroadcastDispatcher extends VolumeMixin(StreamDispatcher) { + public broadcast: VoiceBroadcast; + } + + export class BitField { + constructor(bits?: BitFieldResolvable); + public bitfield: number; + public add(...bits: BitFieldResolvable[]): BitField; + public any(bit: BitFieldResolvable): boolean; + public equals(bit: BitFieldResolvable): boolean; + public freeze(): Readonly>; + public has(bit: BitFieldResolvable): boolean; + public missing(bits: BitFieldResolvable, ...hasParam: readonly unknown[]): S[]; + public remove(...bits: BitFieldResolvable[]): BitField; + public serialize(...hasParam: readonly unknown[]): Record; + public toArray(...hasParam: readonly unknown[]): S[]; + public toJSON(): number; + public valueOf(): number; + public [Symbol.iterator](): IterableIterator; + public static FLAGS: object; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class CategoryChannel extends GuildChannel { + public readonly children: Collection; + public type: 'category'; + } + + export class Channel extends Base { + constructor(client: Client, data?: object); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public deleted: boolean; + public id: Snowflake; + public type: keyof typeof ChannelType; + public delete(reason?: string): Promise; + public fetch(force?: boolean): Promise; + public isText(): this is TextChannel | DMChannel | NewsChannel; + public toString(): string; + } + + export class Client extends BaseClient { + constructor(options?: ClientOptions); + private actions: object; + private _eval(script: string): any; + private _validateOptions(options?: ClientOptions): void; + + public channels: ChannelManager; + public readonly emojis: GuildEmojiManager; + public guilds: GuildManager; + public readyAt: Date | null; + public readonly readyTimestamp: number | null; + public shard: ShardClientUtil | null; + public token: string | null; + public readonly uptime: number | null; + public user: ClientUser | null; + public users: UserManager; + public voice: ClientVoiceManager | null; + public ws: WebSocketManager; + public destroy(): void; + public fetchApplication(): Promise; + public fetchGuildPreview(guild: GuildResolvable): Promise; + public fetchInvite(invite: InviteResolvable): Promise; + public fetchGuildTemplate(template: GuildTemplateResolvable): Promise; + public fetchVoiceRegions(): Promise>; + public fetchWebhook(id: Snowflake, token?: string): Promise; + public generateInvite(options?: InviteGenerationOptions | PermissionResolvable): Promise; + public login(token?: string): Promise; + public sweepMessages(lifetime?: number): number; + public toJSON(): object; + + public on(event: K, listener: (...args: ClientEvents[K]) => void): this; + public on( + event: Exclude, + listener: (...args: any[]) => void, + ): this; + + public once(event: K, listener: (...args: ClientEvents[K]) => void): this; + public once( + event: Exclude, + listener: (...args: any[]) => void, + ): this; + + public emit(event: K, ...args: ClientEvents[K]): boolean; + public emit(event: Exclude, ...args: any[]): boolean; + + public off(event: K, listener: (...args: ClientEvents[K]) => void): this; + public off( + event: Exclude, + listener: (...args: any[]) => void, + ): this; + + public removeAllListeners(event?: K): this; + public removeAllListeners(event?: Exclude): this; + } + + export class ClientApplication extends Application { + public botPublic: boolean | null; + public botRequireCodeGrant: boolean | null; + public cover: string | null; + public owner: User | Team | null; + public rpcOrigins: string[]; + } + + export class ClientUser extends User { + public mfaEnabled: boolean; + public verified: boolean; + public setActivity(options?: ActivityOptions): Promise; + public setActivity(name: string, options?: ActivityOptions): Promise; + public setAFK(afk: boolean): Promise; + public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise; + public setPresence(data: PresenceData): Promise; + public setStatus(status: PresenceStatusData, shardID?: number | number[]): Promise; + public setUsername(username: string): Promise; + } + + export class ClientVoiceManager { + constructor(client: Client); + public readonly client: Client; + public connections: Collection; + public broadcasts: VoiceBroadcast[]; + + private joinChannel(channel: VoiceChannel): Promise; + + public createBroadcast(): VoiceBroadcast; + } + + export abstract class Collector extends EventEmitter { + constructor(client: Client, filter: CollectorFilter, options?: CollectorOptions); + private _timeout: NodeJS.Timeout | null; + private _idletimeout: NodeJS.Timeout | null; + + public readonly client: Client; + public collected: Collection; + public ended: boolean; + public filter: CollectorFilter; + public readonly next: Promise; + public options: CollectorOptions; + public checkEnd(): void; + public handleCollect(...args: any[]): void; + public handleDispose(...args: any[]): void; + public stop(reason?: string): void; + public resetTimer(options?: { time?: number; idle?: number }): void; + public [Symbol.asyncIterator](): AsyncIterableIterator; + public toJSON(): object; + + protected listener: (...args: any[]) => void; + public abstract collect(...args: any[]): K; + public abstract dispose(...args: any[]): K; + public abstract endReason(): void; + + public on(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this; + public on(event: 'end', listener: (collected: Collection, reason: string) => void): this; + + public once(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this; + public once(event: 'end', listener: (collected: Collection, reason: string) => void): this; + } + + type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif'; + + export const Constants: { + Package: { + name: string; + version: string; + description: string; + author: string; + license: string; + main: PathLike; + types: PathLike; + homepage: string; + keywords: string[]; + bugs: { url: string }; + repository: { type: string; url: string }; + browser: { [key: string]: boolean }; + scripts: { [key: string]: string }; + engines: { [key: string]: string }; + dependencies: { [key: string]: string }; + peerDependencies: { [key: string]: string }; + devDependencies: { [key: string]: string }; + [key: string]: any; + }; + browser: boolean; + DefaultOptions: ClientOptions; + UserAgent: string | null; + Endpoints: { + botGateway: string; + invite: (root: string, code: string) => string; + CDN: ( + root: string, + ) => { + Asset: (name: string) => string; + DefaultAvatar: (id: string | number) => string; + Emoji: (emojiID: string, format: 'png' | 'gif') => string; + Avatar: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; + Banner: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + Icon: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; + AppIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + AppAsset: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + GDMIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + Splash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + DiscoverySplash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + TeamIcon: (teamID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + }; + }; + WSCodes: { + 1000: 'WS_CLOSE_REQUESTED'; + 4004: 'TOKEN_INVALID'; + 4010: 'SHARDING_INVALID'; + 4011: 'SHARDING_REQUIRED'; + }; + Events: { + RATE_LIMIT: 'rateLimit'; + CLIENT_READY: 'ready'; + RESUMED: 'resumed'; + GUILD_CREATE: 'guildCreate'; + GUILD_DELETE: 'guildDelete'; + GUILD_UPDATE: 'guildUpdate'; + INVITE_CREATE: 'inviteCreate'; + INVITE_DELETE: 'inviteDelete'; + GUILD_UNAVAILABLE: 'guildUnavailable'; + GUILD_MEMBER_ADD: 'guildMemberAdd'; + GUILD_MEMBER_REMOVE: 'guildMemberRemove'; + GUILD_MEMBER_UPDATE: 'guildMemberUpdate'; + GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable'; + GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking'; + GUILD_MEMBERS_CHUNK: 'guildMembersChunk'; + GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate'; + GUILD_ROLE_CREATE: 'roleCreate'; + GUILD_ROLE_DELETE: 'roleDelete'; + GUILD_ROLE_UPDATE: 'roleUpdate'; + GUILD_EMOJI_CREATE: 'emojiCreate'; + GUILD_EMOJI_DELETE: 'emojiDelete'; + GUILD_EMOJI_UPDATE: 'emojiUpdate'; + GUILD_BAN_ADD: 'guildBanAdd'; + GUILD_BAN_REMOVE: 'guildBanRemove'; + CHANNEL_CREATE: 'channelCreate'; + CHANNEL_DELETE: 'channelDelete'; + CHANNEL_UPDATE: 'channelUpdate'; + CHANNEL_PINS_UPDATE: 'channelPinsUpdate'; + MESSAGE_CREATE: 'message'; + MESSAGE_DELETE: 'messageDelete'; + MESSAGE_UPDATE: 'messageUpdate'; + MESSAGE_BULK_DELETE: 'messageDeleteBulk'; + MESSAGE_REACTION_ADD: 'messageReactionAdd'; + MESSAGE_REACTION_REMOVE: 'messageReactionRemove'; + MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll'; + USER_UPDATE: 'userUpdate'; + PRESENCE_UPDATE: 'presenceUpdate'; + VOICE_STATE_UPDATE: 'voiceStateUpdate'; + VOICE_BROADCAST_SUBSCRIBE: 'subscribe'; + VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe'; + TYPING_START: 'typingStart'; + WEBHOOKS_UPDATE: 'webhookUpdate'; + DISCONNECT: 'disconnect'; + RECONNECTING: 'reconnecting'; + ERROR: 'error'; + WARN: 'warn'; + DEBUG: 'debug'; + SHARD_DISCONNECT: 'shardDisconnect'; + SHARD_ERROR: 'shardError'; + SHARD_RECONNECTING: 'shardReconnecting'; + SHARD_READY: 'shardReady'; + SHARD_RESUME: 'shardResume'; + INVALIDATED: 'invalidated'; + RAW: 'raw'; + }; + ShardEvents: { + CLOSE: 'close'; + DESTROYED: 'destroyed'; + INVALID_SESSION: 'invalidSession'; + READY: 'ready'; + RESUMED: 'resumed'; + }; + PartialTypes: { + [K in PartialTypes]: K; + }; + WSEvents: { + [K in WSEventType]: K; + }; + Colors: { + DEFAULT: 0x000000; + WHITE: 0xffffff; + AQUA: 0x1abc9c; + GREEN: 0x2ecc71; + BLUE: 0x3498db; + YELLOW: 0xffff00; + PURPLE: 0x9b59b6; + LUMINOUS_VIVID_PINK: 0xe91e63; + GOLD: 0xf1c40f; + ORANGE: 0xe67e22; + RED: 0xe74c3c; + GREY: 0x95a5a6; + NAVY: 0x34495e; + DARK_AQUA: 0x11806a; + DARK_GREEN: 0x1f8b4c; + DARK_BLUE: 0x206694; + DARK_PURPLE: 0x71368a; + DARK_VIVID_PINK: 0xad1457; + DARK_GOLD: 0xc27c0e; + DARK_ORANGE: 0xa84300; + DARK_RED: 0x992d22; + DARK_GREY: 0x979c9f; + DARKER_GREY: 0x7f8c8d; + LIGHT_GREY: 0xbcc0c0; + DARK_NAVY: 0x2c3e50; + BLURPLE: 0x7289da; + GREYPLE: 0x99aab5; + DARK_BUT_NOT_BLACK: 0x2c2f33; + NOT_QUITE_BLACK: 0x23272a; + }; + Status: { + READY: 0; + CONNECTING: 1; + RECONNECTING: 2; + IDLE: 3; + NEARLY: 4; + DISCONNECTED: 5; + }; + OPCodes: { + DISPATCH: 0; + HEARTBEAT: 1; + IDENTIFY: 2; + STATUS_UPDATE: 3; + VOICE_STATE_UPDATE: 4; + VOICE_GUILD_PING: 5; + RESUME: 6; + RECONNECT: 7; + REQUEST_GUILD_MEMBERS: 8; + INVALID_SESSION: 9; + HELLO: 10; + HEARTBEAT_ACK: 11; + }; + APIErrors: APIErrors; + VoiceStatus: { + CONNECTED: 0; + CONNECTING: 1; + AUTHENTICATING: 2; + RECONNECTING: 3; + DISCONNECTED: 4; + }; + VoiceOPCodes: { + IDENTIFY: 0; + SELECT_PROTOCOL: 1; + READY: 2; + HEARTBEAT: 3; + SESSION_DESCRIPTION: 4; + SPEAKING: 5; + HELLO: 8; + CLIENT_CONNECT: 12; + CLIENT_DISCONNECT: 13; + }; + ChannelTypes: { + TEXT: 0; + DM: 1; + VOICE: 2; + GROUP: 3; + CATEGORY: 4; + NEWS: 5; + STORE: 6; + }; + ClientApplicationAssetTypes: { + SMALL: 1; + BIG: 2; + }; + MessageTypes: MessageType[]; + ActivityTypes: ActivityType[]; + ExplicitContentFilterLevels: ExplicitContentFilterLevel[]; + DefaultMessageNotifications: DefaultMessageNotifications[]; + VerificationLevels: VerificationLevel[]; + MembershipStates: 'INVITED' | 'ACCEPTED'; + }; + + export class DataResolver { + public static resolveBase64(data: Base64Resolvable): string; + public static resolveCode(data: string, regx: RegExp): string; + public static resolveFile(resource: BufferResolvable | Stream): Promise; + public static resolveFileAsBuffer(resource: BufferResolvable | Stream): Promise; + public static resolveImage(resource: BufferResolvable | Base64Resolvable): Promise; + public static resolveInviteCode(data: InviteResolvable): string; + public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string; + } + + export class DiscordAPIError extends Error { + constructor(path: string, error: object, method: string, httpStatus: number); + private static flattenErrors(obj: object, key: string): string[]; + + public code: number; + public method: string; + public path: string; + public httpStatus: number; + } + + export class DMChannel extends TextBasedChannel(Channel, ['bulkDelete']) { + constructor(client: Client, data?: object); + public messages: MessageManager; + public recipient: User; + public readonly partial: false; + public type: 'dm'; + public fetch(force?: boolean): Promise; + } + + export class Emoji extends Base { + constructor(client: Client, emoji: object); + public animated: boolean; + public readonly createdAt: Date | null; + public readonly createdTimestamp: number | null; + public deleted: boolean; + public id: Snowflake | null; + public name: string; + public readonly identifier: string; + public readonly url: string | null; + public toJSON(): object; + public toString(): string; + } + + export class Guild extends Base { + constructor(client: Client, data: object); + private _sortedRoles(): Collection; + private _sortedChannels(channel: Channel): Collection; + private _memberSpeakUpdate(user: Snowflake, speaking: boolean): void; + + public readonly afkChannel: VoiceChannel | null; + public afkChannelID: Snowflake | null; + public afkTimeout: number; + public applicationID: Snowflake | null; + public approximateMemberCount: number | null; + public approximatePresenceCount: number | null; + public available: boolean; + public banner: string | null; + public channels: GuildChannelManager; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public defaultMessageNotifications: DefaultMessageNotifications | number; + public deleted: boolean; + public description: string | null; + public discoverySplash: string | null; + public embedChannel: GuildChannel | null; + public embedChannelID: Snowflake | null; + public embedEnabled: boolean; + public emojis: GuildEmojiManager; + public explicitContentFilter: ExplicitContentFilterLevel; + public features: GuildFeatures[]; + public icon: string | null; + public id: Snowflake; + public readonly joinedAt: Date; + public joinedTimestamp: number; + public large: boolean; + public maximumMembers: number | null; + public maximumPresences: number | null; + public readonly me: GuildMember | null; + public memberCount: number; + public members: GuildMemberManager; + public mfaLevel: number; + public name: string; + public readonly nameAcronym: string; + public readonly owner: GuildMember | null; + public ownerID: Snowflake; + public readonly partnered: boolean; + public preferredLocale: string; + public premiumSubscriptionCount: number | null; + public premiumTier: PremiumTier; + public presences: PresenceManager; + public readonly publicUpdatesChannel: TextChannel | null; + public publicUpdatesChannelID: Snowflake | null; + public region: string; + public roles: RoleManager; + public readonly rulesChannel: TextChannel | null; + public rulesChannelID: Snowflake | null; + public readonly shard: WebSocketShard; + public shardID: number; + public splash: string | null; + public readonly systemChannel: TextChannel | null; + public systemChannelFlags: Readonly; + public systemChannelID: Snowflake | null; + public vanityURLCode: string | null; + public vanityURLUses: number | null; + public verificationLevel: VerificationLevel; + public readonly verified: boolean; + public readonly voice: VoiceState | null; + public readonly voiceStates: VoiceStateManager; + public readonly widgetChannel: TextChannel | null; + public widgetChannelID: Snowflake | null; + public widgetEnabled: boolean | null; + public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise; + public bannerURL(options?: ImageURLOptions): string | null; + public createIntegration(data: IntegrationData, reason?: string): Promise; + public createTemplate(name: string, description?: string): Promise; + public delete(): Promise; + public discoverySplashURL(options?: ImageURLOptions): string | null; + public edit(data: GuildEditData, reason?: string): Promise; + public equals(guild: Guild): boolean; + public fetch(): Promise; + public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise; + public fetchBan(user: UserResolvable): Promise<{ user: User; reason: string }>; + public fetchBans(): Promise>; + public fetchEmbed(): Promise; + public fetchIntegrations(options?: FetchIntegrationsOptions): Promise>; + public fetchInvites(): Promise>; + public fetchPreview(): Promise; + public fetchTemplates(): Promise>; + public fetchVanityCode(): Promise; + public fetchVanityData(): Promise<{ code: string; uses: number }>; + public fetchVoiceRegions(): Promise>; + public fetchWebhooks(): Promise>; + public fetchWidget(): Promise; + public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; + public leave(): Promise; + public member(user: UserResolvable): GuildMember | null; + public setAFKChannel(afkChannel: ChannelResolvable | null, reason?: string): Promise; + public setAFKTimeout(afkTimeout: number, reason?: string): Promise; + public setBanner(banner: Base64Resolvable | null, reason?: string): Promise; + public setChannelPositions(channelPositions: readonly ChannelPosition[]): Promise; + public setDefaultMessageNotifications( + defaultMessageNotifications: DefaultMessageNotifications | number, + reason?: string, + ): Promise; + public setDiscoverySplash(discoverySplash: Base64Resolvable | null, reason?: string): Promise; + public setEmbed(embed: GuildWidgetData, reason?: string): Promise; + public setExplicitContentFilter( + explicitContentFilter: ExplicitContentFilterLevel | number, + reason?: string, + ): Promise; + public setIcon(icon: Base64Resolvable | null, reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setOwner(owner: GuildMemberResolvable, reason?: string): Promise; + public setPreferredLocale(preferredLocale: string, reason?: string): Promise; + public setPublicUpdatesChannel(publicUpdatesChannel: ChannelResolvable | null, reason?: string): Promise; + public setRegion(region: string, reason?: string): Promise; + public setRolePositions(rolePositions: readonly RolePosition[]): Promise; + public setRulesChannel(rulesChannel: ChannelResolvable | null, reason?: string): Promise; + public setSplash(splash: Base64Resolvable | null, reason?: string): Promise; + public setSystemChannel(systemChannel: ChannelResolvable | null, reason?: string): Promise; + public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise; + public setVerificationLevel(verificationLevel: VerificationLevel | number, reason?: string): Promise; + public setWidget(widget: GuildWidgetData, reason?: string): Promise; + public splashURL(options?: ImageURLOptions): string | null; + public toJSON(): object; + public toString(): string; + } + + export class GuildAuditLogs { + constructor(guild: Guild, data: object); + private webhooks: Collection; + private integrations: Collection; + + public entries: Collection; + + public static Actions: GuildAuditLogsActions; + public static Targets: GuildAuditLogsTargets; + public static Entry: typeof GuildAuditLogsEntry; + public static actionType(action: number): GuildAuditLogsActionType; + public static build(...args: any[]): Promise; + public static targetType(target: number): GuildAuditLogsTarget; + public toJSON(): object; + } + + class GuildAuditLogsEntry { + constructor(logs: GuildAuditLogs, guild: Guild, data: object); + public action: GuildAuditLogsAction; + public actionType: GuildAuditLogsActionType; + public changes: AuditLogChange[] | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public executor: User; + public extra: object | Role | GuildMember | null; + public id: Snowflake; + public reason: string | null; + public target: + | Guild + | GuildChannel + | User + | Role + | GuildEmoji + | Invite + | Webhook + | Message + | Integration + | { id: Snowflake } + | null; + public targetType: GuildAuditLogsTarget; + public toJSON(): object; + } + + export class GuildChannel extends Channel { + constructor(guild: Guild, data?: object); + private memberPermissions(member: GuildMember): Readonly; + private rolePermissions(role: Role): Readonly; + + public readonly calculatedPosition: number; + public readonly deletable: boolean; + public guild: Guild; + public readonly manageable: boolean; + public readonly members: Collection; + public name: string; + public readonly parent: CategoryChannel | null; + public parentID: Snowflake | null; + public permissionOverwrites: Collection; + public readonly permissionsLocked: boolean | null; + public readonly position: number; + public rawPosition: number; + public type: Exclude; + public readonly viewable: boolean; + public clone(options?: GuildChannelCloneOptions): Promise; + public createInvite(options?: InviteOptions): Promise; + public createOverwrite( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOption, + reason?: string, + ): Promise; + public edit(data: ChannelData, reason?: string): Promise; + public equals(channel: GuildChannel): boolean; + public fetchInvites(): Promise>; + public lockPermissions(): Promise; + public overwritePermissions( + overwrites: readonly OverwriteResolvable[] | Collection, + reason?: string, + ): Promise; + public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly | null; + public setName(name: string, reason?: string): Promise; + public setParent( + channel: CategoryChannel | Snowflake | null, + options?: { lockPermissions?: boolean; reason?: string }, + ): Promise; + public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise; + public setTopic(topic: string | null, reason?: string): Promise; + public updateOverwrite( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOption, + reason?: string, + ): Promise; + public isText(): this is TextChannel | NewsChannel; + } + + export class GuildEmoji extends BaseGuildEmoji { + public readonly deletable: boolean; + public guild: Guild; + public author: User | null; + public readonly roles: GuildEmojiRoleManager; + public readonly url: string; + public delete(reason?: string): Promise; + public edit(data: GuildEmojiEditData, reason?: string): Promise; + public equals(other: GuildEmoji | object): boolean; + public fetchAuthor(): Promise; + public setName(name: string, reason?: string): Promise; + } + + export class GuildMember extends PartialTextBasedChannel(Base) { + constructor(client: Client, data: object, guild: Guild); + public readonly bannable: boolean; + public deleted: boolean; + public readonly displayColor: number; + public readonly displayHexColor: string; + public readonly displayName: string; + public guild: Guild; + public readonly id: Snowflake; + public readonly joinedAt: Date | null; + public joinedTimestamp: number | null; + public readonly kickable: boolean; + public lastMessageChannelID: Snowflake | null; + public readonly manageable: boolean; + public nickname: string | null; + public readonly partial: false; + public readonly permissions: Readonly; + public readonly premiumSince: Date | null; + public premiumSinceTimestamp: number | null; + public readonly presence: Presence; + public readonly roles: GuildMemberRoleManager; + public user: User; + public readonly voice: VoiceState; + public ban(options?: BanOptions): Promise; + public fetch(force?: boolean): Promise; + public createDM(force?: boolean): Promise; + public deleteDM(): Promise; + public edit(data: GuildMemberEditData, reason?: string): Promise; + public hasPermission( + permission: PermissionResolvable, + options?: { checkAdmin?: boolean; checkOwner?: boolean }, + ): boolean; + public kick(reason?: string): Promise; + public permissionsIn(channel: ChannelResolvable): Readonly; + public setNickname(nickname: string, reason?: string): Promise; + public toJSON(): object; + public toString(): string; + public valueOf(): string; + } + + export class GuildPreview extends Base { + constructor(client: Client, data: object); + public approximateMemberCount: number; + public approximatePresenceCount: number; + public description: string | null; + public discoverySplash: string | null; + public emojis: Collection; + public features: GuildFeatures[]; + public icon: string | null; + public id: string; + public name: string; + public splash: string | null; + public discoverySplashURL(options?: ImageURLOptions): string | null; + public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; + public splashURL(options?: ImageURLOptions): string | null; + public fetch(): Promise; + public toJSON(): object; + public toString(): string; + } + + export class GuildTemplate extends Base { + constructor(client: Client, data: object); + public readonly createdTimestamp: number; + public readonly updatedTimestamp: number; + public readonly url: string; + public code: string; + public name: string; + public description: string | null; + public usageCount: number; + public creator: User; + public creatorID: Snowflake; + public createdAt: Date; + public updatedAt: Date; + public guild: Guild | null; + public guildID: Snowflake; + public serializedGuild: object; + public unSynced: boolean | null; + public createGuild(name: string, icon?: BufferResolvable | Base64Resolvable): Promise; + public delete(): Promise; + public edit(options?: { name?: string; description?: string }): Promise; + public sync(): Promise; + } + + export class GuildPreviewEmoji extends BaseGuildEmoji { + constructor(client: Client, data: object, guild: GuildPreview); + public guild: GuildPreview; + public readonly roles: Set; + } + + export class HTTPError extends Error { + constructor(message: string, name: string, code: number, method: string, path: string); + public code: number; + public method: string; + public name: string; + public path: string; + } + + export class Integration extends Base { + constructor(client: Client, data: object, guild: Guild); + public account: IntegrationAccount; + public application: IntegrationApplication | null; + public enabled: boolean; + public expireBehavior: number; + public expireGracePeriod: number; + public guild: Guild; + public id: Snowflake; + public name: string; + public role: Role; + public syncedAt: number; + public syncing: boolean; + public type: string; + public user: User | null; + public delete(reason?: string): Promise; + public edit(data: IntegrationEditData, reason?: string): Promise; + public sync(): Promise; + } + + export class IntegrationApplication extends Application { + public bot: User | null; + } + + export class Intents extends BitField { + public static FLAGS: Record; + public static PRIVILEGED: number; + public static ALL: number; + public static NON_PRIVILEGED: number; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class Invite extends Base { + constructor(client: Client, data: object); + public channel: GuildChannel | PartialGroupDMChannel; + public code: string; + public readonly deletable: boolean; + public readonly createdAt: Date | null; + public createdTimestamp: number | null; + public readonly expiresAt: Date | null; + public readonly expiresTimestamp: number | null; + public guild: Guild | null; + public inviter: User | null; + public maxAge: number | null; + public maxUses: number | null; + public memberCount: number; + public presenceCount: number; + public targetUser: User | null; + public targetUserType: TargetUser | null; + public temporary: boolean | null; + public readonly url: string; + public uses: number | null; + public delete(reason?: string): Promise; + public toJSON(): object; + public toString(): string; + } + + export class Message extends Base { + constructor(client: Client, data: object, channel: TextChannel | DMChannel | NewsChannel); + private _edits: Message[]; + private patch(data: object): Message; + + public activity: MessageActivity | null; + public application: ClientApplication | null; + public attachments: Collection; + public author: User; + public channel: TextChannel | DMChannel | NewsChannel; + public readonly cleanContent: string; + public content: string; + public readonly createdAt: Date; + public createdTimestamp: number; + public readonly deletable: boolean; + public deleted: boolean; + public readonly editable: boolean; + public readonly editedAt: Date | null; + public editedTimestamp: number | null; + public readonly edits: Message[]; + public embeds: MessageEmbed[]; + public readonly guild: Guild | null; + public id: Snowflake; + public readonly member: GuildMember | null; + public mentions: MessageMentions; + public nonce: string | null; + public readonly partial: false; + public readonly pinnable: boolean; + public pinned: boolean; + public reactions: ReactionManager; + public system: boolean; + public tts: boolean; + public type: MessageType; + public readonly url: string; + public webhookID: Snowflake | null; + public flags: Readonly; + public reference: MessageReference | null; + public awaitReactions( + filter: CollectorFilter, + options?: AwaitReactionsOptions, + ): Promise>; + public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector; + public delete(options?: { timeout?: number; reason?: string }): Promise; + public edit( + content: APIMessageContentResolvable | MessageEditOptions | MessageEmbed | APIMessage, + ): Promise; + public edit(content: StringResolvable, options: MessageEditOptions | MessageEmbed): Promise; + public equals(message: Message, rawData: object): boolean; + public fetchWebhook(): Promise; + public crosspost(): Promise; + public fetch(force?: boolean): Promise; + public pin(options?: { reason?: string }): Promise; + public react(emoji: EmojiIdentifierResolvable): Promise; + public reply( + content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + public reply(options: MessageOptions & { split: true | SplitOptions }): Promise; + public reply(options: MessageOptions | APIMessage): Promise; + public reply( + content: StringResolvable, + options: (MessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + public reply( + content: StringResolvable, + options: MessageOptions & { split: true | SplitOptions }, + ): Promise; + public reply(content: StringResolvable, options: MessageOptions): Promise; + public suppressEmbeds(suppress?: boolean): Promise; + public toJSON(): object; + public toString(): string; + public unpin(options?: { reason?: string }): Promise; + } + + export class MessageAttachment { + constructor(attachment: BufferResolvable | Stream, name?: string, data?: object); + + public attachment: BufferResolvable | Stream; + public height: number | null; + public id: Snowflake; + public name: string | null; + public proxyURL: string; + public size: number; + public readonly spoiler: boolean; + public url: string; + public width: number | null; + public setFile(attachment: BufferResolvable | Stream, name?: string): this; + public setName(name: string): this; + public toJSON(): object; + } + + export class MessageCollector extends Collector { + constructor(channel: TextChannel | DMChannel, filter: CollectorFilter, options?: MessageCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + + public channel: Channel; + public options: MessageCollectorOptions; + public received: number; + + public collect(message: Message): Snowflake; + public dispose(message: Message): Snowflake; + public endReason(): string; + } + + export class MessageEmbed { + constructor(data?: MessageEmbed | MessageEmbedOptions); + public author: MessageEmbedAuthor | null; + public color: number | null; + public readonly createdAt: Date | null; + public description: string | null; + public fields: EmbedField[]; + public files: (MessageAttachment | string | FileOptions)[]; + public footer: MessageEmbedFooter | null; + public readonly hexColor: string | null; + public image: MessageEmbedImage | null; + public readonly length: number; + public provider: MessageEmbedProvider | null; + public thumbnail: MessageEmbedThumbnail | null; + public timestamp: number | null; + public title: string | null; + public type: string; + public url: string | null; + public readonly video: MessageEmbedVideo | null; + public addField(name: StringResolvable, value: StringResolvable, inline?: boolean): this; + public addFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): this; + public attachFiles(file: (MessageAttachment | FileOptions | string)[]): this; + public setAuthor(name: StringResolvable, iconURL?: string, url?: string): this; + public setColor(color: ColorResolvable): this; + public setDescription(description: StringResolvable): this; + public setFooter(text: StringResolvable, iconURL?: string): this; + public setImage(url: string): this; + public setThumbnail(url: string): this; + public setTimestamp(timestamp?: Date | number): this; + public setTitle(title: StringResolvable): this; + public setURL(url: string): this; + public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this; + public toJSON(): object; + + public static normalizeField( + name: StringResolvable, + value: StringResolvable, + inline?: boolean, + ): Required; + public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; + } + + export class MessageFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class MessageMentions { + constructor( + message: Message, + users: object[] | Collection, + roles: Snowflake[] | Collection, + everyone: boolean, + ); + private _channels: Collection | null; + private readonly _content: string; + private _members: Collection | null; + + public readonly channels: Collection; + public readonly client: Client; + public everyone: boolean; + public readonly guild: Guild; + public has( + data: UserResolvable | RoleResolvable | GuildChannelResolvable, + options?: { + ignoreDirect?: boolean; + ignoreRoles?: boolean; + ignoreEveryone?: boolean; + }, + ): boolean; + public readonly members: Collection | null; + public roles: Collection; + public users: Collection; + public crosspostedChannels: Collection; + public toJSON(): object; + + public static CHANNELS_PATTERN: RegExp; + public static EVERYONE_PATTERN: RegExp; + public static ROLES_PATTERN: RegExp; + public static USERS_PATTERN: RegExp; + } + + export class MessageReaction { + constructor(client: Client, data: object, message: Message); + private _emoji: GuildEmoji | ReactionEmoji; + + public readonly client: Client; + public count: number | null; + public readonly emoji: GuildEmoji | ReactionEmoji; + public me: boolean; + public message: Message; + public readonly partial: boolean; + public users: ReactionUserManager; + public remove(): Promise; + public fetch(): Promise; + public toJSON(): object; + } + + export class NewsChannel extends TextBasedChannel(GuildChannel) { + constructor(guild: Guild, data?: object); + public messages: MessageManager; + public nsfw: boolean; + public topic: string | null; + public type: 'news'; + public createWebhook( + name: string, + options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string }, + ): Promise; + public setNSFW(nsfw: boolean, reason?: string): Promise; + public fetchWebhooks(): Promise>; + public addFollower(channel: GuildChannelResolvable, reason?: string): Promise; + } + + export class PartialGroupDMChannel extends Channel { + constructor(client: Client, data: object); + public name: string; + public icon: string | null; + public iconURL(options?: ImageURLOptions): string | null; + } + + export class PermissionOverwrites { + constructor(guildChannel: GuildChannel, data?: object); + public allow: Readonly; + public readonly channel: GuildChannel; + public deny: Readonly; + public id: Snowflake; + public type: OverwriteType; + public update(options: PermissionOverwriteOption, reason?: string): Promise; + public delete(reason?: string): Promise; + public toJSON(): object; + public static resolveOverwriteOptions( + options: ResolvedOverwriteOptions, + initialPermissions: { allow?: PermissionResolvable; deny?: PermissionResolvable }, + ): ResolvedOverwriteOptions; + public static resolve(overwrite: OverwriteResolvable, guild: Guild): RawOverwriteData; + } + + export class Permissions extends BitField { + public any(permission: PermissionResolvable, checkAdmin?: boolean): boolean; + public has(permission: PermissionResolvable, checkAdmin?: boolean): boolean; + public missing(bits: BitFieldResolvable, checkAdmin?: boolean): PermissionString[]; + public serialize(checkAdmin?: boolean): Record; + public toArray(checkAdmin?: boolean): PermissionString[]; + + public static ALL: number; + public static DEFAULT: number; + public static FLAGS: PermissionFlags; + public static resolve(permission?: PermissionResolvable): number; + } + + export class Presence { + constructor(client: Client, data?: object); + public activities: Activity[]; + public clientStatus: ClientPresenceStatusData | null; + public guild: Guild | null; + public readonly member: GuildMember | null; + public status: PresenceStatus; + public readonly user: User | null; + public userID: Snowflake; + public equals(presence: Presence): boolean; + } + + export class ReactionCollector extends Collector { + constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + private _handleMessageDeletion(message: Message): void; + + public message: Message; + public options: ReactionCollectorOptions; + public total: number; + public users: Collection; + + public static key(reaction: MessageReaction): Snowflake | string; + + public collect(reaction: MessageReaction): Snowflake | string; + public dispose(reaction: MessageReaction, user: User): Snowflake | string; + public empty(): void; + public endReason(): string | null; + + public on(event: 'collect' | 'dispose' | 'remove', listener: (reaction: MessageReaction, user: User) => void): this; + public on( + event: 'end', + listener: (collected: Collection, reason: string) => void, + ): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once( + event: 'collect' | 'dispose' | 'remove', + listener: (reaction: MessageReaction, user: User) => void, + ): this; + public once( + event: 'end', + listener: (collected: Collection, reason: string) => void, + ): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + export class ReactionEmoji extends Emoji { + constructor(reaction: MessageReaction, emoji: object); + public reaction: MessageReaction; + public toJSON(): object; + } + + export class RichPresenceAssets { + constructor(activity: Activity, assets: object); + public largeImage: Snowflake | null; + public largeText: string | null; + public smallImage: Snowflake | null; + public smallText: string | null; + public largeImageURL(options?: ImageURLOptions): string | null; + public smallImageURL(options?: ImageURLOptions): string | null; + } + + export class Role extends Base { + constructor(client: Client, data: object, guild: Guild); + public color: number; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public deleted: boolean; + public readonly editable: boolean; + public guild: Guild; + public readonly hexColor: string; + public hoist: boolean; + public id: Snowflake; + public managed: boolean; + public readonly members: Collection; + public mentionable: boolean; + public name: string; + public permissions: Readonly; + public readonly position: number; + public rawPosition: number; + public comparePositionTo(role: Role): number; + public delete(reason?: string): Promise; + public edit(data: RoleData, reason?: string): Promise; + public equals(role: Role): boolean; + public permissionsIn(channel: ChannelResolvable): Readonly; + public setColor(color: ColorResolvable, reason?: string): Promise; + public setHoist(hoist: boolean, reason?: string): Promise; + public setMentionable(mentionable: boolean, reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setPermissions(permissions: PermissionResolvable, reason?: string): Promise; + public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise; + public toJSON(): object; + public toString(): string; + + public static comparePositions(role1: Role, role2: Role): number; + } + + export class Shard extends EventEmitter { + constructor(manager: ShardingManager, id: number); + private _evals: Map>; + private _exitListener: (...args: any[]) => void; + private _fetches: Map>; + private _handleExit(respawn?: boolean): void; + private _handleMessage(message: any): void; + + public args: string[]; + public execArgv: string[]; + public env: object; + public id: number; + public manager: ShardingManager; + public process: ChildProcess | null; + public ready: boolean; + public worker: any | null; + public eval(script: string): Promise; + public eval(fn: (client: Client) => T): Promise; + public fetchClientValue(prop: string): Promise; + public kill(): void; + public respawn(delay?: number, spawnTimeout?: number): Promise; + public send(message: any): Promise; + public spawn(spawnTimeout?: number): Promise; + + public on(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this; + public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this; + public on(event: 'error', listener: (error: Error) => void): this; + public on(event: 'message', listener: (message: any) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this; + public once(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this; + public once(event: 'error', listener: (error: Error) => void): this; + public once(event: 'message', listener: (message: any) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + export class ShardClientUtil { + constructor(client: Client, mode: ShardingManagerMode); + private _handleMessage(message: any): void; + private _respond(type: string, message: any): void; + + public client: Client; + public readonly count: number; + public readonly ids: number[]; + public mode: ShardingManagerMode; + public parentPort: any | null; + public broadcastEval(script: string): Promise; + public broadcastEval(script: string, shard: number): Promise; + public broadcastEval(fn: (client: Client) => T): Promise; + public broadcastEval(fn: (client: Client) => T, shard: number): Promise; + public fetchClientValues(prop: string): Promise; + public fetchClientValues(prop: string, shard: number): Promise; + public respawnAll(shardDelay?: number, respawnDelay?: number, spawnTimeout?: number): Promise; + public send(message: any): Promise; + + public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil; + public static shardIDForGuildID(guildID: Snowflake, shardCount: number): number; + } + + export class ShardingManager extends EventEmitter { + constructor( + file: string, + options?: { + totalShards?: number | 'auto'; + shardList?: number[] | 'auto'; + mode?: ShardingManagerMode; + respawn?: boolean; + shardArgs?: string[]; + token?: string; + execArgv?: string[]; + }, + ); + private _performOnShards(method: string, args: any[]): Promise; + private _performOnShards(method: string, args: any[], shard: number): Promise; + + public file: string; + public respawn: boolean; + public shardArgs: string[]; + public shards: Collection; + public token: string | null; + public totalShards: number | 'auto'; + public broadcast(message: any): Promise; + public broadcastEval(script: string): Promise; + public broadcastEval(script: string, shard: number): Promise; + public createShard(id: number): Shard; + public fetchClientValues(prop: string): Promise; + public fetchClientValues(prop: string, shard: number): Promise; + public respawnAll( + shardDelay?: number, + respawnDelay?: number, + spawnTimeout?: number, + ): Promise>; + public spawn(amount?: number | 'auto', delay?: number, spawnTimeout?: number): Promise>; + + public on(event: 'shardCreate', listener: (shard: Shard) => void): this; + + public once(event: 'shardCreate', listener: (shard: Shard) => void): this; + } + + export class SnowflakeUtil { + public static deconstruct(snowflake: Snowflake): DeconstructedSnowflake; + public static generate(timestamp?: number | Date): Snowflake; + public static readonly EPOCH: number; + } + + export class Speaking extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class StoreChannel extends GuildChannel { + constructor(guild: Guild, data?: object); + public nsfw: boolean; + public type: 'store'; + } + + class StreamDispatcher extends VolumeMixin(Writable) { + constructor(player: object, options?: StreamOptions, streams?: object); + public readonly bitrateEditable: boolean; + public broadcast: VoiceBroadcast | null; + public readonly paused: boolean; + public pausedSince: number | null; + public readonly pausedTime: number; + public player: object; + public readonly streamTime: number; + public readonly totalStreamTime: number; + + public pause(silence?: boolean): void; + public resume(): void; + public setBitrate(value: number | 'auto'): boolean; + public setFEC(enabled: boolean): boolean; + public setPLP(value: number): boolean; + + public on(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this; + public on(event: 'debug', listener: (info: string) => void): this; + public on(event: 'error', listener: (err: Error) => void): this; + public on(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this; + public on(event: 'speaking', listener: (speaking: boolean) => void): this; + public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this; + public once(event: 'debug', listener: (info: string) => void): this; + public once(event: 'error', listener: (err: Error) => void): this; + public once(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this; + public once(event: 'speaking', listener: (speaking: boolean) => void): this; + public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + export class Structures { + public static get(structure: K): Extendable[K]; + public static get(structure: string): (...args: any[]) => void; + public static extend( + structure: K, + extender: (baseClass: Extendable[K]) => T, + ): T; + public static extend void>( + structure: string, + extender: (baseClass: typeof Function) => T, + ): T; + } + + export class SystemChannelFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class Team extends Base { + constructor(client: Client, data: object); + public id: Snowflake; + public name: string; + public icon: string | null; + public ownerID: Snowflake | null; + public members: Collection; + + public readonly owner: TeamMember; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + + public iconURL(options?: ImageURLOptions): string; + public toJSON(): object; + public toString(): string; + } + + export class TeamMember extends Base { + constructor(team: Team, data: object); + public team: Team; + public readonly id: Snowflake; + public permissions: string[]; + public membershipState: MembershipStates; + public user: User; + + public toString(): string; + } + + export class TextChannel extends TextBasedChannel(GuildChannel) { + constructor(guild: Guild, data?: object); + public messages: MessageManager; + public nsfw: boolean; + public type: 'text'; + public rateLimitPerUser: number; + public topic: string | null; + public createWebhook( + name: string, + options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string }, + ): Promise; + public setNSFW(nsfw: boolean, reason?: string): Promise; + public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise; + public fetchWebhooks(): Promise>; + } + + export class User extends PartialTextBasedChannel(Base) { + constructor(client: Client, data: object); + public avatar: string | null; + public bot: boolean; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public discriminator: string; + public readonly defaultAvatarURL: string; + public readonly dmChannel: DMChannel | null; + public flags: Readonly | null; + public id: Snowflake; + public lastMessageID: Snowflake | null; + public locale: string | null; + public readonly partial: false; + public readonly presence: Presence; + public system: boolean | null; + public readonly tag: string; + public username: string; + public avatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; + public createDM(): Promise; + public deleteDM(): Promise; + public displayAvatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string; + public equals(user: User): boolean; + public fetch(force?: boolean): Promise; + public fetchFlags(force?: boolean): Promise; + public toString(): string; + public typingDurationIn(channel: ChannelResolvable): number; + public typingIn(channel: ChannelResolvable): boolean; + public typingSinceIn(channel: ChannelResolvable): Date; + } + + export class UserFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; + } + + export class Util { + public static basename(path: string, ext?: string): string; + public static binaryToID(num: string): Snowflake; + public static cleanContent(str: string, message: Message): string; + public static removeMentions(str: string): string; + public static cloneObject(obj: object): object; + public static convertToBuffer(ab: ArrayBuffer | string): Buffer; + public static delayFor(ms: number): Promise; + public static discordSort( + collection: Collection, + ): Collection; + public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string; + public static escapeCodeBlock(text: string): string; + public static escapeInlineCode(text: string): string; + public static escapeBold(text: string): string; + public static escapeItalic(text: string): string; + public static escapeUnderline(text: string): string; + public static escapeStrikethrough(text: string): string; + public static escapeSpoiler(text: string): string; + public static cleanCodeBlockContent(text: string): string; + public static fetchRecommendedShards(token: string, guildsPerShard?: number): Promise; + public static flatten(obj: object, ...props: { [key: string]: boolean | string }[]): object; + public static idToBinary(num: Snowflake): string; + public static makeError(obj: { name: string; message: string; stack: string }): Error; + public static makePlainError(err: Error): { name: string; message: string; stack: string }; + public static mergeDefault(def: object, given: object): object; + public static moveElementInArray(array: any[], element: any, newIndex: number, offset?: boolean): number; + public static parseEmoji(text: string): { animated: boolean; name: string; id: string | null } | null; + public static resolveColor(color: ColorResolvable): number; + public static resolveString(data: StringResolvable): string; + public static setPosition( + item: T, + position: number, + relative: boolean, + sorted: Collection, + route: object, + reason?: string, + ): Promise<{ id: Snowflake; position: number }[]>; + public static splitMessage(text: StringResolvable, options?: SplitOptions): string[]; + public static str2ab(str: string): ArrayBuffer; + } + + class VoiceBroadcast extends EventEmitter { + constructor(client: Client); + public client: Client; + public subscribers: StreamDispatcher[]; + public readonly dispatcher: BroadcastDispatcher | null; + public play(input: string | Readable, options?: StreamOptions): BroadcastDispatcher; + public end(): void; + + public on(event: 'end', listener: () => void): this; + public on(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'end', listener: () => void): this; + public once(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + export class VoiceChannel extends GuildChannel { + constructor(guild: Guild, data?: object); + public bitrate: number; + public readonly editable: boolean; + public readonly full: boolean; + public readonly joinable: boolean; + public readonly speakable: boolean; + public type: 'voice'; + public userLimit: number; + public join(): Promise; + public leave(): void; + public setBitrate(bitrate: number, reason?: string): Promise; + public setUserLimit(userLimit: number, reason?: string): Promise; + } + + class VoiceConnection extends EventEmitter { + constructor(voiceManager: ClientVoiceManager, channel: VoiceChannel); + private authentication: object; + private sockets: object; + private ssrcMap: Map; + private _speaking: Map>; + private _disconnect(): void; + private authenticate(): void; + private authenticateFailed(reason: string): void; + private checkAuthenticated(): void; + private cleanup(): void; + private connect(): void; + private onReady(data: object): void; + private onSessionDescription(mode: string, secret: string): void; + private onSpeaking(data: object): void; + private reconnect(token: string, endpoint: string): void; + private sendVoiceStateUpdate(options: object): Promise; + private setSessionID(sessionID: string): void; + private setTokenAndEndpoint(token: string, endpoint: string): void; + private updateChannel(channel: VoiceChannel): void; + + public channel: VoiceChannel; + public readonly client: Client; + public readonly dispatcher: StreamDispatcher; + public player: object; + public receiver: VoiceReceiver; + public speaking: Readonly; + public status: VoiceStatus; + public readonly voice: VoiceState | null; + public voiceManager: ClientVoiceManager; + public disconnect(): void; + public play(input: VoiceBroadcast | Readable | string, options?: StreamOptions): StreamDispatcher; + public setSpeaking(value: BitFieldResolvable): void; + + public on(event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', listener: () => void): this; + public on(event: 'debug', listener: (message: string) => void): this; + public on(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this; + public on(event: 'speaking', listener: (user: User, speaking: Readonly) => void): this; + public on(event: 'warn', listener: (warning: string | Error) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once( + event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', + listener: () => void, + ): this; + public once(event: 'debug', listener: (message: string) => void): this; + public once(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this; + public once(event: 'speaking', listener: (user: User, speaking: Readonly) => void): this; + public once(event: 'warn', listener: (warning: string | Error) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + class VoiceReceiver extends EventEmitter { + constructor(connection: VoiceConnection); + public createStream( + user: UserResolvable, + options?: { mode?: 'opus' | 'pcm'; end?: 'silence' | 'manual' }, + ): Readable; + + public on(event: 'debug', listener: (error: Error | string) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'debug', listener: (error: Error | string) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + export class VoiceRegion { + constructor(data: object); + public custom: boolean; + public deprecated: boolean; + public id: string; + public name: string; + public optimal: boolean; + public vip: boolean; + public toJSON(): object; + } + + export class VoiceState extends Base { + constructor(guild: Guild, data: object); + public readonly channel: VoiceChannel | null; + public channelID: Snowflake | null; + public readonly connection: VoiceConnection | null; + public readonly deaf: boolean | null; + public guild: Guild; + public id: Snowflake; + public readonly member: GuildMember | null; + public readonly mute: boolean | null; + public selfDeaf: boolean | null; + public selfMute: boolean | null; + public serverDeaf: boolean | null; + public serverMute: boolean | null; + public sessionID: string | null; + public streaming: boolean; + public selfVideo: boolean; + public readonly speaking: boolean | null; + + public setDeaf(deaf: boolean, reason?: string): Promise; + public setMute(mute: boolean, reason?: string): Promise; + public kick(reason?: string): Promise; + public setChannel(channel: ChannelResolvable | null, reason?: string): Promise; + public setSelfDeaf(deaf: boolean): Promise; + public setSelfMute(mute: boolean): Promise; + } + + class VolumeInterface extends EventEmitter { + constructor(options?: { volume?: number }); + public readonly volume: number; + public readonly volumeDecibels: number; + public readonly volumeEditable: boolean; + public readonly volumeLogarithmic: number; + public setVolume(volume: number): void; + public setVolumeDecibels(db: number): void; + public setVolumeLogarithmic(value: number): void; + + public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; + + public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; + } + + export class Webhook extends WebhookMixin() { + constructor(client: Client, data?: object); + public avatar: string; + public avatarURL(options?: ImageURLOptions): string | null; + public channelID: Snowflake; + public client: Client; + public guildID: Snowflake; + public name: string; + public owner: User | object | null; + public token: string | null; + public type: WebhookTypes; + } + + export class WebhookClient extends WebhookMixin(BaseClient) { + constructor(id: string, token: string, options?: ClientOptions); + public client: this; + public token: string; + } + + export class WebSocketManager extends EventEmitter { + constructor(client: Client); + private totalShards: number | string; + private shardQueue: Set; + private packetQueue: object[]; + private destroyed: boolean; + private reconnecting: boolean; + private sessionStartLimit: { total: number; remaining: number; reset_after: number } | null; + + public readonly client: Client; + public gateway: string | null; + public shards: Collection; + public status: Status; + public readonly ping: number; + + public on(event: WSEventType, listener: (data: any, shardID: number) => void): this; + public once(event: WSEventType, listener: (data: any, shardID: number) => void): this; + + private debug(message: string, shard?: WebSocketShard): void; + private connect(): Promise; + private createShards(): Promise; + private reconnect(): Promise; + private broadcast(packet: object): void; + private destroy(): void; + private _handleSessionLimit(remaining?: number, resetAfter?: number): Promise; + private handlePacket(packet?: object, shard?: WebSocketShard): boolean; + private checkShardsReady(): Promise; + private triggerClientReady(): void; + } + + export class WebSocketShard extends EventEmitter { + constructor(manager: WebSocketManager, id: number); + private sequence: number; + private closeSequence: number; + private sessionID: string | null; + private lastPingTimestamp: number; + private lastHeartbeatAcked: boolean; + private ratelimit: { queue: object[]; total: number; remaining: number; time: 60e3; timer: NodeJS.Timeout | null }; + private connection: WebSocket | null; + private helloTimeout: NodeJS.Timeout | null; + private eventsAttached: boolean; + private expectedGuilds: Set | null; + private readyTimeout: NodeJS.Timeout | null; + + public manager: WebSocketManager; + public id: number; + public status: Status; + public ping: number; + + private debug(message: string): void; + private connect(): Promise; + private onOpen(): void; + private onMessage(event: MessageEvent): void; + private onError(error: ErrorEvent | object): void; + private onClose(event: CloseEvent): void; + private onPacket(packet: object): void; + private checkReady(): void; + private setHelloTimeout(time?: number): void; + private setHeartbeatTimer(time: number): void; + private sendHeartbeat(): void; + private ackHeartbeat(): void; + private identify(): void; + private identifyNew(): void; + private identifyResume(): void; + private _send(data: object): void; + private processQueue(): void; + private destroy(destroyOptions?: { closeCode?: number; reset?: boolean; emit?: boolean; log?: boolean }): void; + private _cleanupConnection(): void; + private _emitDestroyed(): void; + + public send(data: object): void; + public on(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this; + public on(event: 'close', listener: (event: CloseEvent) => void): this; + public on(event: 'allReady', listener: (unavailableGuilds?: Set) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this; + public once(event: 'close', listener: (event: CloseEvent) => void): this; + public once(event: 'allReady', listener: (unavailableGuilds?: Set) => void): this; + public once(event: string, listener: (...args: any[]) => void): this; + } + + //#endregion + + //#region Collections + + export class Collection extends BaseCollection { + public flatMap( + fn: (value: V, key: K, collection: this) => Collection, + thisArg?: unknown, + ): Collection; + public flatMap( + fn: (this: This, value: V, key: K, collection: this) => Collection, + thisArg: This, + ): Collection; + public mapValues(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): Collection; + public mapValues( + fn: (this: This, value: V, key: K, collection: this) => T, + thisArg: This, + ): Collection; + public toJSON(): object; + } + + //#endregion + + //#region Managers + + export class ChannelManager extends BaseManager { + constructor(client: Client, iterable: Iterable); + public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; + } + + export abstract class BaseManager { + constructor(client: Client, iterable: Iterable, holds: Constructable, cacheType: Collection); + public holds: Constructable; + public cache: Collection; + public cacheType: Collection; + public readonly client: Client; + public add(data: any, cache?: boolean, { id, extras }?: { id: K; extras: any[] }): Holds; + public resolve(resolvable: R): Holds | null; + public resolveID(resolvable: R): K | null; + public valueOf(): Collection; + } + + export class GuildChannelManager extends BaseManager { + constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create(name: string, options: GuildCreateChannelOptions & { type: 'voice' }): Promise; + public create(name: string, options: GuildCreateChannelOptions & { type: 'category' }): Promise; + public create(name: string, options?: GuildCreateChannelOptions & { type?: 'text' }): Promise; + public create( + name: string, + options: GuildCreateChannelOptions, + ): Promise; + } + + export class GuildEmojiManager extends BaseManager { + constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create( + attachment: BufferResolvable | Base64Resolvable, + name: string, + options?: GuildEmojiCreateOptions, + ): Promise; + public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null; + } + + export class GuildEmojiRoleManager { + constructor(emoji: GuildEmoji); + public emoji: GuildEmoji; + public guild: Guild; + public cache: Collection; + public add( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + ): Promise; + public set(roles: readonly RoleResolvable[] | Collection): Promise; + public remove( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + ): Promise; + } + + export class GuildManager extends BaseManager { + constructor(client: Client, iterable?: Iterable); + public create(name: string, options?: GuildCreateOptions): Promise; + public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; + } + + export class GuildMemberManager extends BaseManager { + constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public ban(user: UserResolvable, options?: BanOptions): Promise; + public fetch( + options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }), + ): Promise; + public fetch(options?: FetchMembersOptions): Promise>; + public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise; + public prune(options?: GuildPruneMembersOptions): Promise; + public unban(user: UserResolvable, reason?: string): Promise; + } + + export class GuildMemberRoleManager extends OverridableManager { + constructor(member: GuildMember); + public readonly hoist: Role | null; + public readonly color: Role | null; + public readonly highest: Role; + public member: GuildMember; + public guild: Guild; + + public add( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + reason?: string, + ): Promise; + public set(roles: readonly RoleResolvable[] | Collection, reason?: string): Promise; + public remove( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + reason?: string, + ): Promise; + } + + export class MessageManager extends BaseManager { + constructor(channel: TextChannel | DMChannel, iterable?: Iterable); + public channel: TextBasedChannelFields; + public cache: Collection; + public fetch(message: Snowflake, cache?: boolean, force?: boolean): Promise; + public fetch( + options?: ChannelLogsQueryOptions, + cache?: boolean, + force?: boolean, + ): Promise>; + public fetchPinned(cache?: boolean): Promise>; + public delete(message: MessageResolvable, reason?: string): Promise; + } + + // Hacky workaround because changing the signature of an overridden method errors + class OverridableManager extends BaseManager { + public add(data: any, cache: any): any; + public set(key: any): any; + } + + export class PresenceManager extends BaseManager { + constructor(client: Client, iterable?: Iterable); + } + + export class ReactionManager extends BaseManager { + constructor(message: Message, iterable?: Iterable); + public message: Message; + public removeAll(): Promise; + } + + export class ReactionUserManager extends BaseManager { + constructor(client: Client, iterable: Iterable | undefined, reaction: MessageReaction); + public reaction: MessageReaction; + public fetch(options?: { + limit?: number; + after?: Snowflake; + before?: Snowflake; + }): Promise>; + public remove(user?: UserResolvable): Promise; + } + + export class RoleManager extends BaseManager { + constructor(guild: Guild, iterable?: Iterable); + public readonly everyone: Role; + public readonly highest: Role; + public guild: Guild; + + public create(options?: { data?: RoleData; reason?: string }): Promise; + public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; + public fetch(id?: Snowflake, cache?: boolean, force?: boolean): Promise; + } + + export class UserManager extends BaseManager { + constructor(client: Client, iterable?: Iterable); + public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; + } + + export class VoiceStateManager extends BaseManager { + constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + } + + //#endregion + + //#region Mixins + + // Model the TextBasedChannel mixin system, allowing application of these fields + // to the classes that use these methods without having to manually add them + // to each of those classes + + type Constructable = new (...args: any[]) => T; + function PartialTextBasedChannel(Base?: Constructable): Constructable; + function TextBasedChannel( + Base?: Constructable, + ignore?: I[], + ): Constructable>; + + interface PartialTextBasedChannelFields { + lastMessageID: Snowflake | null; + readonly lastMessage: Message | null; + send( + content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + send(options: MessageOptions & { split: true | SplitOptions }): Promise; + send(options: MessageOptions | APIMessage): Promise; + send(content: StringResolvable, options: (MessageOptions & { split?: false }) | MessageAdditions): Promise; + send(content: StringResolvable, options: MessageOptions & { split: true | SplitOptions }): Promise; + send(content: StringResolvable, options: MessageOptions): Promise; + } + + interface TextBasedChannelFields extends PartialTextBasedChannelFields { + _typing: Map; + lastPinTimestamp: number | null; + readonly lastPinAt: Date | null; + typing: boolean; + typingCount: number; + awaitMessages(filter: CollectorFilter, options?: AwaitMessagesOptions): Promise>; + bulkDelete( + messages: Collection | readonly MessageResolvable[] | number, + filterOld?: boolean, + ): Promise>; + createMessageCollector(filter: CollectorFilter, options?: MessageCollectorOptions): MessageCollector; + startTyping(count?: number): Promise; + stopTyping(force?: boolean): void; + } + + function WebhookMixin(Base?: Constructable): Constructable; + + function VolumeMixin(base: Constructable): Constructable; + + interface WebhookFields { + id: Snowflake; + readonly createdAt: Date; + readonly createdTimestamp: number; + readonly url: string; + delete(reason?: string): Promise; + edit(options: WebhookEditData): Promise; + send( + content: APIMessageContentResolvable | (WebhookMessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + send(options: WebhookMessageOptions & { split: true | SplitOptions }): Promise; + send(options: WebhookMessageOptions | APIMessage): Promise; + send( + content: StringResolvable, + options: (WebhookMessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + send( + content: StringResolvable, + options: WebhookMessageOptions & { split: true | SplitOptions }, + ): Promise; + send(content: StringResolvable, options: WebhookMessageOptions): Promise; + sendSlackMessage(body: object): Promise; + } + + //#endregion + + //#region Typedefs + + type ActivityFlagsString = 'INSTANCE' | 'JOIN' | 'SPECTATE' | 'JOIN_REQUEST' | 'SYNC' | 'PLAY'; + + interface ActivityOptions { + name?: string; + url?: string; + type?: ActivityType | number; + shardID?: number | readonly number[]; + } + + type ActivityType = 'PLAYING' | 'STREAMING' | 'LISTENING' | 'WATCHING' | 'CUSTOM_STATUS' | 'COMPETING'; + + interface AddGuildMemberOptions { + accessToken: string; + nick?: string; + roles?: Collection | RoleResolvable[]; + mute?: boolean; + deaf?: boolean; + } + + interface APIErrors { + UNKNOWN_ACCOUNT: 10001; + UNKNOWN_APPLICATION: 10002; + UNKNOWN_CHANNEL: 10003; + UNKNOWN_GUILD: 10004; + UNKNOWN_INTEGRATION: 10005; + UNKNOWN_INVITE: 10006; + UNKNOWN_MEMBER: 10007; + UNKNOWN_MESSAGE: 10008; + UNKNOWN_OVERWRITE: 10009; + UNKNOWN_PROVIDER: 10010; + UNKNOWN_ROLE: 10011; + UNKNOWN_TOKEN: 10012; + UNKNOWN_USER: 10013; + UNKNOWN_EMOJI: 10014; + UNKNOWN_WEBHOOK: 10015; + UNKNOWN_BAN: 10026; + UNKNOWN_GUILD_TEMPLATE: 10057; + BOT_PROHIBITED_ENDPOINT: 20001; + BOT_ONLY_ENDPOINT: 20002; + CHANNEL_HIT_WRITE_RATELIMIT: 20028; + MAXIMUM_GUILDS: 30001; + MAXIMUM_FRIENDS: 30002; + MAXIMUM_PINS: 30003; + MAXIMUM_ROLES: 30005; + MAXIMUM_WEBHOOKS: 30007; + MAXIMUM_REACTIONS: 30010; + MAXIMUM_CHANNELS: 30013; + MAXIMUM_ATTACHMENTS: 30015; + MAXIMUM_INVITES: 30016; + GUILD_ALREADY_HAS_TEMPLATE: 30031; + UNAUTHORIZED: 40001; + ACCOUNT_VERIFICATION_REQUIRED: 40002; + REQUEST_ENTITY_TOO_LARGE: 40005; + FEATURE_TEMPORARILY_DISABLED: 40006; + USER_BANNED: 40007; + ALREADY_CROSSPOSTED: 40033; + MISSING_ACCESS: 50001; + INVALID_ACCOUNT_TYPE: 50002; + CANNOT_EXECUTE_ON_DM: 50003; + EMBED_DISABLED: 50004; + CANNOT_EDIT_MESSAGE_BY_OTHER: 50005; + CANNOT_SEND_EMPTY_MESSAGE: 50006; + CANNOT_MESSAGE_USER: 50007; + CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008; + CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009; + OAUTH2_APPLICATION_BOT_ABSENT: 50010; + MAXIMUM_OAUTH2_APPLICATIONS: 50011; + INVALID_OAUTH_STATE: 50012; + MISSING_PERMISSIONS: 50013; + INVALID_AUTHENTICATION_TOKEN: 50014; + NOTE_TOO_LONG: 50015; + INVALID_BULK_DELETE_QUANTITY: 50016; + CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019; + INVALID_OR_TAKEN_INVITE_CODE: 50020; + CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021; + INVALID_OAUTH_TOKEN: 50025; + BULK_DELETE_MESSAGE_TOO_OLD: 50034; + INVALID_FORM_BODY: 50035; + INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036; + INVALID_API_VERSION: 50041; + CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074; + REACTION_BLOCKED: 90001; + RESOURCE_OVERLOADED: 130000; + } + + type APIMessageContentResolvable = string | number | boolean | bigint | symbol | readonly StringResolvable[]; + + interface ApplicationAsset { + name: string; + id: Snowflake; + type: 'BIG' | 'SMALL'; + } + + interface AuditLogChange { + key: string; + old?: any; + new?: any; + } + + interface AwaitMessagesOptions extends MessageCollectorOptions { + errors?: string[]; + } + + interface AwaitReactionsOptions extends ReactionCollectorOptions { + errors?: string[]; + } + + interface BanOptions { + days?: number; + reason?: string; + } + + type Base64Resolvable = Buffer | Base64String; + + type Base64String = string; + + type BitFieldResolvable = + | RecursiveReadonlyArray>> + | T + | number + | Readonly>; + + type BufferResolvable = Buffer | string; + + interface ChannelCreationOverwrites { + allow?: PermissionResolvable | number; + deny?: PermissionResolvable | number; + id: RoleResolvable | UserResolvable; + } + + interface ChannelData { + name?: string; + position?: number; + topic?: string; + nsfw?: boolean; + bitrate?: number; + userLimit?: number; + parentID?: Snowflake | null; + rateLimitPerUser?: number; + lockPermissions?: boolean; + permissionOverwrites?: readonly OverwriteResolvable[] | Collection; + } + + interface ChannelLogsQueryOptions { + limit?: number; + before?: Snowflake; + after?: Snowflake; + around?: Snowflake; + } + + interface ChannelPosition { + channel: ChannelResolvable; + position: number; + } + + type ChannelResolvable = Channel | Snowflake; + + interface ClientEvents { + channelCreate: [Channel]; + channelDelete: [Channel | PartialDMChannel]; + channelPinsUpdate: [Channel | PartialDMChannel, Date]; + channelUpdate: [Channel, Channel]; + debug: [string]; + warn: [string]; + disconnect: [any, number]; + emojiCreate: [GuildEmoji]; + emojiDelete: [GuildEmoji]; + emojiUpdate: [GuildEmoji, GuildEmoji]; + error: [Error]; + guildBanAdd: [Guild, User]; + guildBanRemove: [Guild, User]; + guildCreate: [Guild]; + guildDelete: [Guild]; + guildUnavailable: [Guild]; + guildIntegrationsUpdate: [Guild]; + guildMemberAdd: [GuildMember]; + guildMemberAvailable: [GuildMember | PartialGuildMember]; + guildMemberRemove: [GuildMember | PartialGuildMember]; + guildMembersChunk: [ + Collection, + Guild, + { count: number; index: number; nonce: string | undefined }, + ]; + guildMemberSpeaking: [GuildMember | PartialGuildMember, Readonly]; + guildMemberUpdate: [GuildMember | PartialGuildMember, GuildMember]; + guildUpdate: [Guild, Guild]; + inviteCreate: [Invite]; + inviteDelete: [Invite]; + message: [Message]; + messageDelete: [Message | PartialMessage]; + messageReactionRemoveAll: [Message | PartialMessage]; + messageReactionRemoveEmoji: [MessageReaction]; + messageDeleteBulk: [Collection]; + messageReactionAdd: [MessageReaction, User | PartialUser]; + messageReactionRemove: [MessageReaction, User | PartialUser]; + messageUpdate: [Message | PartialMessage, Message | PartialMessage]; + presenceUpdate: [Presence | undefined, Presence]; + rateLimit: [RateLimitData]; + ready: []; + invalidated: []; + roleCreate: [Role]; + roleDelete: [Role]; + roleUpdate: [Role, Role]; + typingStart: [Channel | PartialDMChannel, User | PartialUser]; + userUpdate: [User | PartialUser, User]; + voiceStateUpdate: [VoiceState, VoiceState]; + webhookUpdate: [TextChannel]; + shardDisconnect: [CloseEvent, number]; + shardError: [Error, number]; + shardReady: [number, Set | undefined]; + shardReconnecting: [number]; + shardResume: [number, number]; + } + + interface ClientOptions { + shards?: number | number[] | 'auto'; + shardCount?: number; + messageCacheMaxSize?: number; + messageCacheLifetime?: number; + messageSweepInterval?: number; + messageEditHistoryMaxSize?: number; + fetchAllMembers?: boolean; + disableMentions?: 'none' | 'all' | 'everyone'; + allowedMentions?: MessageMentionOptions; + partials?: PartialTypes[]; + restWsBridgeTimeout?: number; + restTimeOffset?: number; + restRequestTimeout?: number; + restSweepInterval?: number; + retryLimit?: number; + presence?: PresenceData; + ws?: WebSocketOptions; + http?: HTTPOptions; + } + + type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; + + interface ClientPresenceStatusData { + web?: ClientPresenceStatus; + mobile?: ClientPresenceStatus; + desktop?: ClientPresenceStatus; + } + + interface CloseEvent { + wasClean: boolean; + code: number; + reason: string; + target: WebSocket; + } + + type CollectorFilter = (...args: any[]) => boolean | Promise; + + interface CollectorOptions { + time?: number; + idle?: number; + dispose?: boolean; + } + + type ColorResolvable = + | 'DEFAULT' + | 'WHITE' + | 'AQUA' + | 'GREEN' + | 'BLUE' + | 'YELLOW' + | 'PURPLE' + | 'LUMINOUS_VIVID_PINK' + | 'GOLD' + | 'ORANGE' + | 'RED' + | 'GREY' + | 'DARKER_GREY' + | 'NAVY' + | 'DARK_AQUA' + | 'DARK_GREEN' + | 'DARK_BLUE' + | 'DARK_PURPLE' + | 'DARK_VIVID_PINK' + | 'DARK_GOLD' + | 'DARK_ORANGE' + | 'DARK_RED' + | 'DARK_GREY' + | 'LIGHT_GREY' + | 'DARK_NAVY' + | 'BLURPLE' + | 'GREYPLE' + | 'DARK_BUT_NOT_BLACK' + | 'NOT_QUITE_BLACK' + | 'RANDOM' + | [number, number, number] + | number + | string; + + interface CrosspostedChannel { + channelID: Snowflake; + guildID: Snowflake; + type: keyof typeof ChannelType; + name: string; + } + + interface DeconstructedSnowflake { + timestamp: number; + readonly date: Date; + workerID: number; + processID: number; + increment: number; + binary: string; + } + + type DefaultMessageNotifications = 'ALL' | 'MENTIONS'; + + interface EmbedField { + name: string; + value: string; + inline: boolean; + } + + interface EmbedFieldData { + name: StringResolvable; + value: StringResolvable; + inline?: boolean; + } + + type EmojiIdentifierResolvable = string | EmojiResolvable; + + type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji; + + interface ErrorEvent { + error: any; + message: string; + type: string; + target: WebSocket; + } + + interface EscapeMarkdownOptions { + codeBlock?: boolean; + inlineCode?: boolean; + bold?: boolean; + italic?: boolean; + underline?: boolean; + strikethrough?: boolean; + spoiler?: boolean; + inlineCodeContent?: boolean; + codeBlockContent?: boolean; + } + + type ExplicitContentFilterLevel = 'DISABLED' | 'MEMBERS_WITHOUT_ROLES' | 'ALL_MEMBERS'; + + interface Extendable { + GuildEmoji: typeof GuildEmoji; + DMChannel: typeof DMChannel; + TextChannel: typeof TextChannel; + VoiceChannel: typeof VoiceChannel; + CategoryChannel: typeof CategoryChannel; + NewsChannel: typeof NewsChannel; + StoreChannel: typeof StoreChannel; + GuildMember: typeof GuildMember; + Guild: typeof Guild; + Message: typeof Message; + MessageReaction: typeof MessageReaction; + Presence: typeof Presence; + VoiceState: typeof VoiceState; + Role: typeof Role; + User: typeof User; + } + + interface FetchIntegrationsOptions { + includeApplications?: boolean; + } + + interface FetchMemberOptions { + user: UserResolvable; + cache?: boolean; + force?: boolean; + } + + interface FetchMembersOptions { + user?: UserResolvable | UserResolvable[]; + query?: string; + limit?: number; + withPresences?: boolean; + time?: number; + nonce?: string; + force?: boolean; + } + + interface FileOptions { + attachment: BufferResolvable | Stream; + name?: string; + } + + type GuildAuditLogsAction = keyof GuildAuditLogsActions; + + interface GuildAuditLogsActions { + ALL?: null; + GUILD_UPDATE?: number; + CHANNEL_CREATE?: number; + CHANNEL_UPDATE?: number; + CHANNEL_DELETE?: number; + CHANNEL_OVERWRITE_CREATE?: number; + CHANNEL_OVERWRITE_UPDATE?: number; + CHANNEL_OVERWRITE_DELETE?: number; + MEMBER_KICK?: number; + MEMBER_PRUNE?: number; + MEMBER_BAN_ADD?: number; + MEMBER_BAN_REMOVE?: number; + MEMBER_UPDATE?: number; + MEMBER_ROLE_UPDATE?: number; + MEMBER_MOVE?: number; + MEMBER_DISCONNECT?: number; + BOT_ADD?: number; + ROLE_CREATE?: number; + ROLE_UPDATE?: number; + ROLE_DELETE?: number; + INVITE_CREATE?: number; + INVITE_UPDATE?: number; + INVITE_DELETE?: number; + WEBHOOK_CREATE?: number; + WEBHOOK_UPDATE?: number; + WEBHOOK_DELETE?: number; + EMOJI_CREATE?: number; + EMOJI_UPDATE?: number; + EMOJI_DELETE?: number; + MESSAGE_DELETE?: number; + MESSAGE_BULK_DELETE?: number; + MESSAGE_PIN?: number; + MESSAGE_UNPIN?: number; + INTEGRATION_CREATE?: number; + INTEGRATION_UPDATE?: number; + INTEGRATION_DELETE?: number; + } + + type GuildAuditLogsActionType = 'CREATE' | 'DELETE' | 'UPDATE' | 'ALL'; + + interface GuildAuditLogsFetchOptions { + before?: Snowflake | GuildAuditLogsEntry; + limit?: number; + user?: UserResolvable; + type?: GuildAuditLogsAction | number; + } + + type GuildAuditLogsTarget = keyof GuildAuditLogsTargets; + + interface GuildAuditLogsTargets { + ALL?: string; + GUILD?: string; + CHANNEL?: string; + USER?: string; + ROLE?: string; + INVITE?: string; + WEBHOOK?: string; + EMOJI?: string; + MESSAGE?: string; + INTEGRATION?: string; + UNKNOWN?: string; + } + + type GuildChannelResolvable = Snowflake | GuildChannel; + + interface GuildCreateChannelOptions { + permissionOverwrites?: OverwriteResolvable[] | Collection; + topic?: string; + type?: Exclude< + keyof typeof ChannelType | ChannelType, + 'dm' | 'group' | 'unknown' | ChannelType.dm | ChannelType.group | ChannelType.unknown + >; + nsfw?: boolean; + parent?: ChannelResolvable; + bitrate?: number; + userLimit?: number; + rateLimitPerUser?: number; + position?: number; + reason?: string; + } + + interface GuildChannelCloneOptions extends GuildCreateChannelOptions { + name?: string; + } + + interface GuildCreateOptions { + afkChannelID?: number; + afkTimeout?: number; + channels?: PartialChannelData[]; + defaultMessageNotifications?: DefaultMessageNotifications | number; + explicitContentFilter?: ExplicitContentFilterLevel | number; + icon?: BufferResolvable | Base64Resolvable | null; + region?: string; + roles?: PartialRoleData[]; + systemChannelID?: number; + verificationLevel?: VerificationLevel | number; + } + + interface GuildWidget { + enabled: boolean; + channel: GuildChannel | null; + } + + interface GuildEditData { + name?: string; + region?: string; + verificationLevel?: VerificationLevel | number; + explicitContentFilter?: ExplicitContentFilterLevel | number; + defaultMessageNotifications?: DefaultMessageNotifications | number; + afkChannel?: ChannelResolvable; + systemChannel?: ChannelResolvable; + systemChannelFlags?: SystemChannelFlagsResolvable; + afkTimeout?: number; + icon?: Base64Resolvable; + owner?: GuildMemberResolvable; + splash?: Base64Resolvable; + discoverySplash?: Base64Resolvable; + banner?: Base64Resolvable; + rulesChannel?: ChannelResolvable; + publicUpdatesChannel?: ChannelResolvable; + preferredLocale?: string; + } + + interface GuildEmojiCreateOptions { + roles?: Collection | RoleResolvable[]; + reason?: string; + } + + interface GuildEmojiEditData { + name?: string; + roles?: Collection | RoleResolvable[]; + } + + type GuildFeatures = + | 'ANIMATED_ICON' + | 'BANNER' + | 'COMMERCE' + | 'COMMUNITY' + | 'DISCOVERABLE' + | 'FEATURABLE' + | 'INVITE_SPLASH' + | 'NEWS' + | 'PARTNERED' + | 'RELAY_ENABLED' + | 'VANITY_URL' + | 'VERIFIED' + | 'VIP_REGIONS' + | 'WELCOME_SCREEN_ENABLED'; + + interface GuildMemberEditData { + nick?: string; + roles?: Collection | readonly RoleResolvable[]; + mute?: boolean; + deaf?: boolean; + channel?: ChannelResolvable | null; + } + + type GuildMemberResolvable = GuildMember | UserResolvable; + + type GuildResolvable = Guild | GuildChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake; + + interface GuildPruneMembersOptions { + count?: boolean; + days?: number; + dry?: boolean; + reason?: string; + roles?: RoleResolvable[]; + } + + interface GuildWidgetData { + enabled: boolean; + channel: GuildChannelResolvable | null; + } + + interface HTTPOptions { + api?: string; + version?: number; + host?: string; + cdn?: string; + invite?: string; + template?: string; + } + + type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096; + + interface ImageURLOptions { + format?: AllowedImageFormat; + size?: ImageSize; + } + + interface IntegrationData { + id: string; + type: string; + } + + interface IntegrationEditData { + expireBehavior?: number; + expireGracePeriod?: number; + } + + interface IntegrationAccount { + id: string; + name: string; + } + + type IntentsString = + | 'GUILDS' + | 'GUILD_MEMBERS' + | 'GUILD_BANS' + | 'GUILD_EMOJIS' + | 'GUILD_INTEGRATIONS' + | 'GUILD_WEBHOOKS' + | 'GUILD_INVITES' + | 'GUILD_VOICE_STATES' + | 'GUILD_PRESENCES' + | 'GUILD_MESSAGES' + | 'GUILD_MESSAGE_REACTIONS' + | 'GUILD_MESSAGE_TYPING' + | 'DIRECT_MESSAGES' + | 'DIRECT_MESSAGE_REACTIONS' + | 'DIRECT_MESSAGE_TYPING'; + + interface InviteGenerationOptions { + permissions?: PermissionResolvable; + guild?: GuildResolvable; + disableGuildSelect?: boolean; + } + + interface InviteOptions { + temporary?: boolean; + maxAge?: number; + maxUses?: number; + unique?: boolean; + reason?: string; + } + + type InviteResolvable = string; + + type GuildTemplateResolvable = string; + + type MembershipStates = 'INVITED' | 'ACCEPTED'; + + type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[]; + + interface MessageActivity { + partyID: string; + type: number; + } + + interface MessageCollectorOptions extends CollectorOptions { + max?: number; + maxProcessed?: number; + } + + interface MessageEditOptions { + content?: StringResolvable; + embed?: MessageEmbed | MessageEmbedOptions | null; + code?: string | boolean; + flags?: BitFieldResolvable; + allowedMentions?: MessageMentionOptions; + } + + interface MessageEmbedAuthor { + name?: string; + url?: string; + iconURL?: string; + proxyIconURL?: string; + } + + interface MessageEmbedFooter { + text?: string; + iconURL?: string; + proxyIconURL?: string; + } + + interface MessageEmbedImage { + url: string; + proxyURL?: string; + height?: number; + width?: number; + } + + interface MessageEmbedOptions { + title?: string; + description?: string; + url?: string; + timestamp?: Date | number; + color?: ColorResolvable; + fields?: EmbedFieldData[]; + files?: (MessageAttachment | string | FileOptions)[]; + author?: Partial & { icon_url?: string; proxy_icon_url?: string }; + thumbnail?: Partial & { proxy_url?: string }; + image?: Partial & { proxy_url?: string }; + video?: Partial & { proxy_url?: string }; + footer?: Partial & { icon_url?: string; proxy_icon_url?: string }; + } + + interface MessageEmbedProvider { + name: string; + url: string; + } + + interface MessageEmbedThumbnail { + url: string; + proxyURL?: string; + height?: number; + width?: number; + } + + interface MessageEmbedVideo { + url?: string; + proxyURL?: string; + height?: number; + width?: number; + } + + interface MessageEvent { + data: WebSocket.Data; + type: string; + target: WebSocket; + } + + type MessageFlagsString = 'CROSSPOSTED' | 'IS_CROSSPOST' | 'SUPPRESS_EMBEDS' | 'SOURCE_MESSAGE_DELETED' | 'URGENT'; + + interface MessageMentionOptions { + parse?: MessageMentionTypes[]; + roles?: Snowflake[]; + users?: Snowflake[]; + } + + type MessageMentionTypes = 'roles' | 'users' | 'everyone'; + + interface MessageOptions { + tts?: boolean; + nonce?: string; + content?: StringResolvable; + embed?: MessageEmbed | MessageEmbedOptions; + disableMentions?: 'none' | 'all' | 'everyone'; + allowedMentions?: MessageMentionOptions; + files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; + code?: string | boolean; + split?: boolean | SplitOptions; + reply?: UserResolvable; + } + + type MessageReactionResolvable = MessageReaction | Snowflake; + + interface MessageReference { + channelID: string; + guildID: string; + messageID: string | null; + } + + type MessageResolvable = Message | Snowflake; + + type MessageTarget = TextChannel | NewsChannel | DMChannel | User | GuildMember | Webhook | WebhookClient; + + type MessageType = + | 'DEFAULT' + | 'RECIPIENT_ADD' + | 'RECIPIENT_REMOVE' + | 'CALL' + | 'CHANNEL_NAME_CHANGE' + | 'CHANNEL_ICON_CHANGE' + | 'PINS_ADD' + | 'GUILD_MEMBER_JOIN' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3' + | 'CHANNEL_FOLLOW_ADD' + | 'GUILD_DISCOVERY_DISQUALIFIED' + | 'GUILD_DISCOVERY_REQUALIFIED'; + + interface OverwriteData { + allow?: PermissionResolvable; + deny?: PermissionResolvable; + id: GuildMemberResolvable | RoleResolvable; + type?: OverwriteType; + } + + type OverwriteResolvable = PermissionOverwrites | OverwriteData; + + type OverwriteType = 'member' | 'role'; + + interface PermissionFlags extends Record {} + + interface PermissionObject extends Record {} + + interface PermissionOverwriteOption extends Partial> {} + + type PermissionResolvable = BitFieldResolvable; + + type PermissionString = + | 'CREATE_INSTANT_INVITE' + | 'KICK_MEMBERS' + | 'BAN_MEMBERS' + | 'ADMINISTRATOR' + | 'MANAGE_CHANNELS' + | 'MANAGE_GUILD' + | 'ADD_REACTIONS' + | 'VIEW_AUDIT_LOG' + | 'PRIORITY_SPEAKER' + | 'STREAM' + | 'VIEW_CHANNEL' + | 'SEND_MESSAGES' + | 'SEND_TTS_MESSAGES' + | 'MANAGE_MESSAGES' + | 'EMBED_LINKS' + | 'ATTACH_FILES' + | 'READ_MESSAGE_HISTORY' + | 'MENTION_EVERYONE' + | 'USE_EXTERNAL_EMOJIS' + | 'VIEW_GUILD_INSIGHTS' + | 'CONNECT' + | 'SPEAK' + | 'MUTE_MEMBERS' + | 'DEAFEN_MEMBERS' + | 'MOVE_MEMBERS' + | 'USE_VAD' + | 'CHANGE_NICKNAME' + | 'MANAGE_NICKNAMES' + | 'MANAGE_ROLES' + | 'MANAGE_WEBHOOKS' + | 'MANAGE_EMOJIS'; + + interface RecursiveArray extends ReadonlyArray> {} + + type RecursiveReadonlyArray = ReadonlyArray>; + + interface PermissionOverwriteOptions { + allow: PermissionResolvable; + deny: PermissionResolvable; + id: UserResolvable | RoleResolvable; + } + + type PremiumTier = number; + + interface PresenceData { + status?: PresenceStatusData; + afk?: boolean; + activity?: { + name?: string; + type?: ActivityType | number; + url?: string; + }; + shardID?: number | number[]; + } + + type PresenceResolvable = Presence | UserResolvable | Snowflake; + + type Partialize = { + readonly client: Client; + readonly createdAt: Date; + readonly createdTimestamp: number; + deleted: boolean; + id: string; + partial: true; + fetch(): Promise; + } & { + [K in keyof Omit< + T, + 'client' | 'createdAt' | 'createdTimestamp' | 'id' | 'partial' | 'fetch' | 'deleted' | O + >]: T[K] extends Function ? T[K] : T[K] | null; // tslint:disable-line:ban-types + }; + + interface PartialDMChannel + extends Partialize< + DMChannel, + 'lastMessage' | 'lastMessageID' | 'messages' | 'recipient' | 'type' | 'typing' | 'typingCount' + > { + lastMessage: null; + lastMessageID: undefined; + messages: MessageManager; + recipient: User | PartialUser; + type: 'dm'; + readonly typing: boolean; + readonly typingCount: number; + } + + interface PartialChannelData { + id?: number; + name: string; + topic?: string; + type?: ChannelType; + parentID?: number; + permissionOverwrites?: { + id: number | Snowflake; + type?: OverwriteType; + allow?: PermissionResolvable; + deny?: PermissionResolvable; + }[]; + } + + interface PartialGuildMember + extends Partialize< + GuildMember, + | 'bannable' + | 'displayColor' + | 'displayHexColor' + | 'displayName' + | 'guild' + | 'kickable' + | 'permissions' + | 'roles' + | 'manageable' + | 'presence' + | 'voice' + > { + readonly bannable: boolean; + readonly displayColor: number; + readonly displayHexColor: string; + readonly displayName: string; + guild: Guild; + readonly manageable: boolean; + joinedAt: null; + joinedTimestamp: null; + readonly kickable: boolean; + readonly permissions: GuildMember['permissions']; + readonly presence: GuildMember['presence']; + readonly roles: GuildMember['roles']; + readonly voice: GuildMember['voice']; + } + + interface PartialMessage + extends Partialize< + Message, + | 'attachments' + | 'channel' + | 'deletable' + | 'crosspostable' + | 'editable' + | 'mentions' + | 'pinnable' + | 'url' + | 'flags' + | 'edits' + | 'embeds' + > { + attachments: Message['attachments']; + channel: Message['channel']; + readonly deletable: boolean; + readonly crosspostable: boolean; + readonly editable: boolean; + readonly edits: Message['edits']; + embeds: Message['embeds']; + flags: Message['flags']; + mentions: Message['mentions']; + readonly pinnable: boolean; + reactions: Message['reactions']; + readonly url: string; + } + + interface PartialRoleData extends RoleData { + id?: number; + } + + type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION'; + + interface PartialUser + extends Omit, 'deleted'> { + bot: User['bot']; + flags: User['flags']; + locale: User['locale']; + system: User['system']; + readonly tag: null; + username: null; + } + + type PresenceStatusData = ClientPresenceStatus | 'invisible'; + + type PresenceStatus = PresenceStatusData | 'offline'; + + interface RateLimitData { + timeout: number; + limit: number; + timeDifference: number; + method: string; + path: string; + route: string; + } + + interface RawOverwriteData { + id: Snowflake; + allow: number; + deny: number; + type: OverwriteType; + } + + interface ReactionCollectorOptions extends CollectorOptions { + max?: number; + maxEmojis?: number; + maxUsers?: number; + } + + interface ResolvedOverwriteOptions { + allow: Permissions; + deny: Permissions; + } + + interface RoleData { + name?: string; + color?: ColorResolvable; + hoist?: boolean; + position?: number; + permissions?: PermissionResolvable; + mentionable?: boolean; + } + + interface RolePosition { + role: RoleResolvable; + position: number; + } + + type RoleResolvable = Role | string; + + type ShardingManagerMode = 'process' | 'worker'; + + type Snowflake = string; + + interface SplitOptions { + maxLength?: number; + char?: string; + prepend?: string; + append?: string; + } + + type Status = number; + + interface StreamOptions { + type?: StreamType; + seek?: number; + volume?: number | boolean; + plp?: number; + fec?: boolean; + bitrate?: number | 'auto'; + highWaterMark?: number; + } + + type SpeakingString = 'SPEAKING' | 'SOUNDSHARE' | 'PRIORITY_SPEAKING'; + + type StreamType = 'unknown' | 'converted' | 'opus' | 'ogg/opus' | 'webm/opus'; + + type StringResolvable = string | string[] | any; + + type SystemChannelFlagsString = 'WELCOME_MESSAGE_DISABLED' | 'BOOST_MESSAGE_DISABLED'; + + type SystemChannelFlagsResolvable = BitFieldResolvable; + + type TargetUser = number; + + interface TypingData { + user: User | PartialUser; + since: Date; + lastTimestamp: Date; + elapsedTime: number; + timeout: NodeJS.Timeout; + } + + type UserFlagsString = + | 'DISCORD_EMPLOYEE' + | 'PARTNERED_SERVER_OWNER' + | 'DISCORD_PARTNER' + | 'HYPESQUAD_EVENTS' + | 'BUGHUNTER_LEVEL_1' + | 'HOUSE_BRAVERY' + | 'HOUSE_BRILLIANCE' + | 'HOUSE_BALANCE' + | 'EARLY_SUPPORTER' + | 'TEAM_USER' + | 'SYSTEM' + | 'BUGHUNTER_LEVEL_2' + | 'VERIFIED_BOT' + | 'EARLY_VERIFIED_DEVELOPER' + | 'VERIFIED_DEVELOPER'; + + type UserResolvable = User | Snowflake | Message | GuildMember; + + type VerificationLevel = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'VERY_HIGH'; + + type VoiceStatus = number; + + interface WebhookEditData { + name?: string; + avatar?: BufferResolvable; + channel?: ChannelResolvable; + reason?: string; + } + + interface WebhookMessageOptions { + username?: string; + avatarURL?: string; + tts?: boolean; + nonce?: string; + embeds?: (MessageEmbed | object)[]; + disableMentions?: 'none' | 'all' | 'everyone'; + allowedMentions?: MessageMentionOptions; + files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; + code?: string | boolean; + split?: boolean | SplitOptions; + } + + type WebhookTypes = 'Incoming' | 'Channel Follower'; + + interface WebSocketOptions { + large_threshold?: number; + compress?: boolean; + intents?: BitFieldResolvable | number; + properties?: WebSocketProperties; + } + + interface WebSocketProperties { + $os?: string; + $browser?: string; + $device?: string; + } + + type WSEventType = + | 'READY' + | 'RESUMED' + | 'GUILD_CREATE' + | 'GUILD_DELETE' + | 'GUILD_UPDATE' + | 'INVITE_CREATE' + | 'INVITE_DELETE' + | 'GUILD_MEMBER_ADD' + | 'GUILD_MEMBER_REMOVE' + | 'GUILD_MEMBER_UPDATE' + | 'GUILD_MEMBERS_CHUNK' + | 'GUILD_ROLE_CREATE' + | 'GUILD_ROLE_DELETE' + | 'GUILD_ROLE_UPDATE' + | 'GUILD_BAN_ADD' + | 'GUILD_BAN_REMOVE' + | 'GUILD_EMOJIS_UPDATE' + | 'GUILD_INTEGRATIONS_UPDATE' + | 'CHANNEL_CREATE' + | 'CHANNEL_DELETE' + | 'CHANNEL_UPDATE' + | 'CHANNEL_PINS_UPDATE' + | 'MESSAGE_CREATE' + | 'MESSAGE_DELETE' + | 'MESSAGE_UPDATE' + | 'MESSAGE_DELETE_BULK' + | 'MESSAGE_REACTION_ADD' + | 'MESSAGE_REACTION_REMOVE' + | 'MESSAGE_REACTION_REMOVE_ALL' + | 'MESSAGE_REACTION_REMOVE_EMOJI' + | 'USER_UPDATE' + | 'PRESENCE_UPDATE' + | 'TYPING_START' + | 'VOICE_STATE_UPDATE' + | 'VOICE_SERVER_UPDATE' + | 'WEBHOOKS_UPDATE'; + + //#endregion +} diff --git a/node_modules/discord.js/typings/index.ts b/node_modules/discord.js/typings/index.ts new file mode 100644 index 0000000..db7abe7 --- /dev/null +++ b/node_modules/discord.js/typings/index.ts @@ -0,0 +1,53 @@ +/// + +import { Client, Message, MessageAttachment, MessageEmbed } from 'discord.js'; + +const client: Client = new Client(); + +client.on('ready', () => { + console.log(`Client is logged in as ${client.user!.tag} and ready!`); +}); + +client.on('guildCreate', g => { + const channel = g.channels.cache.random(); + if (!channel) return; + + channel.setName('foo').then(updatedChannel => { + console.log(`New channel name: ${updatedChannel.name}`); + }); +}); + +client.on('messageReactionRemoveAll', async message => { + console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`); + + if (message.partial) message = await message.fetch(); + + console.log(`messageReactionRemoveAll - content: ${message.content}`); +}); + +// These are to check that stuff is the right type +declare const assertIsMessage: (m: Promise) => void; +declare const assertIsMessageArray: (m: Promise) => void; + +client.on('message', ({ channel }) => { + assertIsMessage(channel.send('string')); + assertIsMessage(channel.send({})); + assertIsMessage(channel.send({ embed: {} })); + assertIsMessage(channel.send({ another: 'property' }, {})); + + const attachment = new MessageAttachment('file.png'); + const embed = new MessageEmbed(); + assertIsMessage(channel.send(attachment)); + assertIsMessage(channel.send(embed)); + assertIsMessage(channel.send([attachment, embed])); + + assertIsMessageArray(channel.send(Symbol('another primitive'), { split: true })); + assertIsMessageArray(channel.send({ split: true })); + + // @ts-expect-error + channel.send(); + // @ts-expect-error + channel.send({ another: 'property' }); +}); + +client.login('absolutely-valid-token'); diff --git a/node_modules/discord.js/webpack/discord.min.js b/node_modules/discord.js/webpack/discord.min.js new file mode 100644 index 0000000..96b0f1c --- /dev/null +++ b/node_modules/discord.js/webpack/discord.min.js @@ -0,0 +1,2 @@ +/*! For license information please see discord.min.js.LICENSE.txt */ +!function webpackUniversalModuleDefinition(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Discord=t():e.Discord=t()}(window,(function(){return function(e){var t={};function __webpack_require__(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,__webpack_require__),s.l=!0,s.exports}return __webpack_require__.m=e,__webpack_require__.c=t,__webpack_require__.d=function(e,t,i){__webpack_require__.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},__webpack_require__.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.t=function(e,t){if(1&t&&(e=__webpack_require__(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(__webpack_require__.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)__webpack_require__.d(i,s,function(t){return e[t]}.bind(null,s));return i},__webpack_require__.n=function(e){var t=e&&e.__esModule?function getDefault(){return e.default}:function getModuleExports(){return e};return __webpack_require__.d(t,"a",t),t},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=102)}([function(e,t,i){"use strict";(function(e){const s=t.Package=i(61),{Error:n,RangeError:r}=i(2),o=t.browser="undefined"!=typeof window;t.DefaultOptions={shardCount:1,messageCacheMaxSize:200,messageCacheLifetime:0,messageSweepInterval:0,messageEditHistoryMaxSize:-1,fetchAllMembers:!1,disableMentions:"none",partials:[],restWsBridgeTimeout:5e3,restRequestTimeout:15e3,retryLimit:1,restTimeOffset:500,restSweepInterval:60,presence:{},ws:{large_threshold:50,compress:!1,properties:{$os:o?"browser":e.platform,$browser:"discord.js",$device:"discord.js"},version:6},http:{version:7,api:"https://discord.com/api",cdn:"https://cdn.discordapp.com",invite:"https://discord.gg",template:"https://discord.new"}},t.UserAgent=o?null:`DiscordBot (${s.homepage.split("#")[0]}, ${s.version}) Node.js/${e.version}`,t.WSCodes={1e3:"WS_CLOSE_REQUESTED",4004:"TOKEN_INVALID",4010:"SHARDING_INVALID",4011:"SHARDING_REQUIRED",4013:"INVALID_INTENTS",4014:"DISALLOWED_INTENTS"};const a=["webp","png","jpg","jpeg","gif"],c=Array.from({length:9},((e,t)=>2**(t+4)));function makeImageUrl(e,{format:t="webp",size:i}={}){if(t&&!a.includes(t))throw new n("IMAGE_FORMAT",t);if(i&&!c.includes(i))throw new r("IMAGE_SIZE",i);return`${e}.${t}${i?"?size="+i:""}`}function keyMirror(e){let t=Object.create(null);for(const i of e)t[i]=i;return t}t.Endpoints={CDN:e=>({Emoji:(t,i="png")=>`${e}/emojis/${t}.${i}`,Asset:t=>`${e}/assets/${t}`,DefaultAvatar:t=>`${e}/embed/avatars/${t}.png`,Avatar:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),makeImageUrl(`${e}/avatars/${t}/${i}`,{format:s,size:n})),Banner:(t,i,s="webp",n)=>makeImageUrl(`${e}/banners/${t}/${i}`,{format:s,size:n}),Icon:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),makeImageUrl(`${e}/icons/${t}/${i}`,{format:s,size:n})),AppIcon:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/app-icons/${t}/${i}`,{size:n,format:s}),AppAsset:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/app-assets/${t}/${i}`,{size:n,format:s}),GDMIcon:(t,i,s="webp",n)=>makeImageUrl(`${e}/channel-icons/${t}/${i}`,{size:n,format:s}),Splash:(t,i,s="webp",n)=>makeImageUrl(`${e}/splashes/${t}/${i}`,{size:n,format:s}),DiscoverySplash:(t,i,s="webp",n)=>makeImageUrl(`${e}/discovery-splashes/${t}/${i}`,{size:n,format:s}),TeamIcon:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/team-icons/${t}/${i}`,{size:n,format:s})}),invite:(e,t)=>`${e}/${t}`,botGateway:"/gateway/bot"},t.Status={READY:0,CONNECTING:1,RECONNECTING:2,IDLE:3,NEARLY:4,DISCONNECTED:5,WAITING_FOR_GUILDS:6,IDENTIFYING:7,RESUMING:8},t.VoiceStatus={CONNECTED:0,CONNECTING:1,AUTHENTICATING:2,RECONNECTING:3,DISCONNECTED:4},t.OPCodes={DISPATCH:0,HEARTBEAT:1,IDENTIFY:2,STATUS_UPDATE:3,VOICE_STATE_UPDATE:4,VOICE_GUILD_PING:5,RESUME:6,RECONNECT:7,REQUEST_GUILD_MEMBERS:8,INVALID_SESSION:9,HELLO:10,HEARTBEAT_ACK:11},t.VoiceOPCodes={IDENTIFY:0,SELECT_PROTOCOL:1,READY:2,HEARTBEAT:3,SESSION_DESCRIPTION:4,SPEAKING:5,HELLO:8,CLIENT_CONNECT:12,CLIENT_DISCONNECT:13},t.Events={RATE_LIMIT:"rateLimit",CLIENT_READY:"ready",GUILD_CREATE:"guildCreate",GUILD_DELETE:"guildDelete",GUILD_UPDATE:"guildUpdate",GUILD_UNAVAILABLE:"guildUnavailable",GUILD_AVAILABLE:"guildAvailable",GUILD_MEMBER_ADD:"guildMemberAdd",GUILD_MEMBER_REMOVE:"guildMemberRemove",GUILD_MEMBER_UPDATE:"guildMemberUpdate",GUILD_MEMBER_AVAILABLE:"guildMemberAvailable",GUILD_MEMBER_SPEAKING:"guildMemberSpeaking",GUILD_MEMBERS_CHUNK:"guildMembersChunk",GUILD_INTEGRATIONS_UPDATE:"guildIntegrationsUpdate",GUILD_ROLE_CREATE:"roleCreate",GUILD_ROLE_DELETE:"roleDelete",INVITE_CREATE:"inviteCreate",INVITE_DELETE:"inviteDelete",GUILD_ROLE_UPDATE:"roleUpdate",GUILD_EMOJI_CREATE:"emojiCreate",GUILD_EMOJI_DELETE:"emojiDelete",GUILD_EMOJI_UPDATE:"emojiUpdate",GUILD_BAN_ADD:"guildBanAdd",GUILD_BAN_REMOVE:"guildBanRemove",CHANNEL_CREATE:"channelCreate",CHANNEL_DELETE:"channelDelete",CHANNEL_UPDATE:"channelUpdate",CHANNEL_PINS_UPDATE:"channelPinsUpdate",MESSAGE_CREATE:"message",MESSAGE_DELETE:"messageDelete",MESSAGE_UPDATE:"messageUpdate",MESSAGE_BULK_DELETE:"messageDeleteBulk",MESSAGE_REACTION_ADD:"messageReactionAdd",MESSAGE_REACTION_REMOVE:"messageReactionRemove",MESSAGE_REACTION_REMOVE_ALL:"messageReactionRemoveAll",MESSAGE_REACTION_REMOVE_EMOJI:"messageReactionRemoveEmoji",USER_UPDATE:"userUpdate",PRESENCE_UPDATE:"presenceUpdate",VOICE_SERVER_UPDATE:"voiceServerUpdate",VOICE_STATE_UPDATE:"voiceStateUpdate",VOICE_BROADCAST_SUBSCRIBE:"subscribe",VOICE_BROADCAST_UNSUBSCRIBE:"unsubscribe",TYPING_START:"typingStart",TYPING_STOP:"typingStop",WEBHOOKS_UPDATE:"webhookUpdate",ERROR:"error",WARN:"warn",DEBUG:"debug",SHARD_DISCONNECT:"shardDisconnect",SHARD_ERROR:"shardError",SHARD_RECONNECTING:"shardReconnecting",SHARD_READY:"shardReady",SHARD_RESUME:"shardResume",INVALIDATED:"invalidated",RAW:"raw"},t.ShardEvents={CLOSE:"close",DESTROYED:"destroyed",INVALID_SESSION:"invalidSession",READY:"ready",RESUMED:"resumed",ALL_READY:"allReady"},t.PartialTypes=keyMirror(["USER","CHANNEL","GUILD_MEMBER","MESSAGE","REACTION"]),t.WSEvents=keyMirror(["READY","RESUMED","GUILD_CREATE","GUILD_DELETE","GUILD_UPDATE","INVITE_CREATE","INVITE_DELETE","GUILD_MEMBER_ADD","GUILD_MEMBER_REMOVE","GUILD_MEMBER_UPDATE","GUILD_MEMBERS_CHUNK","GUILD_INTEGRATIONS_UPDATE","GUILD_ROLE_CREATE","GUILD_ROLE_DELETE","GUILD_ROLE_UPDATE","GUILD_BAN_ADD","GUILD_BAN_REMOVE","GUILD_EMOJIS_UPDATE","CHANNEL_CREATE","CHANNEL_DELETE","CHANNEL_UPDATE","CHANNEL_PINS_UPDATE","MESSAGE_CREATE","MESSAGE_DELETE","MESSAGE_UPDATE","MESSAGE_DELETE_BULK","MESSAGE_REACTION_ADD","MESSAGE_REACTION_REMOVE","MESSAGE_REACTION_REMOVE_ALL","MESSAGE_REACTION_REMOVE_EMOJI","USER_UPDATE","PRESENCE_UPDATE","TYPING_START","VOICE_STATE_UPDATE","VOICE_SERVER_UPDATE","WEBHOOKS_UPDATE"]),t.MessageTypes=["DEFAULT","RECIPIENT_ADD","RECIPIENT_REMOVE","CALL","CHANNEL_NAME_CHANGE","CHANNEL_ICON_CHANGE","PINS_ADD","GUILD_MEMBER_JOIN","USER_PREMIUM_GUILD_SUBSCRIPTION","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3","CHANNEL_FOLLOW_ADD",null,"GUILD_DISCOVERY_DISQUALIFIED","GUILD_DISCOVERY_REQUALIFIED"],t.ActivityTypes=["PLAYING","STREAMING","LISTENING","WATCHING","CUSTOM_STATUS","COMPETING"],t.ChannelTypes={TEXT:0,DM:1,VOICE:2,GROUP:3,CATEGORY:4,NEWS:5,STORE:6},t.ClientApplicationAssetTypes={SMALL:1,BIG:2},t.Colors={DEFAULT:0,WHITE:16777215,AQUA:1752220,GREEN:3066993,BLUE:3447003,YELLOW:16776960,PURPLE:10181046,LUMINOUS_VIVID_PINK:15277667,GOLD:15844367,ORANGE:15105570,RED:15158332,GREY:9807270,NAVY:3426654,DARK_AQUA:1146986,DARK_GREEN:2067276,DARK_BLUE:2123412,DARK_PURPLE:7419530,DARK_VIVID_PINK:11342935,DARK_GOLD:12745742,DARK_ORANGE:11027200,DARK_RED:10038562,DARK_GREY:9936031,DARKER_GREY:8359053,LIGHT_GREY:12370112,DARK_NAVY:2899536,BLURPLE:7506394,GREYPLE:10070709,DARK_BUT_NOT_BLACK:2895667,NOT_QUITE_BLACK:2303786},t.ExplicitContentFilterLevels=["DISABLED","MEMBERS_WITHOUT_ROLES","ALL_MEMBERS"],t.VerificationLevels=["NONE","LOW","MEDIUM","HIGH","VERY_HIGH"],t.APIErrors={UNKNOWN_ACCOUNT:10001,UNKNOWN_APPLICATION:10002,UNKNOWN_CHANNEL:10003,UNKNOWN_GUILD:10004,UNKNOWN_INTEGRATION:10005,UNKNOWN_INVITE:10006,UNKNOWN_MEMBER:10007,UNKNOWN_MESSAGE:10008,UNKNOWN_OVERWRITE:10009,UNKNOWN_PROVIDER:10010,UNKNOWN_ROLE:10011,UNKNOWN_TOKEN:10012,UNKNOWN_USER:10013,UNKNOWN_EMOJI:10014,UNKNOWN_WEBHOOK:10015,UNKNOWN_BAN:10026,UNKNOWN_GUILD_TEMPLATE:10057,BOT_PROHIBITED_ENDPOINT:20001,BOT_ONLY_ENDPOINT:20002,CHANNEL_HIT_WRITE_RATELIMIT:20028,MAXIMUM_GUILDS:30001,MAXIMUM_FRIENDS:30002,MAXIMUM_PINS:30003,MAXIMUM_ROLES:30005,MAXIMUM_WEBHOOKS:30007,MAXIMUM_REACTIONS:30010,MAXIMUM_CHANNELS:30013,MAXIMUM_ATTACHMENTS:30015,MAXIMUM_INVITES:30016,GUILD_ALREADY_HAS_TEMPLATE:30031,UNAUTHORIZED:40001,ACCOUNT_VERIFICATION_REQUIRED:40002,REQUEST_ENTITY_TOO_LARGE:40005,FEATURE_TEMPORARILY_DISABLED:40006,USER_BANNED:40007,ALREADY_CROSSPOSTED:40033,MISSING_ACCESS:50001,INVALID_ACCOUNT_TYPE:50002,CANNOT_EXECUTE_ON_DM:50003,EMBED_DISABLED:50004,CANNOT_EDIT_MESSAGE_BY_OTHER:50005,CANNOT_SEND_EMPTY_MESSAGE:50006,CANNOT_MESSAGE_USER:50007,CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL:50008,CHANNEL_VERIFICATION_LEVEL_TOO_HIGH:50009,OAUTH2_APPLICATION_BOT_ABSENT:50010,MAXIMUM_OAUTH2_APPLICATIONS:50011,INVALID_OAUTH_STATE:50012,MISSING_PERMISSIONS:50013,INVALID_AUTHENTICATION_TOKEN:50014,NOTE_TOO_LONG:50015,INVALID_BULK_DELETE_QUANTITY:50016,CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL:50019,INVALID_OR_TAKEN_INVITE_CODE:50020,CANNOT_EXECUTE_ON_SYSTEM_MESSAGE:50021,INVALID_OAUTH_TOKEN:50025,BULK_DELETE_MESSAGE_TOO_OLD:50034,INVALID_FORM_BODY:50035,INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT:50036,INVALID_API_VERSION:50041,CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL:50074,REACTION_BLOCKED:90001,RESOURCE_OVERLOADED:13e4},t.DefaultMessageNotifications=["ALL","MENTIONS"],t.MembershipStates=[null,"INVITED","ACCEPTED"],t.WebhookTypes=[null,"Incoming","Channel Follower"]}).call(this,i(15))},function(e,t,i){"use strict";const{PartialTypes:s}=i(0);e.exports=class GenericAction{constructor(e){this.client=e}handle(e){return e}getPayload(e,t,i,s,n){const r=t.cache.get(i);return!r&&this.client.options.partials.includes(s)?t.add(e,n):r}getChannel(e){const t=e.channel_id||e.id;return e.channel||this.getPayload({id:t,guild_id:e.guild_id,recipients:[e.author||{id:e.user_id}]},this.client.channels,t,s.CHANNEL)}getMessage(e,t,i){const n=e.message_id||e.id;return e.message||this.getPayload({id:n,channel_id:t.id,guild_id:e.guild_id||(t.guild?t.guild.id:null)},t.messages,n,s.MESSAGE,i)}getReaction(e,t,i){const n=e.emoji.id||decodeURIComponent(e.emoji.name);return this.getPayload({emoji:e.emoji,count:t.partial?null:0,me:!!i&&i.id===this.client.user.id},t.reactions,n,s.REACTION)}getMember(e,t){return this.getPayload(e,t.members,e.user.id,s.GUILD_MEMBER)}getUser(e){const t=e.user_id;return e.user||this.getPayload({id:t},this.client.users,t,s.USER)}getUserFromMember(e){if(e.guild_id&&e.member&&e.member.user){const t=this.client.guilds.cache.get(e.guild_id);return t?t.members.add(e.member).user:this.client.users.add(e.member.user)}return this.getUser(e)}}},function(e,t,i){"use strict";e.exports=i(62),e.exports.Messages=i(105)},function(e,t,i){"use strict";const s=i(106),n=i(4);e.exports=class Collection extends s{toJSON(){return this.map((e=>"function"==typeof e.toJSON?e.toJSON():n.flatten(e)))}}},function(e,t,i){"use strict";(function(t){const{parse:s}=i(35),n=i(36),{Colors:r,DefaultOptions:o,Endpoints:a}=i(0),{Error:c,RangeError:l,TypeError:h}=i(2),isObject=e=>"object"==typeof e&&null!==e;class Util{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static flatten(e,...t){if(!isObject(e))return e;const s=Object.keys(e).filter((e=>!e.startsWith("_"))).map((e=>({[e]:!0})));t=s.length?Object.assign(...s,...t):Object.assign({},...t);const n={};for(let[s,r]of Object.entries(t)){if(!r)continue;r=!0===r?s:r;const t=e[s],o=isObject(t),a=o&&"function"==typeof t.valueOf?t.valueOf():null;t instanceof i(3)?n[r]=Array.from(t.keys()):a instanceof i(3)?n[r]=Array.from(a.keys()):Array.isArray(t)?n[r]=t.map((e=>Util.flatten(e))):"object"!=typeof a?n[r]=a:o||(n[r]=t)}return n}static splitMessage(e,{maxLength:t=2e3,char:i="\n",prepend:s="",append:n=""}={}){if((e=Util.resolveString(e)).length<=t)return[e];const r=e.split(i);if(r.some((e=>e.length>t)))throw new l("SPLIT_MAX_LEN");const o=[];let a="";for(const e of r)a&&(a+i+e+n).length>t&&(o.push(a+n),a=s),a+=(a&&a!==s?i:"")+e;return o.concat(a).filter((e=>e))}static escapeMarkdown(e,{codeBlock:t=!0,inlineCode:i=!0,bold:s=!0,italic:n=!0,underline:r=!0,strikethrough:o=!0,spoiler:a=!0,codeBlockContent:c=!0,inlineCodeContent:l=!0}={}){return c?l?(i&&(e=Util.escapeInlineCode(e)),t&&(e=Util.escapeCodeBlock(e)),n&&(e=Util.escapeItalic(e)),s&&(e=Util.escapeBold(e)),r&&(e=Util.escapeUnderline(e)),o&&(e=Util.escapeStrikethrough(e)),a&&(e=Util.escapeSpoiler(e)),e):e.split(/(?<=^|[^`])`(?=[^`]|$)/g).map(((e,i,c)=>i%2&&i!==c.length-1?e:Util.escapeMarkdown(e,{codeBlock:t,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a}))).join(i?"\\`":"`"):e.split("```").map(((e,t,c)=>t%2&&t!==c.length-1?e:Util.escapeMarkdown(e,{inlineCode:i,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a,inlineCodeContent:l}))).join(t?"\\`\\`\\`":"```")}static escapeCodeBlock(e){return e.replace(/```/g,"\\`\\`\\`")}static escapeInlineCode(e){return e.replace(/(?<=^|[^`])`(?=[^`]|$)/g,"\\`")}static escapeItalic(e){let t=0;return e=e.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g,((e,i)=>"**"===i?++t%2?"\\*"+i:i+"\\*":"\\*"+i)),t=0,e.replace(/(?<=^|[^_])_([^_]|__|$)/g,((e,i)=>"__"===i?++t%2?"\\_"+i:i+"\\_":"\\_"+i))}static escapeBold(e){let t=0;return e.replace(/\*\*(\*)?/g,((e,i)=>i?++t%2?i+"\\*\\*":"\\*\\*"+i:"\\*\\*"))}static escapeUnderline(e){let t=0;return e.replace(/__(_)?/g,((e,i)=>i?++t%2?i+"\\_\\_":"\\_\\_"+i:"\\_\\_"))}static escapeStrikethrough(e){return e.replace(/~~/g,"\\~\\~")}static escapeSpoiler(e){return e.replace(/\|\|/g,"\\|\\|")}static fetchRecommendedShards(e,t=1e3){if(!e)throw new c("TOKEN_MISSING");return n(`${o.http.api}/v${o.http.version}${a.botGateway}`,{method:"GET",headers:{Authorization:"Bot "+e.replace(/^Bot\s*/i,"")}}).then((e=>{if(e.ok)return e.json();if(401===e.status)throw new c("TOKEN_INVALID");throw e})).then((e=>e.shards*(1e3/t)))}static parseEmoji(e){if(e.includes("%")&&(e=decodeURIComponent(e)),!e.includes(":"))return{animated:!1,name:e,id:null};const t=e.match(/?/);return t?{animated:Boolean(t[1]),name:t[2],id:t[3]||null}:null}static cloneObject(e){return Object.assign(Object.create(e),e)}static mergeDefault(e,t){if(!t)return e;for(const n in e)i=t,s=n,Object.prototype.hasOwnProperty.call(i,s)&&void 0!==t[n]?t[n]===Object(t[n])&&(t[n]=Util.mergeDefault(e[n],t[n])):t[n]=e[n];var i,s;return t}static convertToBuffer(e){return"string"==typeof e&&(e=Util.str2ab(e)),t.from(e)}static str2ab(e){const t=new ArrayBuffer(2*e.length),i=new Uint16Array(t);for(var s=0,n=e.length;s-1&&i16777215)throw new l("COLOR_RANGE");if(e&&isNaN(e))throw new h("COLOR_CONVERT");return e}static discordSort(e){return e.sorted(((e,t)=>e.rawPosition-t.rawPosition||parseInt(t.id.slice(0,-10))-parseInt(e.id.slice(0,-10))||parseInt(t.id.slice(10))-parseInt(e.id.slice(10))))}static setPosition(e,t,i,s,n,r){let o=s.array();return Util.moveElementInArray(o,e,t,i),o=o.map(((e,t)=>({id:e.id,position:t}))),n.patch({data:o,reason:r}).then((()=>o))}static basename(e,t){let i=s(e);return t&&i.ext.startsWith(t)?i.name:i.base.split("?")[0]}static idToBinary(e){let t="",i=parseInt(e.slice(0,-10))||0,s=parseInt(e.slice(-10));for(;s>0||i>0;)t=String(1&s)+t,s=Math.floor(s/2),i>0&&(s+=i%2*5e9,i=Math.floor(i/2));return t}static binaryToID(e){let t="";for(;e.length>50;){const i=parseInt(e.slice(0,-32),2),s=parseInt((i%10).toString(2)+e.slice(-32),2);t=(s%10).toString()+t,e=Math.floor(i/10).toString(2)+Math.floor(s/10).toString(2).padStart(32,"0")}for(e=parseInt(e,2);e>0;)t=(e%10).toString()+t,e=Math.floor(e/10);return t}static removeMentions(e){return e.replace(/@/g,"@​")}static cleanContent(e,t){return e=e.replace(/<@!?[0-9]+>/g,(e=>{const i=e.replace(/<|!|>|@/g,"");if("dm"===t.channel.type){const s=t.client.users.cache.get(i);return s?Util.removeMentions("@"+s.username):e}const s=t.channel.guild.members.cache.get(i);if(s)return Util.removeMentions("@"+s.displayName);{const s=t.client.users.cache.get(i);return s?Util.removeMentions("@"+s.username):e}})).replace(/<#[0-9]+>/g,(e=>{const i=t.client.channels.cache.get(e.replace(/<|#|>/g,""));return i?"#"+i.name:e})).replace(/<@&[0-9]+>/g,(e=>{if("dm"===t.channel.type)return e;const i=t.guild.roles.cache.get(e.replace(/<|@|>|&/g,""));return i?"@"+i.name:e})),"everyone"===t.client.options.disableMentions&&(e=e.replace(/@([^<>@ ]*)/gmus,((e,t)=>t.match(/^[&!]?\d+$/)?"@"+t:"@​"+t))),"all"===t.client.options.disableMentions?Util.removeMentions(e):e}static cleanCodeBlockContent(e){return e.replace(/```/g,"`​``")}static delayFor(e){return new Promise((t=>{setTimeout(t,e)}))}}e.exports=Util}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(4);e.exports=class Base{constructor(e){Object.defineProperty(this,"client",{value:e})}_clone(){return Object.assign(Object.create(this),this)}_patch(e){return e}_update(e){const t=this._clone();return this._patch(e),t}toJSON(...e){return s.flatten(this,...e)}valueOf(){return this.id}}},function(e,t,i){"use strict";const s=i(4),n=14200704e5;let r=0;e.exports=class SnowflakeUtil{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static generate(e=Date.now()){if(e instanceof Date&&(e=e.getTime()),"number"!=typeof e||isNaN(e))throw new TypeError(`"timestamp" argument must be a number (received ${isNaN(e)?"NaN":typeof e})`);r>=4095&&(r=0);const t=`${(e-n).toString(2).padStart(42,"0")}0000100000${(r++).toString(2).padStart(12,"0")}`;return s.binaryToID(t)}static deconstruct(e){const t=s.idToBinary(e).toString(2).padStart(64,"0"),i={timestamp:parseInt(t.substring(0,42),2)+n,workerID:parseInt(t.substring(42,47),2),processID:parseInt(t.substring(47,52),2),increment:parseInt(t.substring(52,64),2),binary:t};return Object.defineProperty(i,"date",{get:function get(){return new Date(this.timestamp)},enumerable:!0}),i}static get EPOCH(){return n}}},function(e,t,i){"use strict";const s=i(3);let n;e.exports=class BaseManager{constructor(e,t,r,o=s,...a){if(n||(n=i(10)),Object.defineProperty(this,"holds",{value:n.get(r.name)||r}),Object.defineProperty(this,"client",{value:e}),this.cacheType=o,this.cache=new o(...a),t)for(const e of t)this.add(e)}add(e,t=!0,{id:i,extras:s=[]}={}){const n=this.cache.get(i||e.id);if(n&&n._patch&&t&&n._patch(e),n)return n;const r=this.holds?new this.holds(this.client,e,...s):e;return t&&this.cache.set(i||r.id,r),r}resolve(e){return e instanceof this.holds?e:"string"==typeof e&&this.cache.get(e)||null}resolveID(e){return e instanceof this.holds?e.id:"string"==typeof e?e:null}valueOf(){return this.cache}}},function(e,t,i){"use strict";const s=i(12);class Permissions extends s{any(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.any(e)}has(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.has(e)}}Permissions.FLAGS={CREATE_INSTANT_INVITE:1,KICK_MEMBERS:2,BAN_MEMBERS:4,ADMINISTRATOR:8,MANAGE_CHANNELS:16,MANAGE_GUILD:32,ADD_REACTIONS:64,VIEW_AUDIT_LOG:128,PRIORITY_SPEAKER:256,STREAM:512,VIEW_CHANNEL:1024,SEND_MESSAGES:2048,SEND_TTS_MESSAGES:4096,MANAGE_MESSAGES:8192,EMBED_LINKS:16384,ATTACH_FILES:32768,READ_MESSAGE_HISTORY:65536,MENTION_EVERYONE:1<<17,USE_EXTERNAL_EMOJIS:1<<18,VIEW_GUILD_INSIGHTS:1<<19,CONNECT:1<<20,SPEAK:1<<21,MUTE_MEMBERS:1<<22,DEAFEN_MEMBERS:1<<23,MOVE_MEMBERS:1<<24,USE_VAD:1<<25,CHANGE_NICKNAME:1<<26,MANAGE_NICKNAMES:1<<27,MANAGE_ROLES:1<<28,MANAGE_WEBHOOKS:1<<29,MANAGE_EMOJIS:1<<30},Permissions.ALL=Object.values(Permissions.FLAGS).reduce(((e,t)=>e|t),0),Permissions.DEFAULT=104324673,e.exports=Permissions},function(e,t,i){"use strict";(function(t){const s=i(35),n=i(35),r=i(127),o=i(36),{Error:a,TypeError:c}=i(2),{browser:l}=i(0),h=i(4);class DataResolver{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static resolveCode(e,t){const i=t.exec(e);return i&&i[1]||e}static resolveInviteCode(e){return this.resolveCode(e,/discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i)}static resolveGuildTemplateCode(e){return this.resolveCode(e,/discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/i)}static async resolveImage(e){if(!e)return null;if("string"==typeof e&&e.startsWith("data:"))return e;const t=await this.resolveFileAsBuffer(e);return DataResolver.resolveBase64(t)}static resolveBase64(e){return t.isBuffer(e)?"data:image/jpg;base64,"+e.toString("base64"):e}static async resolveFile(e){if(!l&&t.isBuffer(e))return e;if(l&&e instanceof ArrayBuffer)return h.convertToBuffer(e);if(l&&e instanceof Blob)return e;if(e instanceof r.Readable)return e;if("string"==typeof e){if(/^https?:\/\//.test(e)){const t=await o(e);return l?t.blob():t.body}if(!l)return new Promise(((t,i)=>{const r=n.resolve(e);s.stat(r,((e,n)=>e?i(e):n.isFile()?t(s.createReadStream(r)):i(new a("FILE_NOT_FOUND",r))))}))}throw new c("REQ_RESOURCE_TYPE")}static async resolveFileAsBuffer(e){const i=await this.resolveFile(e);if(t.isBuffer(i))return i;const s=[];for await(const e of i)s.push(e);return t.concat(s)}}e.exports=DataResolver}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s={GuildEmoji:i(25),DMChannel:i(39),TextChannel:i(41),VoiceChannel:i(81),CategoryChannel:i(82),NewsChannel:i(83),StoreChannel:i(84),GuildMember:i(11),Guild:i(54),Message:i(28),MessageReaction:i(52),Presence:i(24).Presence,ClientPresence:i(93),VoiceState:i(94),Role:i(20),User:i(27)};e.exports=class Structures{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static get(e){if("string"==typeof e)return s[e];throw new TypeError(`"structure" argument must be a string (received ${typeof e})`)}static extend(e,t){if(!s[e])throw new RangeError(`"${e}" is not a valid extensible structure.`);if("function"!=typeof t){throw new TypeError(`"extender" argument must be a function that returns the extended structure class/prototype ${`(received ${typeof t})`}.`)}const i=t(s[e]);if("function"!=typeof i){throw new TypeError(`The extender function must return the extended structure class/prototype ${`(received ${typeof i})`}.`)}if(!(i.prototype instanceof s[e])){const t=Object.getPrototypeOf(i),n=`${i.name||"unnamed"}${t.name?" extends "+t.name:""}`;throw new Error(`The class/prototype returned from the extender function must extend the existing structure class/prototype (received function ${n}; expected extension of ${s[e].name}).`)}return s[e]=i,i}}},function(e,t,i){"use strict";const s=i(5),n=i(20),r=i(33),{Error:o}=i(2),a=i(73),c=i(8);let l;class GuildMember extends s{constructor(e,t,i){super(e),this.guild=i,this.joinedTimestamp=null,this.lastMessageID=null,this.lastMessageChannelID=null,this.premiumSinceTimestamp=null,this.deleted=!1,this.nickname=null,this._roles=[],t&&this._patch(t)}_patch(e){"user"in e&&(this.user=this.client.users.add(e.user,!0)),"nick"in e&&(this.nickname=e.nick),"joined_at"in e&&(this.joinedTimestamp=new Date(e.joined_at).getTime()),"premium_since"in e&&(this.premiumSinceTimestamp=new Date(e.premium_since).getTime()),"roles"in e&&(this._roles=e.roles)}_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}get partial(){return!this.joinedTimestamp}get roles(){return new a(this)}get lastMessage(){const e=this.guild.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get voice(){l||(l=i(10));const e=l.get("VoiceState");return this.guild.voiceStates.cache.get(this.id)||new e(this.guild,{user_id:this.id})}get joinedAt(){return this.joinedTimestamp?new Date(this.joinedTimestamp):null}get premiumSince(){return this.premiumSinceTimestamp?new Date(this.premiumSinceTimestamp):null}get presence(){l||(l=i(10));const e=l.get("Presence");return this.guild.presences.cache.get(this.id)||new e(this.client,{user:{id:this.id},guild:this.guild})}get displayColor(){const e=this.roles.color;return e&&e.color||0}get displayHexColor(){const e=this.roles.color;return e&&e.hexColor||"#000000"}get id(){return this.user.id}get displayName(){return this.nickname||this.user.username}get permissions(){return this.user.id===this.guild.ownerID?new c(c.ALL).freeze():new c(this.roles.cache.map((e=>e.permissions))).freeze()}get manageable(){if(this.user.id===this.guild.ownerID)return!1;if(this.user.id===this.client.user.id)return!1;if(this.client.user.id===this.guild.ownerID)return!0;if(!this.guild.me)throw new o("GUILD_UNCACHED_ME");return this.guild.me.roles.highest.comparePositionTo(this.roles.highest)>0}get kickable(){return this.manageable&&this.guild.me.permissions.has(c.FLAGS.KICK_MEMBERS)}get bannable(){return this.manageable&&this.guild.me.permissions.has(c.FLAGS.BAN_MEMBERS)}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new o("GUILD_CHANNEL_RESOLVE");return e.memberPermissions(this)}hasPermission(e,{checkAdmin:t=!0,checkOwner:i=!0}={}){if(i&&this.user.id===this.guild.ownerID)return!0;return new c(this.roles.cache.map((e=>e.permissions))).has(e,t)}async edit(e,t){if(e.channel){if(e.channel=this.guild.channels.resolve(e.channel),!e.channel||"voice"!==e.channel.type)throw new o("GUILD_VOICE_CHANNEL_RESOLVE");e.channel_id=e.channel.id,e.channel=void 0}else null===e.channel&&(e.channel_id=null,e.channel=void 0);e.roles&&(e.roles=e.roles.map((e=>e instanceof n?e.id:e)));let i=this.client.api.guilds(this.guild.id);if(this.user.id===this.client.user.id){const t=Object.keys(e);i=1===t.length&&"nick"===t[0]?i.members("@me").nick:i.members(this.id)}else i=i.members(this.id);await i.patch({data:e,reason:t});const s=this._clone();return e.user=this.user,s._patch(e),s}setNickname(e,t){return this.edit({nick:e},t)}createDM(){return this.user.createDM()}deleteDM(){return this.user.deleteDM()}kick(e){return this.client.api.guilds(this.guild.id).members(this.user.id).delete({reason:e}).then((()=>this))}ban(e){return this.guild.members.ban(this,e)}fetch(e=!1){return this.guild.members.fetch({user:this.id,cache:!0,force:e})}toString(){return`<@${this.nickname?"!":""}${this.user.id}>`}toJSON(){return super.toJSON({guild:"guildID",user:"userID",displayName:!0,speaking:!1,lastMessage:!1,lastMessageID:!1,roles:!0})}send(){}}r.applyToClass(GuildMember),e.exports=GuildMember},function(e,t,i){"use strict";const{RangeError:s}=i(2);class BitField{constructor(e){this.bitfield=this.constructor.resolve(e)}any(e){return 0!=(this.bitfield&this.constructor.resolve(e))}equals(e){return this.bitfield===this.constructor.resolve(e)}has(e){return Array.isArray(e)?e.every((e=>this.has(e))):(e=this.constructor.resolve(e),(this.bitfield&e)===e)}missing(e,...t){return Array.isArray(e)||(e=new this.constructor(e).toArray(!1)),e.filter((e=>!this.has(e,...t)))}freeze(){return Object.freeze(this)}add(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield|t):(this.bitfield|=t,this)}remove(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield&~t):(this.bitfield&=~t,this)}serialize(...e){const t={};for(const[i,s]of Object.entries(this.constructor.FLAGS))t[i]=this.has(s,...e);return t}toArray(...e){return Object.keys(this.constructor.FLAGS).filter((t=>this.has(t,...e)))}toJSON(){return this.bitfield}valueOf(){return this.bitfield}*[Symbol.iterator](){yield*this.toArray()}static resolve(e=0){if("number"==typeof e&&e>=0)return e;if(e instanceof BitField)return e.bitfield;if(Array.isArray(e))return e.map((e=>this.resolve(e))).reduce(((e,t)=>e|t),0);if("string"==typeof e&&void 0!==this.FLAGS[e])return this.FLAGS[e];const t=new s("BITFIELD_INVALID");throw t.bit=e,t}}BitField.FLAGS={},e.exports=BitField},function(e,t,i){"use strict";const s=i(30),n=i(17),{WebhookTypes:r}=i(0),o=i(9),a=i(6);class Webhook{constructor(e,t){Object.defineProperty(this,"client",{value:e}),t&&this._patch(t)}_patch(e){this.name=e.name,Object.defineProperty(this,"token",{value:e.token||null,writable:!0,configurable:!0}),this.avatar=e.avatar,this.id=e.id,this.type=r[e.type],this.guildID=e.guild_id,this.channelID=e.channel_id,e.user?this.owner=this.client.users?this.client.users.cache.get(e.user.id):e.user:this.owner=null}async send(e,t){let i;if(e instanceof s)i=e.resolveData();else if(i=s.create(this,e,t).resolveData(),Array.isArray(i.data.content))return Promise.all(i.split().map(this.send.bind(this)));const{data:n,files:r}=await i.resolveFiles();return this.client.api.webhooks(this.id,this.token).post({data:n,files:r,query:{wait:!0},auth:!1}).then((e=>{const t=this.client.channels?this.client.channels.cache.get(e.channel_id):void 0;return t?t.messages.add(e,!1):e}))}sendSlackMessage(e){return this.client.api.webhooks(this.id,this.token).slack.post({query:{wait:!0},auth:!1,data:e}).then((e=>"ok"===e.toString()))}async edit({name:e=this.name,avatar:t,channel:i},s){t&&"string"==typeof t&&!t.startsWith("data:")&&(t=await o.resolveImage(t)),i&&(i=i instanceof n?i.id:i);const r=await this.client.api.webhooks(this.id,i?void 0:this.token).patch({data:{name:e,avatar:t,channel_id:i},reason:s});return this.name=r.name,this.avatar=r.avatar,this.channelID=r.channel_id,this}delete(e){return this.client.api.webhooks(this.id,this.token).delete({reason:e})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get url(){return this.client.options.http.api+this.client.api.webhooks(this.id,this.token)}avatarURL({format:e,size:t}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t):null}static applyToClass(e){for(const t of["send","sendSlackMessage","edit","delete","createdTimestamp","createdAt","url"])Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(Webhook.prototype,t))}}e.exports=Webhook},function(e,t,i){"use strict";(function(e){var s=i(103),n=i(104),r=i(60);function kMaxLength(){return Buffer.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function createBuffer(e,t){if(kMaxLength()=kMaxLength())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+kMaxLength().toString(16)+" bytes");return 0|e}function byteLength(e,t){if(Buffer.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var i=e.length;if(0===i)return 0;for(var s=!1;;)switch(t){case"ascii":case"latin1":case"binary":return i;case"utf8":case"utf-8":case void 0:return utf8ToBytes(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*i;case"hex":return i>>>1;case"base64":return base64ToBytes(e).length;default:if(s)return utf8ToBytes(e).length;t=(""+t).toLowerCase(),s=!0}}function slowToString(e,t,i){var s=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===i||i>this.length)&&(i=this.length),i<=0)return"";if((i>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return hexSlice(this,t,i);case"utf8":case"utf-8":return utf8Slice(this,t,i);case"ascii":return asciiSlice(this,t,i);case"latin1":case"binary":return latin1Slice(this,t,i);case"base64":return base64Slice(this,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,t,i);default:if(s)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),s=!0}}function swap(e,t,i){var s=e[t];e[t]=e[i],e[i]=s}function bidirectionalIndexOf(e,t,i,s,n){if(0===e.length)return-1;if("string"==typeof i?(s=i,i=0):i>2147483647?i=2147483647:i<-2147483648&&(i=-2147483648),i=+i,isNaN(i)&&(i=n?0:e.length-1),i<0&&(i=e.length+i),i>=e.length){if(n)return-1;i=e.length-1}else if(i<0){if(!n)return-1;i=0}if("string"==typeof t&&(t=Buffer.from(t,s)),Buffer.isBuffer(t))return 0===t.length?-1:arrayIndexOf(e,t,i,s,n);if("number"==typeof t)return t&=255,Buffer.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?n?Uint8Array.prototype.indexOf.call(e,t,i):Uint8Array.prototype.lastIndexOf.call(e,t,i):arrayIndexOf(e,[t],i,s,n);throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(e,t,i,s,n){var r,o=1,a=e.length,c=t.length;if(void 0!==s&&("ucs2"===(s=String(s).toLowerCase())||"ucs-2"===s||"utf16le"===s||"utf-16le"===s)){if(e.length<2||t.length<2)return-1;o=2,a/=2,c/=2,i/=2}function read(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(n){var l=-1;for(r=i;ra&&(i=a-c),r=i;r>=0;r--){for(var h=!0,u=0;un&&(s=n):s=n;var r=t.length;if(r%2!=0)throw new TypeError("Invalid hex string");s>r/2&&(s=r/2);for(var o=0;o>8,n=i%256,r.push(n),r.push(s);return r}(t,e.length-i),e,i,s)}function base64Slice(e,t,i){return 0===t&&i===e.length?s.fromByteArray(e):s.fromByteArray(e.slice(t,i))}function utf8Slice(e,t,i){i=Math.min(e.length,i);for(var s=[],n=t;n239?4:h>223?3:h>191?2:1;if(n+d<=i)switch(d){case 1:h<128&&(u=h);break;case 2:128==(192&(r=e[n+1]))&&(l=(31&h)<<6|63&r)>127&&(u=l);break;case 3:r=e[n+1],a=e[n+2],128==(192&r)&&128==(192&a)&&(l=(15&h)<<12|(63&r)<<6|63&a)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:r=e[n+1],a=e[n+2],c=e[n+3],128==(192&r)&&128==(192&a)&&128==(192&c)&&(l=(15&h)<<18|(63&r)<<12|(63&a)<<6|63&c)>65535&&l<1114112&&(u=l)}null===u?(u=65533,d=1):u>65535&&(u-=65536,s.push(u>>>10&1023|55296),u=56320|1023&u),s.push(u),n+=d}return function decodeCodePointsArray(e){var t=e.length;if(t<=o)return String.fromCharCode.apply(String,e);var i="",s=0;for(;s0&&(e=this.toString("hex",0,i).match(/.{2}/g).join(" "),this.length>i&&(e+=" ... ")),""},Buffer.prototype.compare=function compare(e,t,i,s,n){if(!Buffer.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===i&&(i=e?e.length:0),void 0===s&&(s=0),void 0===n&&(n=this.length),t<0||i>e.length||s<0||n>this.length)throw new RangeError("out of range index");if(s>=n&&t>=i)return 0;if(s>=n)return-1;if(t>=i)return 1;if(this===e)return 0;for(var r=(n>>>=0)-(s>>>=0),o=(i>>>=0)-(t>>>=0),a=Math.min(r,o),c=this.slice(s,n),l=e.slice(t,i),h=0;hn)&&(i=n),e.length>0&&(i<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");s||(s="utf8");for(var r=!1;;)switch(s){case"hex":return hexWrite(this,e,t,i);case"utf8":case"utf-8":return utf8Write(this,e,t,i);case"ascii":return asciiWrite(this,e,t,i);case"latin1":case"binary":return latin1Write(this,e,t,i);case"base64":return base64Write(this,e,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,e,t,i);default:if(r)throw new TypeError("Unknown encoding: "+s);s=(""+s).toLowerCase(),r=!0}},Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var o=4096;function asciiSlice(e,t,i){var s="";i=Math.min(e.length,i);for(var n=t;ns)&&(i=s);for(var n="",r=t;ri)throw new RangeError("Trying to access beyond buffer length")}function checkInt(e,t,i,s,n,r){if(!Buffer.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>n||te.length)throw new RangeError("Index out of range")}function objectWriteUInt16(e,t,i,s){t<0&&(t=65535+t+1);for(var n=0,r=Math.min(e.length-i,2);n>>8*(s?n:1-n)}function objectWriteUInt32(e,t,i,s){t<0&&(t=4294967295+t+1);for(var n=0,r=Math.min(e.length-i,4);n>>8*(s?n:3-n)&255}function checkIEEE754(e,t,i,s,n,r){if(i+s>e.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("Index out of range")}function writeFloat(e,t,i,s,r){return r||checkIEEE754(e,0,i,4),n.write(e,t,i,s,23,4),i+4}function writeDouble(e,t,i,s,r){return r||checkIEEE754(e,0,i,8),n.write(e,t,i,s,52,8),i+8}Buffer.prototype.slice=function slice(e,t){var i,s=this.length;if((e=~~e)<0?(e+=s)<0&&(e=0):e>s&&(e=s),(t=void 0===t?s:~~t)<0?(t+=s)<0&&(t=0):t>s&&(t=s),t0&&(n*=256);)s+=this[e+--t]*n;return s},Buffer.prototype.readUInt8=function readUInt8(e,t){return t||checkOffset(e,1,this.length),this[e]},Buffer.prototype.readUInt16LE=function readUInt16LE(e,t){return t||checkOffset(e,2,this.length),this[e]|this[e+1]<<8},Buffer.prototype.readUInt16BE=function readUInt16BE(e,t){return t||checkOffset(e,2,this.length),this[e]<<8|this[e+1]},Buffer.prototype.readUInt32LE=function readUInt32LE(e,t){return t||checkOffset(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},Buffer.prototype.readUInt32BE=function readUInt32BE(e,t){return t||checkOffset(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},Buffer.prototype.readIntLE=function readIntLE(e,t,i){e|=0,t|=0,i||checkOffset(e,t,this.length);for(var s=this[e],n=1,r=0;++r=(n*=128)&&(s-=Math.pow(2,8*t)),s},Buffer.prototype.readIntBE=function readIntBE(e,t,i){e|=0,t|=0,i||checkOffset(e,t,this.length);for(var s=t,n=1,r=this[e+--s];s>0&&(n*=256);)r+=this[e+--s]*n;return r>=(n*=128)&&(r-=Math.pow(2,8*t)),r},Buffer.prototype.readInt8=function readInt8(e,t){return t||checkOffset(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},Buffer.prototype.readInt16LE=function readInt16LE(e,t){t||checkOffset(e,2,this.length);var i=this[e]|this[e+1]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt16BE=function readInt16BE(e,t){t||checkOffset(e,2,this.length);var i=this[e+1]|this[e]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt32LE=function readInt32LE(e,t){return t||checkOffset(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},Buffer.prototype.readInt32BE=function readInt32BE(e,t){return t||checkOffset(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},Buffer.prototype.readFloatLE=function readFloatLE(e,t){return t||checkOffset(e,4,this.length),n.read(this,e,!0,23,4)},Buffer.prototype.readFloatBE=function readFloatBE(e,t){return t||checkOffset(e,4,this.length),n.read(this,e,!1,23,4)},Buffer.prototype.readDoubleLE=function readDoubleLE(e,t){return t||checkOffset(e,8,this.length),n.read(this,e,!0,52,8)},Buffer.prototype.readDoubleBE=function readDoubleBE(e,t){return t||checkOffset(e,8,this.length),n.read(this,e,!1,52,8)},Buffer.prototype.writeUIntLE=function writeUIntLE(e,t,i,s){(e=+e,t|=0,i|=0,s)||checkInt(this,e,t,i,Math.pow(2,8*i)-1,0);var n=1,r=0;for(this[t]=255&e;++r=0&&(r*=256);)this[t+n]=e/r&255;return t+i},Buffer.prototype.writeUInt8=function writeUInt8(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,1,255,0),Buffer.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},Buffer.prototype.writeUInt16LE=function writeUInt16LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):objectWriteUInt16(this,e,t,!0),t+2},Buffer.prototype.writeUInt16BE=function writeUInt16BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):objectWriteUInt16(this,e,t,!1),t+2},Buffer.prototype.writeUInt32LE=function writeUInt32LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):objectWriteUInt32(this,e,t,!0),t+4},Buffer.prototype.writeUInt32BE=function writeUInt32BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):objectWriteUInt32(this,e,t,!1),t+4},Buffer.prototype.writeIntLE=function writeIntLE(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);checkInt(this,e,t,i,n-1,-n)}var r=0,o=1,a=0;for(this[t]=255&e;++r>0)-a&255;return t+i},Buffer.prototype.writeIntBE=function writeIntBE(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);checkInt(this,e,t,i,n-1,-n)}var r=i-1,o=1,a=0;for(this[t+r]=255&e;--r>=0&&(o*=256);)e<0&&0===a&&0!==this[t+r+1]&&(a=1),this[t+r]=(e/o>>0)-a&255;return t+i},Buffer.prototype.writeInt8=function writeInt8(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,1,127,-128),Buffer.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},Buffer.prototype.writeInt16LE=function writeInt16LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):objectWriteUInt16(this,e,t,!0),t+2},Buffer.prototype.writeInt16BE=function writeInt16BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):objectWriteUInt16(this,e,t,!1),t+2},Buffer.prototype.writeInt32LE=function writeInt32LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,2147483647,-2147483648),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):objectWriteUInt32(this,e,t,!0),t+4},Buffer.prototype.writeInt32BE=function writeInt32BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):objectWriteUInt32(this,e,t,!1),t+4},Buffer.prototype.writeFloatLE=function writeFloatLE(e,t,i){return writeFloat(this,e,t,!0,i)},Buffer.prototype.writeFloatBE=function writeFloatBE(e,t,i){return writeFloat(this,e,t,!1,i)},Buffer.prototype.writeDoubleLE=function writeDoubleLE(e,t,i){return writeDouble(this,e,t,!0,i)},Buffer.prototype.writeDoubleBE=function writeDoubleBE(e,t,i){return writeDouble(this,e,t,!1,i)},Buffer.prototype.copy=function copy(e,t,i,s){if(i||(i=0),s||0===s||(s=this.length),t>=e.length&&(t=e.length),t||(t=0),s>0&&s=this.length)throw new RangeError("sourceStart out of bounds");if(s<0)throw new RangeError("sourceEnd out of bounds");s>this.length&&(s=this.length),e.length-t=0;--n)e[n+t]=this[n+i];else if(r<1e3||!Buffer.TYPED_ARRAY_SUPPORT)for(n=0;n>>=0,i=void 0===i?this.length:i>>>0,e||(e=0),"number"==typeof e)for(r=t;r55295&&i<57344){if(!n){if(i>56319){(t-=3)>-1&&r.push(239,191,189);continue}if(o+1===s){(t-=3)>-1&&r.push(239,191,189);continue}n=i;continue}if(i<56320){(t-=3)>-1&&r.push(239,191,189),n=i;continue}i=65536+(n-55296<<10|i-56320)}else n&&(t-=3)>-1&&r.push(239,191,189);if(n=null,i<128){if((t-=1)<0)break;r.push(i)}else if(i<2048){if((t-=2)<0)break;r.push(i>>6|192,63&i|128)}else if(i<65536){if((t-=3)<0)break;r.push(i>>12|224,i>>6&63|128,63&i|128)}else{if(!(i<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;r.push(i>>18|240,i>>12&63|128,i>>6&63|128,63&i|128)}}return r}function base64ToBytes(e){return s.toByteArray(function base64clean(e){if((e=function stringtrim(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(a,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function blitBuffer(e,t,i,s){for(var n=0;n=t.length||n>=e.length);++n)t[n+i]=e[n];return n}}).call(this,i(22))},function(e,t){var i,s,n=e.exports={};function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}function runTimeout(e){if(i===setTimeout)return setTimeout(e,0);if((i===defaultSetTimout||!i)&&setTimeout)return i=setTimeout,setTimeout(e,0);try{return i(e,0)}catch(t){try{return i.call(null,e,0)}catch(t){return i.call(this,e,0)}}}!function(){try{i="function"==typeof setTimeout?setTimeout:defaultSetTimout}catch(e){i=defaultSetTimout}try{s="function"==typeof clearTimeout?clearTimeout:defaultClearTimeout}catch(e){s=defaultClearTimeout}}();var r,o=[],a=!1,c=-1;function cleanUpNextTick(){a&&r&&(a=!1,r.length?o=r.concat(o):c=-1,o.length&&drainQueue())}function drainQueue(){if(!a){var e=runTimeout(cleanUpNextTick);a=!0;for(var t=o.length;t;){for(r=o,o=[];++c1)for(var i=1;i0&&o.length>n&&!o.warned){o.warned=!0;var a=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");a.name="MaxListenersExceededWarning",a.emitter=e,a.type=t,a.count=o.length,function ProcessEmitWarning(e){console&&console.warn&&console.warn(e)}(a)}return e}function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(e,t,i){var s={fired:!1,wrapFn:void 0,target:e,type:t,listener:i},n=onceWrapper.bind(s);return n.listener=i,s.wrapFn=n,n}function _listeners(e,t,i){var s=e._events;if(void 0===s)return[];var n=s[t];return void 0===n?[]:"function"==typeof n?i?[n.listener||n]:[n]:i?function unwrapListeners(e){for(var t=new Array(e.length),i=0;i0&&(o=t[0]),o instanceof Error)throw o;var a=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw a.context=o,a}var c=n[e];if(void 0===c)return!1;if("function"==typeof c)r(c,this,t);else{var l=c.length,h=arrayClone(c,l);for(i=0;i=0;r--)if(i[r]===t||i[r].listener===t){o=i[r].listener,n=r;break}if(n<0)return this;0===n?i.shift():function spliceOne(e,t){for(;t+1=0;s--)this.removeListener(e,t[s]);return this},EventEmitter.prototype.listeners=function listeners(e){return _listeners(this,e,!0)},EventEmitter.prototype.rawListeners=function rawListeners(e){return _listeners(this,e,!1)},EventEmitter.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):listenerCount.call(e,t)},EventEmitter.prototype.listenerCount=listenerCount,EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?s(this._events):[]}},function(e,t,i){"use strict";const s=i(5),{ChannelTypes:n}=i(0),r=i(6);e.exports=class Channel extends s{constructor(e,t){super(e);const i=Object.keys(n)[t.type];this.type=i?i.toLowerCase():"unknown",this.deleted=!1,t&&this._patch(t)}_patch(e){this.id=e.id}get createdTimestamp(){return r.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toString(){return`<#${this.id}>`}delete(){return this.client.api.channels(this.id).delete().then((()=>this))}fetch(e=!1){return this.client.channels.fetch(this.id,!0,e)}isText(){return"messages"in this}static create(e,t,s){const r=i(10);let o;if(t.guild_id||s){if(s=s||e.guilds.cache.get(t.guild_id)){switch(t.type){case n.TEXT:o=new(r.get("TextChannel"))(s,t);break;case n.VOICE:o=new(r.get("VoiceChannel"))(s,t);break;case n.CATEGORY:o=new(r.get("CategoryChannel"))(s,t);break;case n.NEWS:o=new(r.get("NewsChannel"))(s,t);break;case n.STORE:o=new(r.get("StoreChannel"))(s,t);break}o&&s.channels.cache.set(o.id,o)}}else if(t.recipients&&t.type!==n.GROUP||t.type===n.DM){o=new(r.get("DMChannel"))(e,t)}else if(t.type===n.GROUP){o=new(i(143))(e,t)}return o}toJSON(...e){return super.toJSON({createdTimestamp:!0},...e)}}},function(e,t,i){"use strict";const s=i(17),n=i(19),r=i(42),o=i(20),{Error:a,TypeError:c}=i(2),l=i(3),h=i(8),u=i(4);e.exports=class GuildChannel extends s{constructor(e,t){super(e.client,t),this.guild=e}_patch(e){if(super._patch(e),this.name=e.name,this.rawPosition=e.position,this.parentID=e.parent_id||null,this.permissionOverwrites=new l,e.permission_overwrites)for(const t of e.permission_overwrites)this.permissionOverwrites.set(t.id,new r(this,t))}get parent(){return this.guild.channels.cache.get(this.parentID)||null}get permissionsLocked(){return this.parent?this.permissionOverwrites.size===this.parent.permissionOverwrites.size&&this.permissionOverwrites.every(((e,t)=>{const i=this.parent.permissionOverwrites.get(t);return void 0!==i&&i.deny.bitfield===e.deny.bitfield&&i.allow.bitfield===e.allow.bitfield})):null}get position(){const e=this.guild._sortedChannels(this);return e.array().indexOf(e.get(this.id))}permissionsFor(e){const t=this.guild.members.resolve(e);if(t)return this.memberPermissions(t);const i=this.guild.roles.resolve(e);return i?this.rolePermissions(i):null}overwritesFor(e,t=!1,i=null){if(t||(e=this.guild.members.resolve(e)),!e)return[];i=i||e.roles.cache;const s=[];let n,r;for(const t of this.permissionOverwrites.values())t.id===this.guild.id?r=t:i.has(t.id)?s.push(t):t.id===e.id&&(n=t);return{everyone:r,roles:s,member:n}}memberPermissions(e){if(e.id===this.guild.ownerID)return new h(h.ALL).freeze();const t=e.roles.cache,i=new h(t.map((e=>e.permissions)));if(i.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const s=this.overwritesFor(e,!0,t);return i.remove(s.everyone?s.everyone.deny:0).add(s.everyone?s.everyone.allow:0).remove(s.roles.length>0?s.roles.map((e=>e.deny)):0).add(s.roles.length>0?s.roles.map((e=>e.allow)):0).remove(s.member?s.member.deny:0).add(s.member?s.member.allow:0).freeze()}rolePermissions(e){if(e.permissions.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const t=this.permissionOverwrites.get(this.guild.id),i=this.permissionOverwrites.get(e.id);return e.permissions.remove(t?t.deny:0).add(t?t.allow:0).remove(i?i.deny:0).add(i?i.allow:0).freeze()}overwritePermissions(e,t){return Array.isArray(e)||e instanceof l?this.edit({permissionOverwrites:e,reason:t}).then((()=>this)):Promise.reject(new c("INVALID_TYPE","overwrites","Array or Collection of Permission Overwrites",!0))}updateOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role"));const s=this.permissionOverwrites.get(e.id);return s?s.update(t,i).then((()=>this)):this.createOverwrite(e,t,i)}createOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role"));const s=e instanceof o?"role":"member",{allow:n,deny:a}=r.resolveOverwriteOptions(t);return this.client.api.channels(this.id).permissions[e.id].put({data:{id:e.id,type:s,allow:n.bitfield,deny:a.bitfield},reason:i}).then((()=>this))}lockPermissions(){if(!this.parent)return Promise.reject(new a("GUILD_CHANNEL_ORPHAN"));const e=this.parent.permissionOverwrites.map((e=>e.toJSON()));return this.edit({permissionOverwrites:e})}get members(){const e=new l;for(const t of this.guild.members.cache.values())this.permissionsFor(t).has("VIEW_CHANNEL",!1)&&e.set(t.id,t);return e}async edit(e,t){let i;if(void 0!==e.position&&await u.setPosition(this,e.position,!1,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,t).then((e=>{this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e})})),e.permissionOverwrites&&(i=e.permissionOverwrites.map((e=>r.resolve(e,this.guild)))),e.lockPermissions)if(e.parentID){const t=this.guild.channels.resolve(e.parentID);t&&"category"===t.type&&(i=t.permissionOverwrites.map((e=>r.resolve(e,this.guild))))}else this.parent&&(i=this.parent.permissionOverwrites.map((e=>r.resolve(e,this.guild))));const s=await this.client.api.channels(this.id).patch({data:{name:(e.name||this.name).trim(),topic:e.topic,nsfw:e.nsfw,bitrate:e.bitrate||this.bitrate,user_limit:void 0!==e.userLimit?e.userLimit:this.userLimit,parent_id:e.parentID,lock_permissions:e.lockPermissions,rate_limit_per_user:e.rateLimitPerUser,permission_overwrites:i},reason:t}),n=this._clone();return n._patch(s),n}setName(e,t){return this.edit({name:e},t)}setParent(e,{lockPermissions:t=!0,reason:i}={}){return this.edit({parentID:null!==e?e.hasOwnProperty("id")?e.id:e:null,lockPermissions:t},i)}setTopic(e,t){return this.edit({topic:e},t)}setPosition(e,{relative:t,reason:i}={}){return u.setPosition(this,e,t,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,i).then((e=>(this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e}),this)))}createInvite({temporary:e=!1,maxAge:t=86400,maxUses:i=0,unique:s,reason:r}={}){return this.client.api.channels(this.id).invites.post({data:{temporary:e,max_age:t,max_uses:i,unique:s},reason:r}).then((e=>new n(this.client,e)))}async fetchInvites(){const e=await this.client.api.channels(this.id).invites.get(),t=new l;for(const i of e){const e=new n(this.client,i);t.set(e.code,e)}return t}clone(e={}){return u.mergeDefault({name:this.name,permissionOverwrites:this.permissionOverwrites,topic:this.topic,type:this.type,nsfw:this.nsfw,parent:this.parent,bitrate:this.bitrate,userLimit:this.userLimit,rateLimitPerUser:this.rateLimitPerUser,reason:null},e),this.guild.channels.create(e.name,e)}equals(e){let t=e&&this.id===e.id&&this.type===e.type&&this.topic===e.topic&&this.position===e.position&&this.name===e.name;return t&&(t=this.permissionOverwrites&&e.permissionOverwrites?this.permissionOverwrites.equals(e.permissionOverwrites):!this.permissionOverwrites&&!e.permissionOverwrites),t}get deletable(){return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get manageable(){if(this.client.user.id===this.guild.ownerID)return!0;if("voice"===this.type){if(!this.permissionsFor(this.client.user).has(h.FLAGS.CONNECT,!1))return!1}else if(!this.viewable)return!1;return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get viewable(){if(this.client.user.id===this.guild.ownerID)return!0;const e=this.permissionsFor(this.client.user);return!!e&&e.has(h.FLAGS.VIEW_CHANNEL,!1)}delete(e){return this.client.api.channels(this.id).delete({reason:e}).then((()=>this))}}},function(e,t,i){"use strict";const s=i(5),{Endpoints:n}=i(0),r=i(8);e.exports=class Invite extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.guild=e.guild?this.client.guilds.add(e.guild,!1):null,this.code=e.code,this.presenceCount="approximate_presence_count"in e?e.approximate_presence_count:null,this.memberCount="approximate_member_count"in e?e.approximate_member_count:null,this.temporary="temporary"in e?e.temporary:null,this.maxAge="max_age"in e?e.max_age:null,this.uses="uses"in e?e.uses:null,this.maxUses="max_uses"in e?e.max_uses:null,this.inviter=e.inviter?this.client.users.add(e.inviter):null,this.targetUser=e.target_user?this.client.users.add(e.target_user):null,this.targetUserType="number"==typeof e.target_user_type?e.target_user_type:null,this.channel=this.client.channels.add(e.channel,this.guild,!1),this.createdTimestamp="created_at"in e?new Date(e.created_at).getTime():null}get createdAt(){return this.createdTimestamp?new Date(this.createdTimestamp):null}get deletable(){const e=this.guild;if(!e||!this.client.guilds.cache.has(e.id))return!1;if(!e.me)throw new Error("GUILD_UNCACHED_ME");return this.channel.permissionsFor(this.client.user).has(r.FLAGS.MANAGE_CHANNELS,!1)||e.me.permissions.has(r.FLAGS.MANAGE_GUILD)}get expiresTimestamp(){return this.createdTimestamp&&this.maxAge?this.createdTimestamp+1e3*this.maxAge:null}get expiresAt(){const{expiresTimestamp:e}=this;return e?new Date(e):null}get url(){return n.invite(this.client.options.http.invite,this.code)}delete(e){return this.client.api.invites[this.code].delete({reason:e}).then((()=>this))}toString(){return this.url}toJSON(){return super.toJSON({url:!0,expiresTimestamp:!0,presenceCount:!1,memberCount:!1,uses:!1,channel:"channelID",inviter:"inviterID",guild:"guildID"})}valueOf(){return this.code}}},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(2),o=i(8),a=i(6),c=i(4);e.exports=class Role extends s{constructor(e,t,i){super(e),this.guild=i,t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.color=e.color,this.hoist=e.hoist,this.rawPosition=e.position,this.permissions=new o(e.permissions).freeze(),this.managed=e.managed,this.mentionable=e.mentionable,this.deleted=!1}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get hexColor(){return"#"+this.color.toString(16).padStart(6,"0")}get members(){return this.guild.members.cache.filter((e=>e.roles.cache.has(this.id)))}get editable(){if(this.managed)return!1;const e=this.guild.member(this.client.user);return!!e.permissions.has(o.FLAGS.MANAGE_ROLES)&&e.roles.highest.comparePositionTo(this)>0}get position(){const e=this.guild._sortedRoles();return e.array().indexOf(e.get(this.id))}comparePositionTo(e){if(!(e=this.guild.roles.resolve(e)))throw new r("INVALID_TYPE","role","Role nor a Snowflake");return this.constructor.comparePositions(this,e)}async edit(e,t){return void 0!==e.permissions?e.permissions=o.resolve(e.permissions):e.permissions=this.permissions.bitfield,void 0!==e.position&&await c.setPosition(this,e.position,!1,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,t).then((e=>{this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e})})),this.client.api.guilds[this.guild.id].roles[this.id].patch({data:{name:e.name||this.name,color:null!==e.color?c.resolveColor(e.color||this.color):null,hoist:void 0!==e.hoist?e.hoist:this.hoist,permissions:e.permissions,mentionable:void 0!==e.mentionable?e.mentionable:this.mentionable},reason:t}).then((e=>{const t=this._clone();return t._patch(e),t}))}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new n("GUILD_CHANNEL_RESOLVE");return e.rolePermissions(this)}setName(e,t){return this.edit({name:e},t)}setColor(e,t){return this.edit({color:e},t)}setHoist(e,t){return this.edit({hoist:e},t)}setPermissions(e,t){return this.edit({permissions:e},t)}setMentionable(e,t){return this.edit({mentionable:e},t)}setPosition(e,{relative:t,reason:i}={}){return c.setPosition(this,e,t,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,i).then((e=>(this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e}),this)))}delete(e){return this.client.api.guilds[this.guild.id].roles[this.id].delete({reason:e}).then((()=>(this.client.actions.GuildRoleDelete.handle({guild_id:this.guild.id,role_id:this.id}),this)))}equals(e){return e&&this.id===e.id&&this.name===e.name&&this.color===e.color&&this.hoist===e.hoist&&this.position===e.position&&this.permissions.bitfield===e.permissions.bitfield&&this.managed===e.managed}toString(){return this.id===this.guild.id?"@everyone":`<@&${this.id}>`}toJSON(){return super.toJSON({createdTimestamp:!0})}static comparePositions(e,t){return e.position===t.position?t.id-e.id:e.position-t.position}}},function(e,t,i){"use strict";var s=i(31),n=Object.keys||function(e){var t=[];for(var i in e)t.push(i);return t};e.exports=Duplex;var r=Object.create(i(26));r.inherits=i(23);var o=i(67),a=i(46);r.inherits(Duplex,o);for(var c=n(a.prototype),l=0;lnew Activity(this,e))):e.activity||e.game?this.activities=[new Activity(this,e.game||e.activity)]:this.activities=[],this.clientStatus=e.client_status||null,this}_clone(){const e=Object.assign(Object.create(this),this);return this.activities&&(e.activities=this.activities.map((e=>e._clone()))),e}equals(e){return this===e||e&&this.status===e.status&&this.activities.length===e.activities.length&&this.activities.every(((t,i)=>t.equals(e.activities[i])))&&this.clientStatus.web===e.clientStatus.web&&this.clientStatus.mobile===e.clientStatus.mobile&&this.clientStatus.desktop===e.clientStatus.desktop}toJSON(){return o.flatten(this)}},t.Activity=Activity,t.RichPresenceAssets=RichPresenceAssets},function(e,t,i){"use strict";const s=i(40),{Error:n}=i(2),r=i(66),o=i(8);class GuildEmoji extends s{constructor(e,t,i){super(e,t,i),this.author=null}_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}_patch(e){super._patch(e),void 0!==e.user&&(this.author=this.client.users.add(e.user))}get deletable(){if(!this.guild.me)throw new n("GUILD_UNCACHED_ME");return!this.managed&&this.guild.me.hasPermission(o.FLAGS.MANAGE_EMOJIS)}get roles(){return new r(this)}async fetchAuthor(){if(this.managed)throw new n("EMOJI_MANAGED");if(!this.guild.me)throw new n("GUILD_UNCACHED_ME");if(!this.guild.me.permissions.has(o.FLAGS.MANAGE_EMOJIS))throw new n("MISSING_MANAGE_EMOJIS_PERMISSION",this.guild);const e=await this.client.api.guilds(this.guild.id).emojis(this.id).get();return this._patch(e),this.author}edit(e,t){const i=e.roles?e.roles.map((e=>e.id||e)):void 0;return this.client.api.guilds(this.guild.id).emojis(this.id).patch({data:{name:e.name,roles:i},reason:t}).then((e=>{const t=this._clone();return t._patch(e),t}))}setName(e,t){return this.edit({name:e},t)}delete(e){return this.client.api.guilds(this.guild.id).emojis(this.id).delete({reason:e}).then((()=>this))}equals(e){return e instanceof GuildEmoji?e.id===this.id&&e.name===this.name&&e.managed===this.managed&&e.requiresColons===this.requiresColons&&e.roles.cache.size===this.roles.cache.size&&e.roles.cache.every((e=>this.roles.cache.has(e.id))):e.id===this.id&&e.name===this.name&&e.roles.length===this.roles.cache.size&&e.roles.every((e=>this.roles.cache.has(e)))}}e.exports=GuildEmoji},function(e,t,i){(function(e){function objectToString(e){return Object.prototype.toString.call(e)}t.isArray=function isArray(e){return Array.isArray?Array.isArray(e):"[object Array]"===objectToString(e)},t.isBoolean=function isBoolean(e){return"boolean"==typeof e},t.isNull=function isNull(e){return null===e},t.isNullOrUndefined=function isNullOrUndefined(e){return null==e},t.isNumber=function isNumber(e){return"number"==typeof e},t.isString=function isString(e){return"string"==typeof e},t.isSymbol=function isSymbol(e){return"symbol"==typeof e},t.isUndefined=function isUndefined(e){return void 0===e},t.isRegExp=function isRegExp(e){return"[object RegExp]"===objectToString(e)},t.isObject=function isObject(e){return"object"==typeof e&&null!==e},t.isDate=function isDate(e){return"[object Date]"===objectToString(e)},t.isError=function isError(e){return"[object Error]"===objectToString(e)||e instanceof Error},t.isFunction=function isFunction(e){return"function"==typeof e},t.isPrimitive=function isPrimitive(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(5),n=i(33),{Error:r}=i(2),o=i(6),a=i(80);let c;class User extends s{constructor(e,t){super(e),this.id=t.id,this.system=null,this.locale=null,this.flags=null,this._patch(t)}_patch(e){"username"in e?this.username=e.username:"string"!=typeof this.username&&(this.username=null),("bot"in e||"boolean"!=typeof this.bot)&&(this.bot=Boolean(e.bot)),"discriminator"in e?this.discriminator=e.discriminator:"string"!=typeof this.discriminator&&(this.discriminator=null),"avatar"in e?this.avatar=e.avatar:"string"!=typeof this.avatar&&(this.avatar=null),"system"in e&&(this.system=Boolean(e.system)),"locale"in e&&(this.locale=e.locale),"public_flags"in e&&(this.flags=new a(e.public_flags)),this.lastMessageID=null,this.lastMessageChannelID=null}get partial(){return"string"!=typeof this.username}get createdTimestamp(){return o.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get lastMessage(){const e=this.client.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get presence(){for(const e of this.client.guilds.cache.values())if(e.presences.cache.has(this.id))return e.presences.cache.get(this.id);c||(c=i(10));return new(c.get("Presence"))(this.client,{user:{id:this.id}})}avatarURL({format:e,size:t,dynamic:i}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t,i):null}get defaultAvatarURL(){return this.client.rest.cdn.DefaultAvatar(this.discriminator%5)}displayAvatarURL(e){return this.avatarURL(e)||this.defaultAvatarURL}get tag(){return"string"==typeof this.username?`${this.username}#${this.discriminator}`:null}typingIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)}typingSinceIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?new Date(e._typing.get(this.id).since):null}typingDurationIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?e._typing.get(this.id).elapsedTime:-1}get dmChannel(){return this.client.channels.cache.find((e=>"dm"===e.type&&e.recipient.id===this.id))||null}async createDM(e=!1){if(!e){const{dmChannel:e}=this;if(e&&!e.partial)return e}const t=await this.client.api.users(this.client.user.id).channels.post({data:{recipient_id:this.id}});return this.client.actions.ChannelCreate.handle(t).channel}async deleteDM(){const{dmChannel:e}=this;if(!e)throw new r("USER_NO_DMCHANNEL");const t=await this.client.api.channels(e.id).delete();return this.client.actions.ChannelDelete.handle(t).channel}equals(e){return e&&this.id===e.id&&this.username===e.username&&this.discriminator===e.discriminator&&this.avatar===e.avatar}async fetchFlags(e=!1){if(this.flags&&!e)return this.flags;const t=await this.client.api.users(this.id).get();return this._patch(t),this.flags}fetch(e=!1){return this.client.users.fetch(this.id,!0,e)}toString(){return`<@${this.id}>`}toJSON(...e){const t=super.toJSON({createdTimestamp:!0,defaultAvatarURL:!0,tag:!0,lastMessage:!1,lastMessageID:!1},...e);return t.avatarURL=this.avatarURL(),t.displayAvatarURL=this.displayAvatarURL(),t}send(){}}n.applyToClass(User),e.exports=User},function(e,t,i){"use strict";const s=i(30),n=i(5),r=i(50),o=i(43),a=i(44),c=i(76),l=i(77),{Error:h,TypeError:u}=i(2),d=i(78),f=i(3),{MessageTypes:p}=i(0),m=i(47),g=i(8),E=i(6),_=i(4);e.exports=class Message extends n{constructor(e,t,i){super(e),this.channel=i,this.deleted=!1,t&&this._patch(t)}_patch(e){if(this.id=e.id,"type"in e?(this.type=p[e.type],this.system=0!==e.type):"string"!=typeof this.type&&(this.system=null,this.type=null),"content"in e?this.content=e.content:"string"!=typeof this.content&&(this.content=null),"author"in e?this.author=this.client.users.add(e.author,!e.webhook_id):this.author||(this.author=null),"pinned"in e?this.pinned=Boolean(e.pinned):"boolean"!=typeof this.pinned&&(this.pinned=null),"tts"in e?this.tts=e.tts:"boolean"!=typeof this.tts&&(this.tts=null),this.nonce="nonce"in e?e.nonce:null,this.embeds=(e.embeds||[]).map((e=>new a(e,!0))),this.attachments=new f,e.attachments)for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t));if(this.createdTimestamp=E.deconstruct(this.id).timestamp,this.editedTimestamp="edited_timestamp"in e?new Date(e.edited_timestamp).getTime():null,this.reactions=new d(this),e.reactions&&e.reactions.length>0)for(const t of e.reactions)this.reactions.add(t);this.mentions=new c(this,e.mentions,e.mention_roles,e.mention_everyone,e.mention_channels),this.webhookID=e.webhook_id||null,this.application=e.application?new r(this.client,e.application):null,this.activity=e.activity?{partyID:e.activity.party_id,type:e.activity.type}:null,this._edits=[],this.member&&e.member?this.member._patch(e.member):e.member&&this.guild&&this.author&&this.guild.members.add(Object.assign(e.member,{user:this.author})),this.flags=new m(e.flags).freeze(),this.reference=e.message_reference?{channelID:e.message_reference.channel_id,guildID:e.message_reference.guild_id,messageID:e.message_reference.message_id}:null}get partial(){return"string"!=typeof this.content||!this.author}patch(e){const t=this._clone(),{messageEditHistoryMaxSize:i}=this.client.options;if(0!==i){const e=-1===i?1/0:i;this._edits.unshift(t)>e&&this._edits.pop()}if("edited_timestamp"in e&&(this.editedTimestamp=new Date(e.edited_timestamp).getTime()),"content"in e&&(this.content=e.content),"pinned"in e&&(this.pinned=e.pinned),"tts"in e&&(this.tts=e.tts),this.embeds="embeds"in e?e.embeds.map((e=>new a(e,!0))):this.embeds.slice(),"attachments"in e){this.attachments=new f;for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t))}else this.attachments=new f(this.attachments);return this.mentions=new c(this,"mentions"in e?e.mentions:this.mentions.users,"mention_roles"in e?e.mention_roles:this.mentions.roles,"mention_everyone"in e?e.mention_everyone:this.mentions.everyone,"mention_channels"in e?e.mention_channels:this.mentions.crosspostedChannels),this.flags=new m("flags"in e?e.flags:0).freeze(),t}get member(){return this.guild&&this.guild.member(this.author)||null}get createdAt(){return new Date(this.createdTimestamp)}get editedAt(){return this.editedTimestamp?new Date(this.editedTimestamp):null}get guild(){return this.channel.guild||null}get url(){return`https://discord.com/channels/${this.guild?this.guild.id:"@me"}/${this.channel.id}/${this.id}`}get cleanContent(){return null!=this.content?_.cleanContent(this.content,this):null}createReactionCollector(e,t={}){return new l(this,e,t)}awaitReactions(e,t={}){return new Promise(((i,s)=>{this.createReactionCollector(e,t).once("end",((e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)}))}))}get edits(){const e=this._edits.slice();return e.unshift(this),e}get editable(){return this.author.id===this.client.user.id}get deletable(){return!this.deleted&&(this.author.id===this.client.user.id||this.guild&&this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}get pinnable(){return"DEFAULT"===this.type&&(!this.guild||this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}get crosspostable(){return"news"===this.channel.type&&!this.flags.has(m.FLAGS.CROSSPOSTED)&&"DEFAULT"===this.type&&this.channel.viewable&&this.channel.permissionsFor(this.client.user).has(g.FLAGS.SEND_MESSAGES)&&(this.author.id===this.client.user.id||this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES))}edit(e,t){const{data:i}=e instanceof s?e.resolveData():s.create(this,e,t).resolveData();return this.client.api.channels[this.channel.id].messages[this.id].patch({data:i}).then((e=>{const t=this._clone();return t._patch(e),t}))}async crosspost(){return await this.client.api.channels(this.channel.id).messages(this.id).crosspost.post(),this}pin(e){return this.client.api.channels(this.channel.id).pins(this.id).put(e).then((()=>this))}unpin(e){return this.client.api.channels(this.channel.id).pins(this.id).delete(e).then((()=>this))}react(e){if(!(e=this.client.emojis.resolveIdentifier(e)))throw new u("EMOJI_TYPE");return this.client.api.channels(this.channel.id).messages(this.id).reactions(e,"@me").put().then((()=>this.client.actions.MessageReactionAdd.handle({user:this.client.user,channel:this.channel,message:this,emoji:_.parseEmoji(e)}).reaction))}delete(e={}){if("object"!=typeof e)return Promise.reject(new u("INVALID_TYPE","options","object",!0));const{timeout:t=0,reason:i}=e;return t<=0?this.channel.messages.delete(this.id,i).then((()=>this)):new Promise((e=>{this.client.setTimeout((()=>{e(this.delete({reason:i}))}),t)}))}reply(e,t){return this.channel.send(e instanceof s?e:s.transformOptions(e,t,{reply:this.member||this.author}))}fetch(e=!1){return this.channel.messages.fetch(this.id,!0,e)}fetchWebhook(){return this.webhookID?this.client.fetchWebhook(this.webhookID):Promise.reject(new h("WEBHOOK_MESSAGE"))}suppressEmbeds(e=!0){const t=new m(this.flags.bitfield);return e?t.add(m.FLAGS.SUPPRESS_EMBEDS):t.remove(m.FLAGS.SUPPRESS_EMBEDS),this.edit({flags:t})}equals(e,t){if(!e)return!1;if(!e.author&&!e.attachments)return this.id===e.id&&this.embeds.length===e.embeds.length;let i=this.id===e.id&&this.author.id===e.author.id&&this.content===e.content&&this.tts===e.tts&&this.nonce===e.nonce&&this.embeds.length===e.embeds.length&&this.attachments.length===e.attachments.length;return i&&t&&(i=this.mentions.everyone===e.mentions.everyone&&this.createdTimestamp===new Date(t.timestamp).getTime()&&this.editedTimestamp===new Date(t.edited_timestamp).getTime()),i}toString(){return this.content}toJSON(){return super.toJSON({channel:"channelID",author:"authorID",application:"applicationID",guild:"guildID",cleanContent:!0,member:!1,reactions:!1})}}},function(e,t,i){"use strict";const s=i(5),n=i(6);e.exports=class Emoji extends s{constructor(e,t){super(e),this.animated=t.animated,this.name=t.name,this.id=t.id,this.deleted=!1}get identifier(){return this.id?`${this.animated?"a:":""}${this.name}:${this.id}`:encodeURIComponent(this.name)}get url(){return this.id?this.client.rest.cdn.Emoji(this.id,this.animated?"gif":"png"):null}get createdTimestamp(){return this.id?n.deconstruct(this.id).timestamp:null}get createdAt(){return this.id?new Date(this.createdTimestamp):null}toString(){return this.id?`<${this.animated?"a":""}:${this.name}:${this.id}>`:this.name}toJSON(){return super.toJSON({guild:"guildID",createdTimestamp:!0,url:!0,identifier:!0})}}},function(e,t,i){"use strict";(function(t){const s=i(43),n=i(44),{RangeError:r}=i(2),{browser:o}=i(0),a=i(9),c=i(47),l=i(4);class APIMessage{constructor(e,t){this.target=e,this.options=t,this.data=null,this.files=null}get isWebhook(){const e=i(13),t=i(48);return this.target instanceof e||this.target instanceof t}get isUser(){const e=i(27),t=i(11);return this.target instanceof e||this.target instanceof t}get isMessage(){const e=i(28);return this.target instanceof e}makeContent(){const e=i(11);let t;if(null===this.options.content?t="":void 0!==this.options.content&&(t=l.resolveString(this.options.content)),"string"!=typeof t)return t;const s=void 0===this.options.disableMentions?this.target.client.options.disableMentions:this.options.disableMentions;"all"===s?t=l.removeMentions(t):"everyone"===s&&(t=t.replace(/@([^<>@ ]*)/gmus,((e,t)=>t.match(/^[&!]?\d+$/)?"@"+t:"@​"+t)));const n=void 0!==this.options.split&&!1!==this.options.split,r=void 0!==this.options.code&&!1!==this.options.code,o=n?{...this.options.split}:void 0;let a="";if(this.options.reply&&!this.isUser&&"dm"!==this.target.type){const t=this.target.client.users.resolveID(this.options.reply);a=`<@${this.options.reply instanceof e&&this.options.reply.nickname?"!":""}${t}>, `,n&&(o.prepend=`${a}${o.prepend||""}`)}if(t||a){if(r){const e="string"==typeof this.options.code?this.options.code:"";t=`${a}\`\`\`${e}\n${l.cleanCodeBlockContent(t)}\n\`\`\``,n&&(o.prepend=`${o.prepend||""}\`\`\`${e}\n`,o.append="\n```"+(o.append||""))}else a&&(t=`${a}${t}`);n&&(t=l.splitMessage(t,o))}return t}resolveData(){if(this.data)return this;const e=this.makeContent(),t=Boolean(this.options.tts);let i;if(void 0!==this.options.nonce&&(i=parseInt(this.options.nonce),isNaN(i)||i<0))throw new r("MESSAGE_NONCE_TYPE");const s=[];this.isWebhook?this.options.embeds&&s.push(...this.options.embeds):this.options.embed&&s.push(this.options.embed);const o=s.map((e=>new n(e).toJSON()));let a,h,u;this.isWebhook&&(a=this.options.username||this.target.name,this.options.avatarURL&&(h=this.options.avatarURL)),this.isMessage&&(u=null!=this.options.flags?new c(this.options.flags).bitfield:this.target.flags.bitfield);let d=void 0===this.options.allowedMentions?this.target.client.options.allowedMentions:this.options.allowedMentions;if(this.options.reply){const e=this.target.client.users.resolveID(this.options.reply);if(d){d=l.cloneObject(d);d.parse&&d.parse.includes("users")||d.users&&d.users.includes(e)||(d.users||(d.users=[]),d.users.push(e))}else d={users:[e]}}return this.data={content:e,tts:t,nonce:i,embed:null===this.options.embed?null:o[0],embeds:o,username:a,avatar_url:h,allowed_mentions:void 0===e?void 0:d,flags:u},this}async resolveFiles(){if(this.files)return this;const e=[];this.isWebhook?this.options.embeds&&e.push(...this.options.embeds):this.options.embed&&e.push(this.options.embed);const t=[];this.options.files&&t.push(...this.options.files);for(const i of e)i.files&&t.push(...i.files);return this.files=await Promise.all(t.map((e=>this.constructor.resolveFile(e)))),this}split(){if(this.data||this.resolveData(),!Array.isArray(this.data.content))return[this];const e=[];for(let t=0;t"string"==typeof e?l.basename(e):e.path?l.basename(e.path):"file.jpg";"string"==typeof e||e instanceof(o?ArrayBuffer:t)||"function"==typeof e.pipe?(i=e,s=findName(i)):(i=e.attachment,s=e.name||findName(i));return{attachment:i,name:s,file:await a.resolveFile(i)}}static partitionMessageAdditions(e){const t=[],i=[];for(const r of e)r instanceof n?t.push(r):r instanceof s&&i.push(r);return[t,i]}static transformOptions(e,t,i={},r=!1){if(t||"object"!=typeof e||Array.isArray(e)||(t=e,e=void 0),t){if(t instanceof n)return r?{content:e,embeds:[t],...i}:{content:e,embed:t,...i};if(t instanceof s)return{content:e,files:[t],...i}}else t={};if(Array.isArray(t)){const[s,n]=this.partitionMessageAdditions(t);return r?{content:e,embeds:s,files:n,...i}:{content:e,embed:s[0],files:n,...i}}if(Array.isArray(e)){const[t,s]=this.partitionMessageAdditions(e);if(t.length||s.length)return r?{embeds:t,files:s,...i}:{embed:t[0],files:s,...i}}return{content:e,...t,...i}}static create(e,t,s,n={}){const r=i(13),o=i(48),a=e instanceof r||e instanceof o;return new this(e,this.transformOptions(t,s,n,a))}}e.exports=APIMessage}).call(this,i(14).Buffer)},function(e,t,i){"use strict";(function(t){void 0===t||!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function nextTick(e,i,s,n){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var r,o,a=arguments.length;switch(a){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick((function afterTickOne(){e.call(null,i)}));case 3:return t.nextTick((function afterTickTwo(){e.call(null,i,s)}));case 4:return t.nextTick((function afterTickThree(){e.call(null,i,s,n)}));default:for(r=new Array(a-1),o=0;oi.send(e,t)));let o;if(e instanceof n)o=e.resolveData();else if(o=n.create(this,e,t).resolveData(),Array.isArray(o.data.content))return Promise.all(o.split().map(this.send.bind(this)));const{data:a,files:c}=await o.resolveFiles();return this.client.api.channels[this.id].messages.post({data:a,files:c}).then((e=>this.client.actions.MessageCreate.handle(e).message))}startTyping(e){if(void 0!==e&&e<1)throw new a("TYPING_COUNT");if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);return t.count=e||t.count+1,t.promise}const t={};return t.promise=new Promise(((i,s)=>{const n=this.client.api.channels[this.id].typing;Object.assign(t,{count:e||1,interval:this.client.setInterval((()=>{n.post().catch((e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)}))}),9e3),resolve:i}),n.post().catch((e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)})),this.client.user._typing.set(this.id,t)})),t.promise}stopTyping(e=!1){if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);t.count--,(t.count<=0||e)&&(this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),t.resolve())}}get typing(){return this.client.user._typing.has(this.id)}get typingCount(){return this.client.user._typing.has(this.id)?this.client.user._typing.get(this.id).count:0}createMessageCollector(e,t={}){return new s(this,e,t)}awaitMessages(e,t={}){return new Promise(((i,s)=>{this.createMessageCollector(e,t).once("end",((e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)}))}))}async bulkDelete(e,t=!1){if(Array.isArray(e)||e instanceof o){let i=e instanceof o?e.keyArray():e.map((e=>e.id||e));if(t&&(i=i.filter((e=>Date.now()-r.deconstruct(e).date.getTime()<12096e5))),0===i.length)return new o;if(1===i.length){await this.client.api.channels(this.id).messages(i[0]).delete();const e=this.client.actions.MessageDelete.getMessage({message_id:i[0]},this);return e?new o([[e.id,e]]):new o}return await this.client.api.channels[this.id].messages["bulk-delete"].post({data:{messages:i}}),i.reduce(((e,t)=>e.set(t,this.client.actions.MessageDeleteBulk.getMessage({message_id:t},this))),new o)}if(!isNaN(e)){const i=await this.messages.fetch({limit:e});return this.bulkDelete(i,t)}throw new c("MESSAGE_BULK_DELETE_TYPE")}static applyToClass(e,t=!1,i=[]){const s=["send"];t&&s.push("lastMessage","lastPinAt","bulkDelete","startTyping","stopTyping","typing","typingCount","createMessageCollector","awaitMessages");for(const t of s)i.includes(t)||Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(TextBasedChannel.prototype,t))}}e.exports=TextBasedChannel;const l=i(34)},function(e,t,i){"use strict";const s=i(7),{TypeError:n}=i(2),r=i(28),o=i(3),a=i(137);e.exports=class MessageManager extends s{constructor(e,t){super(e.client,t,r,a,e.client.options.messageCacheMaxSize),this.channel=e}add(e,t){return super.add(e,t,{extras:[this.channel]})}fetch(e,t=!0,i=!1){return"string"==typeof e?this._fetchId(e,t,i):this._fetchMany(e,t)}fetchPinned(e=!0){return this.client.api.channels[this.channel.id].pins.get().then((t=>{const i=new o;for(const s of t)i.set(s.id,this.add(s,e));return i}))}async delete(e,t){if(!(e=this.resolveID(e)))throw new n("INVALID_TYPE","message","MessageResolvable");await this.client.api.channels(this.channel.id).messages(e).delete({reason:t})}async _fetchId(e,t,i){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.channels[this.channel.id].messages[e].get();return this.add(s,t)}async _fetchMany(e={},t){const i=await this.client.api.channels[this.channel.id].messages.get({query:e}),s=new o;for(const e of i)s.set(e.id,this.add(e,t));return s}}},function(e,t){},function(e,t,i){"use strict";var s=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==s)return s;throw new Error("unable to locate global object")}();e.exports=t=s.fetch,s.fetch&&(t.default=s.fetch.bind(s)),t.Headers=s.Headers,t.Request=s.Request,t.Response=s.Response},function(e,t,i){"use strict";(function(t,s){i(63);const n=i(16),r=i(107),{DefaultOptions:o}=i(0),a=i(4);e.exports=class BaseClient extends n{constructor(e={}){super(),this._timeouts=new Set,this._intervals=new Set,this._immediates=new Set,this.options=a.mergeDefault(o,e),this.rest=new r(this,e._tokenType)}get api(){return this.rest.api}destroy(){for(const e of this._timeouts)this.clearTimeout(e);for(const e of this._intervals)this.clearInterval(e);for(const e of this._immediates)this.clearImmediate(e);this._timeouts.clear(),this._intervals.clear(),this._immediates.clear()}setTimeout(e,t,...i){const s=setTimeout((()=>{e(...i),this._timeouts.delete(s)}),t);return this._timeouts.add(s),s}clearTimeout(e){clearTimeout(e),this._timeouts.delete(e)}setInterval(e,t,...i){const s=setInterval(e,t,...i);return this._intervals.add(s),s}clearInterval(e){clearInterval(e),this._intervals.delete(e)}setImmediate(e,...i){const s=t(e,...i);return this._immediates.add(s),s}clearImmediate(e){s(e),this._immediates.delete(e)}incrementMaxListeners(){const e=this.getMaxListeners();0!==e&&this.setMaxListeners(e+1)}decrementMaxListeners(){const e=this.getMaxListeners();0!==e&&this.setMaxListeners(e-1)}toJSON(...e){return a.flatten(this,{domain:!1},...e)}}}).call(this,i(38).setImmediate,i(38).clearImmediate)},function(e,t,i){(function(e){var s=void 0!==e&&e||"undefined"!=typeof self&&self||window,n=Function.prototype.apply;function Timeout(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new Timeout(n.call(setTimeout,s,arguments),clearTimeout)},t.setInterval=function(){return new Timeout(n.call(setInterval,s,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},Timeout.prototype.unref=Timeout.prototype.ref=function(){},Timeout.prototype.close=function(){this._clearFn.call(s,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout((function onTimeout(){e._onTimeout&&e._onTimeout()}),t))},i(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,i(22))},function(e,t,i){"use strict";const s=i(17),n=i(33),r=i(34);class DMChannel extends s{constructor(e,t){super(e,t),this.type="dm",this.messages=new r(this),this._typing=new Map}_patch(e){super._patch(e),e.recipients&&(this.recipient=this.client.users.add(e.recipients[0])),this.lastMessageID=e.last_message_id,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null}get partial(){return void 0===this.lastMessageID}fetch(e=!1){return this.recipient.createDM(e)}toString(){return this.recipient.toString()}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}}n.applyToClass(DMChannel,!0,["bulkDelete"]),e.exports=DMChannel},function(e,t,i){"use strict";const s=i(29);e.exports=class BaseGuildEmoji extends s{constructor(e,t,i){super(e,t),this.guild=i,this.requireColons=null,this.managed=null,this.available=null,Object.defineProperty(this,"_roles",{value:[],writable:!0}),this._patch(t)}_patch(e){e.name&&(this.name=e.name),void 0!==e.require_colons&&(this.requiresColons=e.require_colons),void 0!==e.managed&&(this.managed=e.managed),void 0!==e.available&&(this.available=e.available),e.roles&&(this._roles=e.roles)}}},function(e,t,i){"use strict";const s=i(18),n=i(13),r=i(33),o=i(34),a=i(3),c=i(9);class TextChannel extends s{constructor(e,t){super(e,t),this.messages=new o(this),this.nsfw=Boolean(t.nsfw),this._typing=new Map}_patch(e){if(super._patch(e),this.topic=e.topic,void 0!==e.nsfw&&(this.nsfw=Boolean(e.nsfw)),this.lastMessageID=e.last_message_id,this.rateLimitPerUser=e.rate_limit_per_user||0,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null,e.messages)for(const t of e.messages)this.messages.add(t)}setRateLimitPerUser(e,t){return this.edit({rateLimitPerUser:e},t)}setNSFW(e,t){return this.edit({nsfw:e},t)}fetchWebhooks(){return this.client.api.channels[this.id].webhooks.get().then((e=>{const t=new a;for(const i of e)t.set(i.id,new n(this.client,i));return t}))}async createWebhook(e,{avatar:t,reason:i}={}){return"string"!=typeof t||t.startsWith("data:")||(t=await c.resolveImage(t)),this.client.api.channels[this.id].webhooks.post({data:{name:e,avatar:t},reason:i}).then((e=>new n(this.client,e)))}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}bulkDelete(){}}r.applyToClass(TextChannel,!0),e.exports=TextChannel},function(e,t,i){"use strict";const s=i(20),{TypeError:n}=i(2),r=i(8),o=i(4);e.exports=class PermissionOverwrites{constructor(e,t){Object.defineProperty(this,"channel",{value:e}),t&&this._patch(t)}_patch(e){this.id=e.id,this.type=e.type,this.deny=new r(e.deny).freeze(),this.allow=new r(e.allow).freeze()}update(e,t){const{allow:i,deny:s}=this.constructor.resolveOverwriteOptions(e,this);return this.channel.client.api.channels(this.channel.id).permissions[this.id].put({data:{id:this.id,type:this.type,allow:i.bitfield,deny:s.bitfield},reason:t}).then((()=>this))}delete(e){return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({reason:e}).then((()=>this))}toJSON(){return o.flatten(this)}static resolveOverwriteOptions(e,{allow:t,deny:i}={}){t=new r(t),i=new r(i);for(const[s,n]of Object.entries(e))!0===n?(t.add(r.FLAGS[s]),i.remove(r.FLAGS[s])):!1===n?(t.remove(r.FLAGS[s]),i.add(r.FLAGS[s])):null===n&&(t.remove(r.FLAGS[s]),i.remove(r.FLAGS[s]));return{allow:t,deny:i}}static resolve(e,t){if(e instanceof this)return e.toJSON();if("string"==typeof e.id&&["role","member"].includes(e.type))return{...e,allow:r.resolve(e.allow),deny:r.resolve(e.deny)};const i=t.roles.resolve(e.id)||t.client.users.resolve(e.id);if(!i)throw new n("INVALID_TYPE","parameter","User nor a Role");const o=i instanceof s?"role":"member";return{id:i.id,type:o,allow:r.resolve(e.allow),deny:r.resolve(e.deny)}}}},function(e,t,i){"use strict";const s=i(4);e.exports=class MessageAttachment{constructor(e,t=null,i){this.attachment=e,this.name=t,i&&this._patch(i)}setFile(e,t=null){return this.attachment=e,this.name=t,this}setName(e){return this.name=e,this}_patch(e){this.id=e.id,this.size=e.size,this.url=e.url,this.proxyURL=e.proxy_url,this.height=void 0!==e.height?e.height:null,this.width=void 0!==e.width?e.width:null}get spoiler(){return s.basename(this.url).startsWith("SPOILER_")}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const{RangeError:s}=i(2),n=i(4);e.exports=class MessageEmbed{constructor(e={},t=!1){this.setup(e,t)}setup(e,t){this.type=e.type||"rich",this.title="title"in e?e.title:null,this.description="description"in e?e.description:null,this.url="url"in e?e.url:null,this.color="color"in e?n.resolveColor(e.color):null,this.timestamp="timestamp"in e?new Date(e.timestamp).getTime():null,this.fields=[],e.fields&&(this.fields=t?e.fields.map(n.cloneObject):this.constructor.normalizeFields(e.fields)),this.thumbnail=e.thumbnail?{url:e.thumbnail.url,proxyURL:e.thumbnail.proxyURL||e.thumbnail.proxy_url,height:e.thumbnail.height,width:e.thumbnail.width}:null,this.image=e.image?{url:e.image.url,proxyURL:e.image.proxyURL||e.image.proxy_url,height:e.image.height,width:e.image.width}:null,this.video=e.video?{url:e.video.url,proxyURL:e.video.proxyURL||e.video.proxy_url,height:e.video.height,width:e.video.width}:null,this.author=e.author?{name:e.author.name,url:e.author.url,iconURL:e.author.iconURL||e.author.icon_url,proxyIconURL:e.author.proxyIconURL||e.author.proxy_icon_url}:null,this.provider=e.provider?{name:e.provider.name,url:e.provider.name}:null,this.footer=e.footer?{text:e.footer.text,iconURL:e.footer.iconURL||e.footer.icon_url,proxyIconURL:e.footer.proxyIconURL||e.footer.proxy_icon_url}:null,this.files=e.files||[]}get createdAt(){return this.timestamp?new Date(this.timestamp):null}get hexColor(){return this.color?"#"+this.color.toString(16).padStart(6,"0"):null}get length(){return(this.title?this.title.length:0)+(this.description?this.description.length:0)+(this.fields.length>=1?this.fields.reduce(((e,t)=>e+t.name.length+t.value.length),0):0)+(this.footer?this.footer.text.length:0)}addField(e,t,i){return this.addFields({name:e,value:t,inline:i})}addFields(...e){return this.fields.push(...this.constructor.normalizeFields(e)),this}spliceFields(e,t,...i){return this.fields.splice(e,t,...this.constructor.normalizeFields(...i)),this}attachFiles(e){return this.files=this.files.concat(e),this}setAuthor(e,t,i){return this.author={name:n.resolveString(e),iconURL:t,url:i},this}setColor(e){return this.color=n.resolveColor(e),this}setDescription(e){return e=n.resolveString(e),this.description=e,this}setFooter(e,t){return e=n.resolveString(e),this.footer={text:e,iconURL:t},this}setImage(e){return this.image={url:e},this}setThumbnail(e){return this.thumbnail={url:e},this}setTimestamp(e=Date.now()){return e instanceof Date&&(e=e.getTime()),this.timestamp=e,this}setTitle(e){return e=n.resolveString(e),this.title=e,this}setURL(e){return this.url=e,this}toJSON(){return{title:this.title,type:"rich",description:this.description,url:this.url,timestamp:this.timestamp?new Date(this.timestamp):null,color:this.color,fields:this.fields,thumbnail:this.thumbnail,image:this.image,author:this.author?{name:this.author.name,url:this.author.url,icon_url:this.author.iconURL}:null,footer:this.footer?{text:this.footer.text,icon_url:this.footer.iconURL}:null}}static normalizeField(e,t,i=!1){if(!(e=n.resolveString(e)))throw new s("EMBED_FIELD_NAME");if(!(t=n.resolveString(t)))throw new s("EMBED_FIELD_VALUE");return{name:e,value:t,inline:i}}static normalizeFields(...e){return e.flat(2).map((e=>this.normalizeField(e&&e.name,e&&e.value,!(!e||"boolean"!=typeof e.inline)&&e.inline)))}}},function(e,t,i){(t=e.exports=i(67)).Stream=t,t.Readable=t,t.Writable=i(46),t.Duplex=i(21),t.Transform=i(71),t.PassThrough=i(132)},function(e,t,i){"use strict";(function(t,s,n){var r=i(31);function CorkedRequest(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function onCorkedFinish(e,t,i){var s=e.entry;e.entry=null;for(;s;){var n=s.callback;t.pendingcb--,n(i),s=s.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=Writable;var o,a=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?s:r.nextTick;Writable.WritableState=WritableState;var c=Object.create(i(26));c.inherits=i(23);var l={deprecate:i(131)},h=i(68),u=i(32).Buffer,d=n.Uint8Array||function(){};var f,p=i(69);function nop(){}function WritableState(e,t){o=o||i(21),e=e||{};var s=t instanceof o;this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var n=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var h=!1===e.decodeStrings;this.decodeStrings=!h,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function onwrite(e,t){var i=e._writableState,s=i.sync,n=i.writecb;if(function onwriteStateUpdate(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(i),t)!function onwriteError(e,t,i,s,n){--t.pendingcb,i?(r.nextTick(n,s),r.nextTick(finishMaybe,e,t),e._writableState.errorEmitted=!0,e.emit("error",s)):(n(s),e._writableState.errorEmitted=!0,e.emit("error",s),finishMaybe(e,t))}(e,i,s,t,n);else{var o=needFinish(i);o||i.corked||i.bufferProcessing||!i.bufferedRequest||clearBuffer(e,i),s?a(afterWrite,e,i,o,n):afterWrite(e,i,o,n)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new CorkedRequest(this)}function Writable(e){if(o=o||i(21),!(f.call(Writable,this)||this instanceof o))return new Writable(e);this._writableState=new WritableState(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),h.call(this)}function doWrite(e,t,i,s,n,r,o){t.writelen=s,t.writecb=o,t.writing=!0,t.sync=!0,i?e._writev(n,t.onwrite):e._write(n,r,t.onwrite),t.sync=!1}function afterWrite(e,t,i,s){i||function onwriteDrain(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,s(),finishMaybe(e,t)}function clearBuffer(e,t){t.bufferProcessing=!0;var i=t.bufferedRequest;if(e._writev&&i&&i.next){var s=t.bufferedRequestCount,n=new Array(s),r=t.corkedRequestsFree;r.entry=i;for(var o=0,a=!0;i;)n[o]=i,i.isBuf||(a=!1),i=i.next,o+=1;n.allBuffers=a,doWrite(e,t,!0,t.length,n,"",r.finish),t.pendingcb++,t.lastBufferedRequest=null,r.next?(t.corkedRequestsFree=r.next,r.next=null):t.corkedRequestsFree=new CorkedRequest(t),t.bufferedRequestCount=0}else{for(;i;){var c=i.chunk,l=i.encoding,h=i.callback;if(doWrite(e,t,!1,t.objectMode?1:c.length,c,l,h),i=i.next,t.bufferedRequestCount--,t.writing)break}null===i&&(t.lastBufferedRequest=null)}t.bufferedRequest=i,t.bufferProcessing=!1}function needFinish(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function callFinal(e,t){e._final((function(i){t.pendingcb--,i&&e.emit("error",i),t.prefinished=!0,e.emit("prefinish"),finishMaybe(e,t)}))}function finishMaybe(e,t){var i=needFinish(t);return i&&(!function prefinish(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,r.nextTick(callFinal,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),i}c.inherits(Writable,h),WritableState.prototype.getBuffer=function getBuffer(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:l.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(Writable,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===Writable&&(e&&e._writableState instanceof WritableState)}})):f=function(e){return e instanceof this},Writable.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},Writable.prototype.write=function(e,t,i){var s=this._writableState,n=!1,o=!s.objectMode&&function _isUint8Array(e){return u.isBuffer(e)||e instanceof d}(e);return o&&!u.isBuffer(e)&&(e=function _uint8ArrayToBuffer(e){return u.from(e)}(e)),"function"==typeof t&&(i=t,t=null),o?t="buffer":t||(t=s.defaultEncoding),"function"!=typeof i&&(i=nop),s.ended?function writeAfterEnd(e,t){var i=new Error("write after end");e.emit("error",i),r.nextTick(t,i)}(this,i):(o||function validChunk(e,t,i,s){var n=!0,o=!1;return null===i?o=new TypeError("May not write null values to stream"):"string"==typeof i||void 0===i||t.objectMode||(o=new TypeError("Invalid non-string/buffer chunk")),o&&(e.emit("error",o),r.nextTick(s,o),n=!1),n}(this,s,e,i))&&(s.pendingcb++,n=function writeOrBuffer(e,t,i,s,n,r){if(!i){var o=function decodeChunk(e,t,i){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=u.from(t,i));return t}(t,s,n);s!==o&&(i=!0,n="buffer",s=o)}var a=t.objectMode?1:s.length;t.length+=a;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Writable.prototype._write=function(e,t,i){i(new Error("_write() is not implemented"))},Writable.prototype._writev=null,Writable.prototype.end=function(e,t,i){var s=this._writableState;"function"==typeof e?(i=e,e=null,t=null):"function"==typeof t&&(i=t,t=null),null!=e&&this.write(e,t),s.corked&&(s.corked=1,this.uncork()),s.ending||s.finished||function endWritable(e,t,i){t.ending=!0,finishMaybe(e,t),i&&(t.finished?r.nextTick(i):e.once("finish",i));t.ended=!0,e.writable=!1}(this,s,i)},Object.defineProperty(Writable.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),Writable.prototype.destroy=p.destroy,Writable.prototype._undestroy=p.undestroy,Writable.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,i(15),i(38).setImmediate,i(22))},function(e,t,i){"use strict";const s=i(12);class MessageFlags extends s{}MessageFlags.FLAGS={CROSSPOSTED:1,IS_CROSSPOST:2,SUPPRESS_EMBEDS:4,SOURCE_MESSAGE_DELETED:8,URGENT:16},e.exports=MessageFlags},function(e,t,i){"use strict";const s=i(37),n=i(13);class WebhookClient extends s{constructor(e,t,i){super(i),Object.defineProperty(this,"client",{value:this}),this.id=e,Object.defineProperty(this,"token",{value:t,writable:!0,configurable:!0})}}n.applyToClass(WebhookClient),e.exports=WebhookClient},function(e,t,i){"use strict";const s=i(16),n=i(3),r=i(4);class Collector extends s{constructor(e,t,i={}){super(),Object.defineProperty(this,"client",{value:e}),this.filter=t,this.options=i,this.collected=new n,this.ended=!1,this._timeout=null,this._idletimeout=null,this.handleCollect=this.handleCollect.bind(this),this.handleDispose=this.handleDispose.bind(this),i.time&&(this._timeout=this.client.setTimeout((()=>this.stop("time")),i.time)),i.idle&&(this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),i.idle))}async handleCollect(...e){const t=this.collect(...e);t&&await this.filter(...e,this.collected)&&(this.collected.set(t,e[0]),this.emit("collect",...e),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),this.options.idle))),this.checkEnd()}handleDispose(...e){if(!this.options.dispose)return;const t=this.dispose(...e);t&&this.filter(...e)&&this.collected.has(t)&&(this.collected.delete(t),this.emit("dispose",...e),this.checkEnd())}get next(){return new Promise(((e,t)=>{if(this.ended)return void t(this.collected);const cleanup=()=>{this.removeListener("collect",onCollect),this.removeListener("end",onEnd)},onCollect=t=>{cleanup(),e(t)},onEnd=()=>{cleanup(),t(this.collected)};this.on("collect",onCollect),this.on("end",onEnd)}))}stop(e="user"){this.ended||(this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=null),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=null),this.ended=!0,this.emit("end",this.collected,e))}resetTimer({time:e,idle:t}={}){this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=this.client.setTimeout((()=>this.stop("time")),e||this.options.time)),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),t||this.options.idle))}checkEnd(){const e=this.endReason();e&&this.stop(e)}async*[Symbol.asyncIterator](){const e=[],onCollect=t=>e.push(t);this.on("collect",onCollect);try{for(;e.length||!this.ended;)e.length?yield e.shift():await new Promise((e=>{const tick=()=>(this.removeListener("collect",tick),this.removeListener("end",tick),e());this.on("collect",tick),this.on("end",tick)}))}finally{this.removeListener("collect",onCollect)}}toJSON(){return r.flatten(this)}collect(){}dispose(){}endReason(){}}e.exports=Collector},function(e,t,i){"use strict";const s=i(74),n=i(51);e.exports=class ClientApplication extends n{_patch(e){super._patch(e),this.cover=e.cover_image||null,this.rpcOrigins=e.rpc_origins||[],this.botRequireCodeGrant=void 0!==e.bot_require_code_grant?e.bot_require_code_grant:null,this.botPublic=void 0!==e.bot_public?e.bot_public:null,this.owner=e.team?new s(this.client,e.team):e.owner?this.client.users.add(e.owner):null}}},function(e,t,i){"use strict";const{ClientApplicationAssetTypes:s,Endpoints:n}=i(0),r=i(6),o=i(5),a=Object.keys(s);e.exports=class Application extends o{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.description=e.description,this.icon=e.icon}get createdTimestamp(){return r.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.AppIcon(this.id,this.icon,{format:e,size:t}):null}coverImage({format:e,size:t}={}){return this.cover?n.CDN(this.client.options.http.cdn).AppIcon(this.id,this.cover,{format:e,size:t}):null}fetchAssets(){return this.client.api.oauth2.applications(this.id).assets.get().then((e=>e.map((e=>({id:e.id,name:e.name,type:a[e.type-1]})))))}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(25),n=i(53),r=i(79),o=i(4);e.exports=class MessageReaction{constructor(e,t,i){Object.defineProperty(this,"client",{value:e}),this.message=i,this.users=new r(e,void 0,this),this._emoji=new n(this,t.emoji),this._patch(t)}_patch(e){null==this.count&&(this.count=e.count),this.me=e.me}async remove(){return await this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions(this._emoji.identifier).delete(),this}get emoji(){if(this._emoji instanceof s)return this._emoji;if(this._emoji.id){const e=this.message.client.emojis.cache;if(e.has(this._emoji.id)){const t=e.get(this._emoji.id);return this._emoji=t,t}}return this._emoji}get partial(){return null===this.count}async fetch(){const e=(await this.message.fetch()).reactions.cache.get(this.emoji.id||this.emoji.name);return this._patch(e||{count:0}),this}toJSON(){return o.flatten(this,{emoji:"emojiID",message:"messageID"})}_add(e){this.partial||(this.users.cache.set(e.id,e),this.me&&e.id===this.message.client.user.id&&0!==this.count||this.count++,this.me||(this.me=e.id===this.message.client.user.id))}_remove(e){this.partial||(this.users.cache.delete(e.id),this.me&&e.id===this.message.client.user.id||this.count--,e.id===this.message.client.user.id&&(this.me=!1),this.count<=0&&0===this.users.cache.size&&this.message.reactions.cache.delete(this.emoji.id||this.emoji.name))}}},function(e,t,i){"use strict";const s=i(29),n=i(4);e.exports=class ReactionEmoji extends s{constructor(e,t){super(e.message.client,t),this.reaction=e}toJSON(){return n.flatten(this,{identifier:!0})}valueOf(){return this.id}}},function(e,t,i){"use strict";(function(t){const{deprecate:s}=i(85),n=i(5),r=i(86),o=i(56),a=i(57),c=i(55),l=i(19),h=i(58),u=i(13),{Error:d,TypeError:f}=i(2),p=i(87),m=i(59),g=i(88),E=i(89),_=i(91),y=i(142),b=i(3),{browser:v,ChannelTypes:w,DefaultMessageNotifications:S,PartialTypes:I,VerificationLevels:A,ExplicitContentFilterLevels:T}=i(0),D=i(9),R=i(6),N=i(92),L=i(4);class Guild extends n{constructor(e,t){super(e),this.members=new g(this),this.channels=new p(this),this.roles=new _(this),this.presences=new E(this.client),this.voiceStates=new y(this),this.deleted=!1,t&&(t.unavailable?(this.available=!1,this.id=t.id):(this._patch(t),t.channels||(this.available=!1)),this.shardID=t.shardID)}get shard(){return this.client.ws.shards.get(this.shardID)}_patch(e){if(this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.discoverySplash=e.discovery_splash,this.region=e.region,this.memberCount=e.member_count||this.memberCount,this.large=Boolean("large"in e?e.large:this.large),this.features=e.features,this.applicationID=e.application_id,this.afkTimeout=e.afk_timeout,this.afkChannelID=e.afk_channel_id,this.systemChannelID=e.system_channel_id,this.embedEnabled=e.embed_enabled,this.premiumTier=e.premium_tier,void 0!==e.premium_subscription_count&&(this.premiumSubscriptionCount=e.premium_subscription_count),void 0!==e.widget_enabled&&(this.widgetEnabled=e.widget_enabled),void 0!==e.widget_channel_id&&(this.widgetChannelID=e.widget_channel_id),void 0!==e.embed_channel_id&&(this.embedChannelID=e.embed_channel_id),this.verificationLevel=A[e.verification_level],this.explicitContentFilter=T[e.explicit_content_filter],this.mfaLevel=e.mfa_level,this.joinedTimestamp=e.joined_at?new Date(e.joined_at).getTime():this.joinedTimestamp,this.defaultMessageNotifications=S[e.default_message_notifications]||e.default_message_notifications,this.systemChannelFlags=new N(e.system_channel_flags).freeze(),void 0!==e.max_members?this.maximumMembers=e.max_members:void 0===this.maximumMembers&&(this.maximumMembers=null),void 0!==e.max_presences?this.maximumPresences=e.max_presences||25e3:void 0===this.maximumPresences&&(this.maximumPresences=null),void 0!==e.approximate_member_count?this.approximateMemberCount=e.approximate_member_count:void 0===this.approximateMemberCount&&(this.approximateMemberCount=null),void 0!==e.approximate_presence_count?this.approximatePresenceCount=e.approximate_presence_count:void 0===this.approximatePresenceCount&&(this.approximatePresenceCount=null),this.vanityURLCode=e.vanity_url_code,this.vanityURLUses=null,this.description=e.description,this.banner=e.banner,this.id=e.id,this.available=!e.unavailable,this.features=e.features||this.features||[],this.rulesChannelID=e.rules_channel_id,this.publicUpdatesChannelID=e.public_updates_channel_id,this.preferredLocale=e.preferred_locale,e.channels){this.channels.cache.clear();for(const t of e.channels)this.client.channels.add(t,this)}if(e.roles){this.roles.cache.clear();for(const t of e.roles)this.roles.add(t)}if(e.members){this.members.cache.clear();for(const t of e.members)this.members.add(t)}if(e.owner_id&&(this.ownerID=e.owner_id),e.presences)for(const t of e.presences)this.presences.add(Object.assign(t,{guild:this}));if(e.voice_states){this.voiceStates.cache.clear();for(const t of e.voice_states)this.voiceStates.add(t)}if(this.emojis)e.emojis&&this.client.actions.GuildEmojisUpdate.handle({guild_id:this.id,emojis:e.emojis});else if(this.emojis=new m(this),e.emojis)for(const t of e.emojis)this.emojis.add(t)}bannerURL({format:e,size:t}={}){return this.banner?this.client.rest.cdn.Banner(this.id,this.banner,e,t):null}get createdTimestamp(){return R.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get joinedAt(){return new Date(this.joinedTimestamp)}get partnered(){return this.features.includes("PARTNERED")}get verified(){return this.features.includes("VERIFIED")}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}get nameAcronym(){return this.name.replace(/'s /g," ").replace(/\w+/g,(e=>e[0])).replace(/\s/g,"")}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}discoverySplashURL({format:e,size:t}={}){return this.discoverySplash?this.client.rest.cdn.DiscoverySplash(this.id,this.discoverySplash,e,t):null}get owner(){return this.members.cache.get(this.ownerID)||(this.client.options.partials.includes(I.GUILD_MEMBER)?this.members.add({user:{id:this.ownerID}},!0):null)}get afkChannel(){return this.client.channels.cache.get(this.afkChannelID)||null}get systemChannel(){return this.client.channels.cache.get(this.systemChannelID)||null}get widgetChannel(){return this.client.channels.cache.get(this.widgetChannelID)||null}get embedChannel(){return this.client.channels.cache.get(this.embedChannelID)||null}get rulesChannel(){return this.client.channels.cache.get(this.rulesChannelID)||null}get publicUpdatesChannel(){return this.client.channels.cache.get(this.publicUpdatesChannelID)||null}get me(){return this.members.cache.get(this.client.user.id)||(this.client.options.partials.includes(I.GUILD_MEMBER)?this.members.add({user:{id:this.client.user.id}},!0):null)}get voice(){return this.voiceStates.cache.get(this.client.user.id)}member(e){return this.members.resolve(e)}fetch(){return this.client.api.guilds(this.id).get({query:{with_counts:!0}}).then((e=>(this._patch(e),this)))}fetchBan(e){const t=this.client.users.resolveID(e);if(!t)throw new d("FETCH_BAN_RESOLVE_ID");return this.client.api.guilds(this.id).bans(t).get().then((e=>({reason:e.reason,user:this.client.users.add(e.user)})))}fetchBans(){return this.client.api.guilds(this.id).bans.get().then((e=>e.reduce(((e,t)=>(e.set(t.user.id,{reason:t.reason,user:this.client.users.add(t.user)}),e)),new b)))}fetchIntegrations({includeApplications:e=!1}={}){return this.client.api.guilds(this.id).integrations.get({query:{include_applications:e}}).then((e=>e.reduce(((e,t)=>e.set(t.id,new c(this.client,t,this))),new b)))}fetchTemplates(){return this.client.api.guilds(this.id).templates.get().then((e=>e.reduce(((e,t)=>e.set(t.code,new a(this.client,t))),new b)))}createIntegration(e,t){return this.client.api.guilds(this.id).integrations.post({data:e,reason:t}).then((()=>this))}createTemplate(e,t){return this.client.api.guilds(this.id).templates.post({data:{name:e,description:t}}).then((e=>new a(this.client,e)))}fetchInvites(){return this.client.api.guilds(this.id).invites.get().then((e=>{const t=new b;for(const i of e){const e=new l(this.client,i);t.set(e.code,e)}return t}))}fetchPreview(){return this.client.api.guilds(this.id).preview.get().then((e=>new o(this.client,e)))}fetchVanityCode(){return this.fetchVanityData().then((e=>e.code))}async fetchVanityData(){if(!this.features.includes("VANITY_URL"))throw new d("VANITY_URL");const e=await this.client.api.guilds(this.id,"vanity-url").get();return this.vanityURLUses=e.uses,e}fetchWebhooks(){return this.client.api.guilds(this.id).webhooks.get().then((e=>{const t=new b;for(const i of e)t.set(i.id,new u(this.client,i));return t}))}fetchVoiceRegions(){return this.client.api.guilds(this.id).regions.get().then((e=>{const t=new b;for(const i of e)t.set(i.id,new h(i));return t}))}fetchEmbed(){return this.fetchWidget()}async fetchWidget(){const e=await this.client.api.guilds(this.id).widget.get();return this.widgetEnabled=this.embedEnabled=e.enabled,this.widgetChannelID=this.embedChannelID=e.channel_id,{enabled:e.enabled,channel:e.channel_id?this.channels.cache.get(e.channel_id):null}}fetchAuditLogs(e={}){return e.before&&e.before instanceof r.Entry&&(e.before=e.before.id),"string"==typeof e.type&&(e.type=r.Actions[e.type]),this.client.api.guilds(this.id)["audit-logs"].get({query:{before:e.before,limit:e.limit,user_id:this.client.users.resolveID(e.user),action_type:e.type}}).then((e=>r.build(this,e)))}async addMember(e,i){if(!(e=this.client.users.resolveID(e)))throw new f("INVALID_TYPE","user","UserResolvable");if(this.members.cache.has(e))return this.members.cache.get(e);if(i.access_token=i.accessToken,i.roles){const e=[];for(let t of i.roles instanceof b?i.roles.values():i.roles){if(t=this.roles.resolve(t),!t)throw new f("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0);e.push(t.id)}i.roles=e}const s=await this.client.api.guilds(this.id).members(e).put({data:i});return s instanceof(v?ArrayBuffer:t)?this.members.fetch(e):this.members.add(s)}edit(e,t){const i={};return e.name&&(i.name=e.name),e.region&&(i.region=e.region),void 0!==e.verificationLevel&&(i.verification_level="number"==typeof e.verificationLevel?Number(e.verificationLevel):A.indexOf(e.verificationLevel)),void 0!==e.afkChannel&&(i.afk_channel_id=this.client.channels.resolveID(e.afkChannel)),void 0!==e.systemChannel&&(i.system_channel_id=this.client.channels.resolveID(e.systemChannel)),e.afkTimeout&&(i.afk_timeout=Number(e.afkTimeout)),void 0!==e.icon&&(i.icon=e.icon),e.owner&&(i.owner_id=this.client.users.resolveID(e.owner)),e.splash&&(i.splash=e.splash),e.discoverySplash&&(i.discovery_splash=e.discoverySplash),e.banner&&(i.banner=e.banner),void 0!==e.explicitContentFilter&&(i.explicit_content_filter="number"==typeof e.explicitContentFilter?e.explicitContentFilter:T.indexOf(e.explicitContentFilter)),void 0!==e.defaultMessageNotifications&&(i.default_message_notifications="string"==typeof e.defaultMessageNotifications?S.indexOf(e.defaultMessageNotifications):e.defaultMessageNotifications),void 0!==e.systemChannelFlags&&(i.system_channel_flags=N.resolve(e.systemChannelFlags)),void 0!==e.rulesChannel&&(i.rules_channel_id=this.client.channels.resolveID(e.rulesChannel)),void 0!==e.publicUpdatesChannel&&(i.public_updates_channel_id=this.client.channels.resolveID(e.publicUpdatesChannel)),e.preferredLocale&&(i.preferred_locale=e.preferredLocale),this.client.api.guilds(this.id).patch({data:i,reason:t}).then((e=>this.client.actions.GuildUpdate.handle(e).updated))}setExplicitContentFilter(e,t){return this.edit({explicitContentFilter:e},t)}setDefaultMessageNotifications(e,t){return this.edit({defaultMessageNotifications:e},t)}setSystemChannelFlags(e,t){return this.edit({systemChannelFlags:e},t)}setName(e,t){return this.edit({name:e},t)}setRegion(e,t){return this.edit({region:e},t)}setVerificationLevel(e,t){return this.edit({verificationLevel:e},t)}setAFKChannel(e,t){return this.edit({afkChannel:e},t)}setSystemChannel(e,t){return this.edit({systemChannel:e},t)}setAFKTimeout(e,t){return this.edit({afkTimeout:e},t)}async setIcon(e,t){return this.edit({icon:await D.resolveImage(e),reason:t})}setOwner(e,t){return this.edit({owner:e},t)}async setSplash(e,t){return this.edit({splash:await D.resolveImage(e),reason:t})}async setDiscoverySplash(e,t){return this.edit({discoverySplash:await D.resolveImage(e),reason:t})}async setBanner(e,t){return this.edit({banner:await D.resolveImage(e),reason:t})}setRulesChannel(e,t){return this.edit({rulesChannel:e},t)}setPublicUpdatesChannel(e,t){return this.edit({publicUpdatesChannel:e},t)}setPreferredLocale(e,t){return this.edit({preferredLocale:e},t)}setChannelPositions(e){const t=e.map((e=>({id:this.client.channels.resolveID(e.channel),position:e.position})));return this.client.api.guilds(this.id).channels.patch({data:t}).then((()=>this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.id,channels:t}).guild))}setRolePositions(e){return e=e.map((e=>({id:this.roles.resolveID(e.role),position:e.position}))),this.client.api.guilds(this.id).roles.patch({data:e}).then((()=>this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.id,roles:e}).guild))}setEmbed(e,t){return this.setWidget(e,t)}setWidget(e,t){return this.client.api.guilds(this.id).widget.patch({data:{enabled:e.enabled,channel_id:this.channels.resolveID(e.channel)},reason:t}).then((()=>this))}leave(){return this.ownerID===this.client.user.id?Promise.reject(new d("GUILD_OWNED")):this.client.api.users("@me").guilds(this.id).delete().then((()=>this.client.actions.GuildDelete.handle({id:this.id}).guild))}delete(){return this.client.api.guilds(this.id).delete().then((()=>this.client.actions.GuildDelete.handle({id:this.id}).guild))}equals(e){let t=e&&e instanceof this.constructor&&this.id===e.id&&this.available===e.available&&this.splash===e.splash&&this.discoverySplash===e.discoverySplash&&this.region===e.region&&this.name===e.name&&this.memberCount===e.memberCount&&this.large===e.large&&this.icon===e.icon&&this.ownerID===e.ownerID&&this.verificationLevel===e.verificationLevel&&this.embedEnabled===e.embedEnabled&&(this.features===e.features||this.features.length===e.features.length&&this.features.every(((t,i)=>t===e.features[i])));return t&&(this.embedChannel?e.embedChannel&&this.embedChannel.id===e.embedChannel.id||(t=!1):e.embedChannel&&(t=!1)),t}toString(){return this.name}toJSON(){const e=super.toJSON({available:!1,createdTimestamp:!0,nameAcronym:!0,presences:!1,voiceStates:!1});return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e.discoverySplashURL=this.discoverySplashURL(),e.bannerURL=this.bannerURL(),e}_sortedRoles(){return L.discordSort(this.roles.cache)}_sortedChannels(e){const t=e.type===w.CATEGORY;return L.discordSort(this.channels.cache.filter((i=>(["text","news","store"].includes(e.type)?["text","news","store"].includes(i.type):i.type===e.type)&&(t||i.parent===e.parent))))}}Guild.prototype.setEmbed=s(Guild.prototype.setEmbed,"Guild#setEmbed: Use setWidget instead"),Guild.prototype.fetchEmbed=s(Guild.prototype.fetchEmbed,"Guild#fetchEmbed: Use fetchWidget instead"),Guild.prototype.fetchVanityCode=s(Guild.prototype.fetchVanityCode,"Guild#fetchVanityCode: Use fetchVanityData() instead"),e.exports=Guild}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(5),n=i(140);e.exports=class Integration extends s{constructor(e,t,i){super(e),this.guild=i,this.id=t.id,this.name=t.name,this.type=t.type,this.enabled=t.enabled,this.syncing=t.syncing,this.role=this.guild.roles.cache.get(t.role_id),t.user?this.user=this.client.users.add(t.user):this.user=null,this.account=t.account,this.syncedAt=t.synced_at,this._patch(t)}_patch(e){this.expireBehavior=e.expire_behavior,this.expireGracePeriod=e.expire_grace_period,"application"in e?this.application?this.application._patch(e.application):this.application=new n(this.client,e.application):this.application||(this.application=null)}sync(){return this.syncing=!0,this.client.api.guilds(this.guild.id).integrations(this.id).post().then((()=>(this.syncing=!1,this.syncedAt=Date.now(),this)))}edit(e,t){return"expireBehavior"in e&&(e.expire_behavior=e.expireBehavior,e.expireBehavior=null),"expireGracePeriod"in e&&(e.expire_grace_period=e.expireGracePeriod,e.expireGracePeriod=null),this.client.api.guilds(this.guild.id).integrations(this.id).patch({data:e,reason:t}).then((()=>(this._patch(e),this)))}delete(e){return this.client.api.guilds(this.guild.id).integrations(this.id).delete({reason:e}).then((()=>this))}toJSON(){return super.toJSON({role:"roleID",guild:"guildID",user:"userID"})}}},function(e,t,i){"use strict";const s=i(5),n=i(141),r=i(3);e.exports=class GuildPreview extends s{constructor(e,t){super(e),t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.discoverySplash=e.discovery_splash,this.features=e.features,this.approximateMemberCount=e.approximate_member_count,this.approximatePresenceCount=e.approximate_presence_count,this.description=e.description||null,this.emojis?this.emojis.clear():this.emojis=new r;for(const t of e.emojis)this.emojis.set(t.id,new n(this.client,t,this))}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}discoverySplashURL({format:e,size:t}={}){return this.discoverySplash?this.client.rest.cdn.DiscoverySplash(this.id,this.discoverySplash,e,t):null}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}fetch(){return this.client.api.guilds(this.id).preview.get().then((e=>(this._patch(e),this)))}toString(){return this.name}toJSON(){const e=super.toJSON();return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e}}},function(e,t,i){"use strict";const s=i(5),{Events:n}=i(0),r=i(9);e.exports=class GuildTemplate extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){return this.code=e.code,this.name=e.name,this.description=e.description,this.usageCount=e.usage_count,this.creatorID=e.creator_id,this.creator=this.client.users.add(e.creator),this.createdAt=new Date(e.created_at),this.updatedAt=new Date(e.updated_at),this.guildID=e.source_guild_id,this.serializedGuild=e.serialized_source_guild,this.unSynced="is_dirty"in e?Boolean(e.is_dirty):null,this}async createGuild(e,t){const{client:i}=this,s=await i.api.guilds.templates(this.code).post({data:{name:e,icon:await r.resolveImage(t)}});return new Promise((e=>{const t=i.guilds.cache.get(s.id);if(t)return e(t);const resolveGuild=t=>{i.off(n.GUILD_CREATE,handleGuild),i.decrementMaxListeners(),e(t)},handleGuild=e=>{e.id===s.id&&(i.clearTimeout(r),resolveGuild(e))};i.incrementMaxListeners(),i.on(n.GUILD_CREATE,handleGuild);const r=i.setTimeout((()=>resolveGuild(i.guilds.add(s))),1e4)}))}edit({name:e,description:t}={}){return this.client.api.guilds(this.guildID).templates(this.code).patch({data:{name:e,description:t}}).then((e=>this._patch(e)))}delete(){return this.client.api.guilds(this.guildID).templates(this.code).delete().then((()=>this))}sync(){return this.client.api.guilds(this.guildID).templates(this.code).put().then((e=>this._patch(e)))}get createdTimestamp(){return this.createdAt.getTime()}get updatedTimestamp(){return this.updatedAt.getTime()}get guild(){return this.client.guilds.cache.get(this.guildID)||null}get url(){return`${this.client.options.http.template}/${this.code}`}toString(){return this.code}}},function(e,t,i){"use strict";const s=i(4);e.exports=class VoiceRegion{constructor(e){this.id=e.id,this.name=e.name,this.vip=e.vip,this.deprecated=e.deprecated,this.optimal=e.optimal,this.custom=e.custom}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const s=i(7),{TypeError:n}=i(2),r=i(25),o=i(53),a=i(3),c=i(9),{parseEmoji:l}=i(4);e.exports=class GuildEmojiManager extends s{constructor(e,t){super(e.client,t,r),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async create(e,t,{roles:i,reason:s}={}){if(!(e=await c.resolveImage(e)))throw new n("REQ_RESOURCE_TYPE");const r={image:e,name:t};if(i){r.roles=[];for(let e of i instanceof a?i.values():i){if(e=this.guild.roles.resolve(e),!e)return Promise.reject(new n("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0));r.roles.push(e.id)}}return this.client.api.guilds(this.guild.id).emojis.post({data:r,reason:s}).then((e=>this.client.actions.GuildEmojiCreate.handle(this.guild,e).emoji))}resolve(e){return e instanceof o?super.resolve(e.id):super.resolve(e)}resolveID(e){return e instanceof o?e.id:super.resolveID(e)}resolveIdentifier(e){const t=this.resolve(e);if(t)return t.identifier;if(e instanceof o)return e.identifier;if("string"==typeof e){const t=l(e);return t&&t.name.length&&(e=`${t.animated?"a:":""}${t.name}${t.id?":"+t.id:""}`),e.includes("%")?e:encodeURIComponent(e)}return null}}},function(e,t){var i={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==i.call(e)}},function(e,t){e.exports={version:"12.5.3",homepage:"https://github.com/discordjs/discord.js#readme"}},function(e,t,i){"use strict";const s=Symbol("code"),n=new Map;function makeDiscordjsError(e){return class DiscordjsError extends e{constructor(e,...t){super(function message(e,t){if("string"!=typeof e)throw new Error("Error message key must be a string");const i=n.get(e);if(!i)throw new Error(`An invalid error message key was used: ${e}.`);return"function"==typeof i?i(...t):void 0===t||0===t.length?i:(t.unshift(i),String(...t))}(e,t)),this[s]=e,Error.captureStackTrace&&Error.captureStackTrace(this,DiscordjsError)}get name(){return`${super.name} [${this[s]}]`}get code(){return this[s]}}}e.exports={register:function register(e,t){n.set(e,"function"==typeof t?t:String(t))},Error:makeDiscordjsError(Error),TypeError:makeDiscordjsError(TypeError),RangeError:makeDiscordjsError(RangeError)}},function(e,t,i){(function(e,t){!function(e,i){"use strict";if(!e.setImmediate){var s,n=1,r={},o=!1,a=e.document,c=Object.getPrototypeOf&&Object.getPrototypeOf(e);c=c&&c.setTimeout?c:e,"[object process]"==={}.toString.call(e.process)?function installNextTickImplementation(){s=function(e){t.nextTick((function(){runIfPresent(e)}))}}():!function canUsePostMessage(){if(e.postMessage&&!e.importScripts){var t=!0,i=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=i,t}}()?e.MessageChannel?function installMessageChannelImplementation(){var e=new MessageChannel;e.port1.onmessage=function(e){runIfPresent(e.data)},s=function(t){e.port2.postMessage(t)}}():a&&"onreadystatechange"in a.createElement("script")?function installReadyStateChangeImplementation(){var e=a.documentElement;s=function(t){var i=a.createElement("script");i.onreadystatechange=function(){runIfPresent(t),i.onreadystatechange=null,e.removeChild(i),i=null},e.appendChild(i)}}():function installSetTimeoutImplementation(){s=function(e){setTimeout(runIfPresent,0,e)}}():function installPostMessageImplementation(){var t="setImmediate$"+Math.random()+"$",onGlobalMessage=function(i){i.source===e&&"string"==typeof i.data&&0===i.data.indexOf(t)&&runIfPresent(+i.data.slice(t.length))};e.addEventListener?e.addEventListener("message",onGlobalMessage,!1):e.attachEvent("onmessage",onGlobalMessage),s=function(i){e.postMessage(t+i,"*")}}(),c.setImmediate=function setImmediate(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),i=0;ie.message)).join(" ")}`):n.code||n.message?i.push(`${n.code?n.code+": ":""}${n.message}`.trim()):"string"==typeof n?i.push(n):i=i.concat(this.flattenErrors(n,e))}return i}}e.exports=DiscordAPIError},function(e,t,i){"use strict";class HTTPError extends Error{constructor(e,t,i,s,n){super(e),this.name=t,this.code=i||500,this.method=s,this.path=n}}e.exports=HTTPError},function(e,t,i){"use strict";const{TypeError:s}=i(2),n=i(3);e.exports=class GuildEmojiRoleManager{constructor(e){this.emoji=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){return this.guild.roles.cache.filter((e=>this.emoji._roles.includes(e.id)))}get cache(){return this._roles}add(e){if(e instanceof n)return this.add(e.keyArray());if(!Array.isArray(e))return this.add([e]);if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=[...new Set(e.concat(...this._roles.values()))];return this.set(t)}remove(e){if(e instanceof n)return this.remove(e.keyArray());if(!Array.isArray(e))return this.remove([e]);if((e=e.map((e=>this.guild.roles.resolveID(e)))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=this._roles.keyArray().filter((t=>!e.includes(t)));return this.set(t)}set(e){return this.emoji.edit({roles:e})}clone(){const e=new this.constructor(this.emoji);return e._patch(this._roles.keyArray().slice()),e}_patch(e){this.emoji._roles=e}}},function(e,t,i){"use strict";(function(t,s){var n=i(31);e.exports=Readable;var r,o=i(60);Readable.ReadableState=ReadableState;i(16).EventEmitter;var EElistenerCount=function(e,t){return e.listeners(t).length},a=i(68),c=i(32).Buffer,l=t.Uint8Array||function(){};var h=Object.create(i(26));h.inherits=i(23);var u=i(128),d=void 0;d=u&&u.debuglog?u.debuglog("stream"):function(){};var f,p=i(129),m=i(69);h.inherits(Readable,a);var g=["error","close","destroy","pause","resume"];function ReadableState(e,t){e=e||{};var s=t instanceof(r=r||i(21));this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var n=e.highWaterMark,o=e.readableHighWaterMark,a=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(o||0===o)?o:a,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new p,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(f||(f=i(70).StringDecoder),this.decoder=new f(e.encoding),this.encoding=e.encoding)}function Readable(e){if(r=r||i(21),!(this instanceof Readable))return new Readable(e);this._readableState=new ReadableState(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),a.call(this)}function readableAddChunk(e,t,i,s,n){var r,o=e._readableState;null===t?(o.reading=!1,function onEofChunk(e,t){if(t.ended)return;if(t.decoder){var i=t.decoder.end();i&&i.length&&(t.buffer.push(i),t.length+=t.objectMode?1:i.length)}t.ended=!0,emitReadable(e)}(e,o)):(n||(r=function chunkInvalid(e,t){var i;(function _isUint8Array(e){return c.isBuffer(e)||e instanceof l})(t)||"string"==typeof t||void 0===t||e.objectMode||(i=new TypeError("Invalid non-string/buffer chunk"));return i}(o,t)),r?e.emit("error",r):o.objectMode||t&&t.length>0?("string"==typeof t||o.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function _uint8ArrayToBuffer(e){return c.from(e)}(t)),s?o.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):addChunk(e,o,t,!0):o.ended?e.emit("error",new Error("stream.push() after EOF")):(o.reading=!1,o.decoder&&!i?(t=o.decoder.write(t),o.objectMode||0!==t.length?addChunk(e,o,t,!1):maybeReadMore(e,o)):addChunk(e,o,t,!1))):s||(o.reading=!1));return function needMoreData(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function computeNewHighWaterMark(e){return e>=E?e=E:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function emitReadable(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(d("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?n.nextTick(emitReadable_,e):emitReadable_(e))}function emitReadable_(e){d("emit readable"),e.emit("readable"),flow(e)}function maybeReadMore(e,t){t.readingMore||(t.readingMore=!0,n.nextTick(maybeReadMore_,e,t))}function maybeReadMore_(e,t){for(var i=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(i=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):i=function fromListPartial(e,t,i){var s;er.length?r.length:e;if(o===r.length?n+=r:n+=r.slice(0,e),0===(e-=o)){o===r.length?(++s,i.next?t.head=i.next:t.head=t.tail=null):(t.head=i,i.data=r.slice(o));break}++s}return t.length-=s,n}(e,t):function copyFromBuffer(e,t){var i=c.allocUnsafe(e),s=t.head,n=1;s.data.copy(i),e-=s.data.length;for(;s=s.next;){var r=s.data,o=e>r.length?r.length:e;if(r.copy(i,i.length-e,0,o),0===(e-=o)){o===r.length?(++n,s.next?t.head=s.next:t.head=t.tail=null):(t.head=s,s.data=r.slice(o));break}++n}return t.length-=n,i}(e,t);return s}(e,t.buffer,t.decoder),i);var i}function endReadable(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,n.nextTick(endReadableNT,t,e))}function endReadableNT(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function indexOf(e,t){for(var i=0,s=e.length;i=t.highWaterMark||t.ended))return d("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?endReadable(this):emitReadable(this),null;if(0===(e=howMuchToRead(e,t))&&t.ended)return 0===t.length&&endReadable(this),null;var s,n=t.needReadable;return d("need readable",n),(0===t.length||t.length-e0?fromList(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),i!==e&&t.ended&&endReadable(this)),null!==s&&this.emit("data",s),s},Readable.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},Readable.prototype.pipe=function(e,t){var i=this,r=this._readableState;switch(r.pipesCount){case 0:r.pipes=e;break;case 1:r.pipes=[r.pipes,e];break;default:r.pipes.push(e)}r.pipesCount+=1,d("pipe count=%d opts=%j",r.pipesCount,t);var a=(!t||!1!==t.end)&&e!==s.stdout&&e!==s.stderr?onend:unpipe;function onunpipe(t,s){d("onunpipe"),t===i&&s&&!1===s.hasUnpiped&&(s.hasUnpiped=!0,function cleanup(){d("cleanup"),e.removeListener("close",onclose),e.removeListener("finish",onfinish),e.removeListener("drain",c),e.removeListener("error",onerror),e.removeListener("unpipe",onunpipe),i.removeListener("end",onend),i.removeListener("end",unpipe),i.removeListener("data",ondata),l=!0,!r.awaitDrain||e._writableState&&!e._writableState.needDrain||c()}())}function onend(){d("onend"),e.end()}r.endEmitted?n.nextTick(a):i.once("end",a),e.on("unpipe",onunpipe);var c=function pipeOnDrain(e){return function(){var t=e._readableState;d("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&EElistenerCount(e,"data")&&(t.flowing=!0,flow(e))}}(i);e.on("drain",c);var l=!1;var h=!1;function ondata(t){d("ondata"),h=!1,!1!==e.write(t)||h||((1===r.pipesCount&&r.pipes===e||r.pipesCount>1&&-1!==indexOf(r.pipes,e))&&!l&&(d("false write response, pause",i._readableState.awaitDrain),i._readableState.awaitDrain++,h=!0),i.pause())}function onerror(t){d("onerror",t),unpipe(),e.removeListener("error",onerror),0===EElistenerCount(e,"error")&&e.emit("error",t)}function onclose(){e.removeListener("finish",onfinish),unpipe()}function onfinish(){d("onfinish"),e.removeListener("close",onclose),unpipe()}function unpipe(){d("unpipe"),i.unpipe(e)}return i.on("data",ondata),function prependListener(e,t,i){if("function"==typeof e.prependListener)return e.prependListener(t,i);e._events&&e._events[t]?o(e._events[t])?e._events[t].unshift(i):e._events[t]=[i,e._events[t]]:e.on(t,i)}(e,"error",onerror),e.once("close",onclose),e.once("finish",onfinish),e.emit("pipe",i),r.flowing||(d("pipe resume"),i.resume()),e},Readable.prototype.unpipe=function(e){var t=this._readableState,i={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,i)),this;if(!e){var s=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var r=0;r>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function utf8FillLast(e){var t=this.lastTotal-this.lastNeed,i=function utf8CheckExtraBytes(e,t,i){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==i?i:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function utf16Text(e,t){if((e.length-t)%2==0){var i=e.toString("utf16le",t);if(i){var s=i.charCodeAt(i.length-1);if(s>=55296&&s<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],i.slice(0,-1)}return i}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function utf16End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var i=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,i)}return t}function base64Text(e,t){var i=(e.length-t)%3;return 0===i?e.toString("base64",t):(this.lastNeed=3-i,this.lastTotal=3,1===i?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-i))}function base64End(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function simpleWrite(e){return e.toString(this.encoding)}function simpleEnd(e){return e&&e.length?this.write(e):""}t.StringDecoder=StringDecoder,StringDecoder.prototype.write=function(e){if(0===e.length)return"";var t,i;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";i=this.lastNeed,this.lastNeed=0}else i=0;return i=0)return n>0&&(e.lastNeed=n-1),n;if(--s=0)return n>0&&(e.lastNeed=n-2),n;if(--s=0)return n>0&&(2===n?n=0:e.lastNeed=n-3),n;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=i;var s=e.length-(i-this.lastNeed);return e.copy(this.lastChar,0,s),e.toString("utf8",t,s)},StringDecoder.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,i){"use strict";e.exports=Transform;var s=i(21),n=Object.create(i(26));function afterTransform(e,t){var i=this._transformState;i.transforming=!1;var s=i.writecb;if(!s)return this.emit("error",new Error("write callback called multiple times"));i.writechunk=null,i.writecb=null,null!=t&&this.push(t),s(e);var n=this._readableState;n.reading=!1,(n.needReadable||n.length{for(const t of e.values())this.handleDispose(t)};this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),this.client.incrementMaxListeners(),this.client.on(n.MESSAGE_CREATE,this.handleCollect),this.client.on(n.MESSAGE_DELETE,this.handleDispose),this.client.on(n.MESSAGE_BULK_DELETE,bulkDeleteListener),this.client.on(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(n.GUILD_DELETE,this._handleGuildDeletion),this.once("end",(()=>{this.client.removeListener(n.MESSAGE_CREATE,this.handleCollect),this.client.removeListener(n.MESSAGE_DELETE,this.handleDispose),this.client.removeListener(n.MESSAGE_BULK_DELETE,bulkDeleteListener),this.client.removeListener(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(n.GUILD_DELETE,this._handleGuildDeletion),this.client.decrementMaxListeners()}))}collect(e){return e.channel.id!==this.channel.id?null:(this.received++,e.id)}dispose(e){return e.channel.id===this.channel.id?e.id:null}endReason(){return this.options.max&&this.collected.size>=this.options.max?"limit":this.options.maxProcessed&&this.received===this.options.maxProcessed?"processedLimit":null}_handleChannelDeletion(e){e.id===this.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.channel.guild&&e.id===this.channel.guild.id&&this.stop("guildDelete")}}},function(e,t,i){"use strict";const{TypeError:s}=i(2),n=i(3);e.exports=class GuildMemberRoleManager{constructor(e){this.member=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){const e=this.guild.roles.everyone;return this.guild.roles.cache.filter((e=>this.member._roles.includes(e.id))).set(e.id,e)}get cache(){return this._roles}get hoist(){const e=this._roles.filter((e=>e.hoist));return e.size?e.reduce(((e,t)=>!e||t.comparePositionTo(e)>0?t:e)):null}get color(){const e=this._roles.filter((e=>e.color));return e.size?e.reduce(((e,t)=>!e||t.comparePositionTo(e)>0?t:e)):null}get highest(){return this._roles.reduce(((e,t)=>t.comparePositionTo(e)>0?t:e),this._roles.first())}async add(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=[...new Set(e.concat(...this._roles.values()))];return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Role, Snowflake or Array or Collection of Roles or Snowflakes");await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].put({reason:t});const i=this.member._clone();return i._roles=[...this._roles.keys(),e.id],i}}async remove(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=this._roles.filter((t=>!e.includes(t)));return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].delete({reason:t});const i=this.member._clone(),n=this._roles.filter((t=>t.id!==e.id));return i._roles=[...n.keys()],i}}set(e,t){return this.member.edit({roles:e},t)}clone(){const e=new this.constructor(this.member);return e.member._roles=[...this._roles.keyArray()],e}}},function(e,t,i){"use strict";const s=i(5),n=i(75),r=i(3),o=i(6);e.exports=class Team extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon||null,this.ownerID=e.owner_user_id||null,this.members=new r;for(const t of e.members){const e=new n(this,t);this.members.set(e.id,e)}}get owner(){return this.members.get(this.ownerID)||null}get createdTimestamp(){return o.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.TeamIcon(this.id,this.icon,{format:e,size:t}):null}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(5),{MembershipStates:n}=i(0);e.exports=class TeamMember extends s{constructor(e,t){super(e.client),this.team=e,this._patch(t)}_patch(e){this.permissions=e.permissions,this.membershipState=n[e.membership_state],this.user=this.client.users.add(e.user)}get id(){return this.user.id}toString(){return this.user.toString()}}},function(e,t,i){"use strict";const s=i(3),{ChannelTypes:n}=i(0),r=i(4);class MessageMentions{constructor(e,t,i,r,o){if(Object.defineProperty(this,"client",{value:e.client}),Object.defineProperty(this,"guild",{value:e.guild}),Object.defineProperty(this,"_content",{value:e.content}),this.everyone=Boolean(r),t)if(t instanceof s)this.users=new s(t);else{this.users=new s;for(const i of t){i.member&&e.guild&&e.guild.members.add(Object.assign(i.member,{user:i}));const t=e.client.users.add(i);this.users.set(t.id,t)}}else this.users=new s;if(i)if(i instanceof s)this.roles=new s(i);else{this.roles=new s;for(const t of i){const i=e.channel.guild.roles.cache.get(t);i&&this.roles.set(i.id,i)}}else this.roles=new s;if(this._members=null,this._channels=null,o)if(o instanceof s)this.crosspostedChannels=new s(o);else{this.crosspostedChannels=new s;const e=Object.keys(n);for(const t of o){const i=e[t.type];this.crosspostedChannels.set(t.id,{channelID:t.id,guildID:t.guild_id,type:i?i.toLowerCase():"unknown",name:t.name})}}else this.crosspostedChannels=new s}get members(){return this._members?this._members:this.guild?(this._members=new s,this.users.forEach((e=>{const t=this.guild.member(e);t&&this._members.set(t.user.id,t)})),this._members):null}get channels(){if(this._channels)return this._channels;let e;for(this._channels=new s;null!==(e=this.constructor.CHANNELS_PATTERN.exec(this._content));){const t=this.client.channels.cache.get(e[1]);t&&this._channels.set(t.id,t)}return this._channels}has(e,{ignoreDirect:t=!1,ignoreRoles:s=!1,ignoreEveryone:n=!1}={}){if(!n&&this.everyone)return!0;const r=i(11);if(!s&&e instanceof r)for(const t of this.roles.values())if(e.roles.cache.has(t.id))return!0;if(!t){const t=this.client.users.resolveID(e)||this.guild&&this.guild.roles.resolveID(e)||this.client.channels.resolveID(e);return this.users.has(t)||this.channels.has(t)||this.roles.has(t)}return!1}toJSON(){return r.flatten(this,{members:!0,channels:!0})}}MessageMentions.EVERYONE_PATTERN=/@(everyone|here)/g,MessageMentions.USERS_PATTERN=/<@!?(\d{17,19})>/g,MessageMentions.ROLES_PATTERN=/<@&(\d{17,19})>/g,MessageMentions.CHANNELS_PATTERN=/<#(\d{17,19})>/g,e.exports=MessageMentions},function(e,t,i){"use strict";const s=i(49),n=i(3),{Events:r}=i(0);class ReactionCollector extends s{constructor(e,t,i={}){super(e.client,t,i),this.message=e,this.users=new n,this.total=0,this.empty=this.empty.bind(this),this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),this._handleMessageDeletion=this._handleMessageDeletion.bind(this),this.client.incrementMaxListeners(),this.client.on(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.on(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.on(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.on(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.on(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(r.GUILD_DELETE,this._handleGuildDeletion),this.once("end",(()=>{this.client.removeListener(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.removeListener(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.removeListener(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.removeListener(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.removeListener(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(r.GUILD_DELETE,this._handleGuildDeletion),this.client.decrementMaxListeners()})),this.on("collect",((e,t)=>{this.total++,this.users.set(t.id,t)})),this.on("remove",((e,t)=>{this.total--,this.collected.some((e=>e.users.cache.has(t.id)))||this.users.delete(t.id)}))}collect(e){return e.message.id!==this.message.id?null:ReactionCollector.key(e)}dispose(e,t){return e.message.id!==this.message.id?null:(this.collected.has(ReactionCollector.key(e))&&this.users.has(t.id)&&this.emit("remove",e,t),e.count?null:ReactionCollector.key(e))}empty(){this.total=0,this.collected.clear(),this.users.clear(),this.checkEnd()}endReason(){return this.options.max&&this.total>=this.options.max?"limit":this.options.maxEmojis&&this.collected.size>=this.options.maxEmojis?"emojiLimit":this.options.maxUsers&&this.users.size>=this.options.maxUsers?"userLimit":null}_handleMessageDeletion(e){e.id===this.message.id&&this.stop("messageDelete")}_handleChannelDeletion(e){e.id===this.message.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.message.guild&&e.id===this.message.guild.id&&this.stop("guildDelete")}static key(e){return e.emoji.id||e.emoji.name}}e.exports=ReactionCollector},function(e,t,i){"use strict";const s=i(7),n=i(52);e.exports=class ReactionManager extends s{constructor(e,t){super(e.client,t,n),this.message=e}add(e,t){return super.add(e,t,{id:e.emoji.id||e.emoji.name,extras:[this.message]})}removeAll(){return this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions.delete().then((()=>this.message))}}},function(e,t,i){"use strict";const s=i(7),{Error:n}=i(2),r=i(3);e.exports=class ReactionUserManager extends s{constructor(e,t,i){super(e,t,{name:"User"}),this.reaction=i}async fetch({limit:e=100,after:t,before:i}={}){const s=this.reaction.message,n=await this.client.api.channels[s.channel.id].messages[s.id].reactions[this.reaction.emoji.identifier].get({query:{limit:e,before:i,after:t}}),o=new r;for(const e of n){const t=this.client.users.add(e);this.cache.set(t.id,t),o.set(t.id,t)}return o}remove(e=this.client.user){const t=this.client.users.resolveID(e);if(!t)return Promise.reject(new n("REACTION_RESOLVE_USER"));const i=this.reaction.message;return this.client.api.channels[i.channel.id].messages[i.id].reactions[this.reaction.emoji.identifier][t===this.client.user.id?"@me":t].delete().then((()=>this.reaction))}}},function(e,t,i){"use strict";const s=i(12);class UserFlags extends s{}UserFlags.FLAGS={DISCORD_EMPLOYEE:1,PARTNERED_SERVER_OWNER:2,DISCORD_PARTNER:2,HYPESQUAD_EVENTS:4,BUGHUNTER_LEVEL_1:8,HOUSE_BRAVERY:64,HOUSE_BRILLIANCE:128,HOUSE_BALANCE:256,EARLY_SUPPORTER:512,TEAM_USER:1024,SYSTEM:4096,BUGHUNTER_LEVEL_2:16384,VERIFIED_BOT:65536,EARLY_VERIFIED_DEVELOPER:1<<17,VERIFIED_DEVELOPER:1<<17},e.exports=UserFlags},function(e,t,i){"use strict";const s=i(18),{Error:n}=i(2),r=i(3),{browser:o}=i(0),a=i(8);e.exports=class VoiceChannel extends s{_patch(e){super._patch(e),this.bitrate=e.bitrate,this.userLimit=e.user_limit}get members(){const e=new r;for(const t of this.guild.voiceStates.cache.values())t.channelID===this.id&&t.member&&e.set(t.id,t.member);return e}get full(){return this.userLimit>0&&this.members.size>=this.userLimit}get deletable(){return super.deletable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get editable(){return this.manageable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get joinable(){return!o&&(!!this.viewable&&(!!this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)&&!(this.full&&!this.permissionsFor(this.client.user).has(a.FLAGS.MOVE_MEMBERS,!1))))}get speakable(){return this.permissionsFor(this.client.user).has(a.FLAGS.SPEAK,!1)}setBitrate(e,t){return this.edit({bitrate:e},t)}setUserLimit(e,t){return this.edit({userLimit:e},t)}join(){return o?Promise.reject(new n("VOICE_NO_BROWSER")):this.client.voice.joinChannel(this)}leave(){if(o)return;const e=this.client.voice.connections.get(this.guild.id);e&&e.channel.id===this.id&&e.disconnect()}}},function(e,t,i){"use strict";const s=i(18);e.exports=class CategoryChannel extends s{get children(){return this.guild.channels.cache.filter((e=>e.parentID===this.id))}}},function(e,t,i){"use strict";const s=i(41),{Error:n}=i(2);e.exports=class NewsChannel extends s{_patch(e){super._patch(e),this.rateLimitPerUser=void 0}async addFollower(e,t){const i=this.guild.channels.resolveID(e);if(!i)throw new n("GUILD_CHANNEL_RESOLVE");return await this.client.api.channels(this.id).followers.post({data:{webhook_channel_id:i},reason:t}),this}}},function(e,t,i){"use strict";const s=i(18);e.exports=class StoreChannel extends s{constructor(e,t){super(e,t),this.nsfw=Boolean(t.nsfw)}_patch(e){super._patch(e),void 0!==e.nsfw&&(this.nsfw=Boolean(e.nsfw))}}},function(e,t,i){(function(e){var s=Object.getOwnPropertyDescriptors||function getOwnPropertyDescriptors(e){for(var t=Object.keys(e),i={},s=0;s=r)return e;switch(e){case"%s":return String(s[i++]);case"%d":return Number(s[i++]);case"%j":try{return JSON.stringify(s[i++])}catch(e){return"[Circular]"}default:return e}})),a=s[i];i=3&&(s.depth=arguments[2]),arguments.length>=4&&(s.colors=arguments[3]),isBoolean(i)?s.showHidden=i:i&&t._extend(s,i),isUndefined(s.showHidden)&&(s.showHidden=!1),isUndefined(s.depth)&&(s.depth=2),isUndefined(s.colors)&&(s.colors=!1),isUndefined(s.customInspect)&&(s.customInspect=!0),s.colors&&(s.stylize=stylizeWithColor),formatValue(s,e,s.depth)}function stylizeWithColor(e,t){var i=inspect.styles[t];return i?"["+inspect.colors[i][0]+"m"+e+"["+inspect.colors[i][1]+"m":e}function stylizeNoColor(e,t){return e}function formatValue(e,i,s){if(e.customInspect&&i&&isFunction(i.inspect)&&i.inspect!==t.inspect&&(!i.constructor||i.constructor.prototype!==i)){var n=i.inspect(s,e);return isString(n)||(n=formatValue(e,n,s)),n}var r=function formatPrimitive(e,t){if(isUndefined(t))return e.stylize("undefined","undefined");if(isString(t)){var i="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(i,"string")}if(isNumber(t))return e.stylize(""+t,"number");if(isBoolean(t))return e.stylize(""+t,"boolean");if(isNull(t))return e.stylize("null","null")}(e,i);if(r)return r;var o=Object.keys(i),a=function arrayToHash(e){var t={};return e.forEach((function(e,i){t[e]=!0})),t}(o);if(e.showHidden&&(o=Object.getOwnPropertyNames(i)),isError(i)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return formatError(i);if(0===o.length){if(isFunction(i)){var c=i.name?": "+i.name:"";return e.stylize("[Function"+c+"]","special")}if(isRegExp(i))return e.stylize(RegExp.prototype.toString.call(i),"regexp");if(isDate(i))return e.stylize(Date.prototype.toString.call(i),"date");if(isError(i))return formatError(i)}var l,h="",u=!1,d=["{","}"];(isArray(i)&&(u=!0,d=["[","]"]),isFunction(i))&&(h=" [Function"+(i.name?": "+i.name:"")+"]");return isRegExp(i)&&(h=" "+RegExp.prototype.toString.call(i)),isDate(i)&&(h=" "+Date.prototype.toUTCString.call(i)),isError(i)&&(h=" "+formatError(i)),0!==o.length||u&&0!=i.length?s<0?isRegExp(i)?e.stylize(RegExp.prototype.toString.call(i),"regexp"):e.stylize("[Object]","special"):(e.seen.push(i),l=u?function formatArray(e,t,i,s,n){for(var r=[],o=0,a=t.length;o=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1}),0)>60)return i[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+i[1];return i[0]+t+" "+e.join(", ")+" "+i[1]}(l,h,d)):d[0]+h+d[1]}function formatError(e){return"["+Error.prototype.toString.call(e)+"]"}function formatProperty(e,t,i,s,n,r){var o,a,c;if((c=Object.getOwnPropertyDescriptor(t,n)||{value:t[n]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),hasOwnProperty(s,n)||(o="["+n+"]"),a||(e.seen.indexOf(c.value)<0?(a=isNull(i)?formatValue(e,c.value,null):formatValue(e,c.value,i-1)).indexOf("\n")>-1&&(a=r?a.split("\n").map((function(e){return" "+e})).join("\n").substr(2):"\n"+a.split("\n").map((function(e){return" "+e})).join("\n")):a=e.stylize("[Circular]","special")),isUndefined(o)){if(r&&n.match(/^\d+$/))return a;(o=JSON.stringify(""+n)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=e.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=e.stylize(o,"string"))}return o+": "+a}function isArray(e){return Array.isArray(e)}function isBoolean(e){return"boolean"==typeof e}function isNull(e){return null===e}function isNumber(e){return"number"==typeof e}function isString(e){return"string"==typeof e}function isUndefined(e){return void 0===e}function isRegExp(e){return isObject(e)&&"[object RegExp]"===objectToString(e)}function isObject(e){return"object"==typeof e&&null!==e}function isDate(e){return isObject(e)&&"[object Date]"===objectToString(e)}function isError(e){return isObject(e)&&("[object Error]"===objectToString(e)||e instanceof Error)}function isFunction(e){return"function"==typeof e}function objectToString(e){return Object.prototype.toString.call(e)}function pad(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(i){if(isUndefined(r)&&(r=e.env.NODE_DEBUG||""),i=i.toUpperCase(),!o[i])if(new RegExp("\\b"+i+"\\b","i").test(r)){var s=e.pid;o[i]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",i,s,e)}}else o[i]=function(){};return o[i]},t.inspect=inspect,inspect.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},inspect.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=isArray,t.isBoolean=isBoolean,t.isNull=isNull,t.isNullOrUndefined=function isNullOrUndefined(e){return null==e},t.isNumber=isNumber,t.isString=isString,t.isSymbol=function isSymbol(e){return"symbol"==typeof e},t.isUndefined=isUndefined,t.isRegExp=isRegExp,t.isObject=isObject,t.isDate=isDate,t.isError=isError,t.isFunction=isFunction,t.isPrimitive=function isPrimitive(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=i(138);var a=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function timestamp(){var e=new Date,t=[pad(e.getHours()),pad(e.getMinutes()),pad(e.getSeconds())].join(":");return[e.getDate(),a[e.getMonth()],t].join(" ")}function hasOwnProperty(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){console.log("%s - %s",timestamp(),t.format.apply(t,arguments))},t.inherits=i(139),t._extend=function(e,t){if(!t||!isObject(t))return e;for(var i=Object.keys(t),s=i.length;s--;)e[i[s]]=t[i[s]];return e};var c="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function callbackifyOnRejected(e,t){if(!e){var i=new Error("Promise was rejected with a falsy value");i.reason=e,e=i}return t(e)}t.promisify=function promisify(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(c&&e[c]){var t;if("function"!=typeof(t=e[c]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,c,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,i,s=new Promise((function(e,s){t=e,i=s})),n=[],r=0;re.target))).then((()=>t))}static targetType(e){return e<10?l.GUILD:e<20?l.CHANNEL:e<30?l.USER:e<40?l.ROLE:e<50?l.INVITE:e<60?l.WEBHOOK:e<70?l.EMOJI:e<80?l.MESSAGE:e<90?l.INTEGRATION:l.UNKNOWN}static actionType(e){return[h.CHANNEL_CREATE,h.CHANNEL_OVERWRITE_CREATE,h.MEMBER_BAN_REMOVE,h.BOT_ADD,h.ROLE_CREATE,h.INVITE_CREATE,h.WEBHOOK_CREATE,h.EMOJI_CREATE,h.MESSAGE_PIN,h.INTEGRATION_CREATE].includes(e)?"CREATE":[h.CHANNEL_DELETE,h.CHANNEL_OVERWRITE_DELETE,h.MEMBER_KICK,h.MEMBER_PRUNE,h.MEMBER_BAN_ADD,h.MEMBER_DISCONNECT,h.ROLE_DELETE,h.INVITE_DELETE,h.WEBHOOK_DELETE,h.EMOJI_DELETE,h.MESSAGE_DELETE,h.MESSAGE_BULK_DELETE,h.MESSAGE_UNPIN,h.INTEGRATION_DELETE].includes(e)?"DELETE":[h.GUILD_UPDATE,h.CHANNEL_UPDATE,h.CHANNEL_OVERWRITE_UPDATE,h.MEMBER_UPDATE,h.MEMBER_ROLE_UPDATE,h.MEMBER_MOVE,h.ROLE_UPDATE,h.INVITE_UPDATE,h.WEBHOOK_UPDATE,h.EMOJI_UPDATE,h.INTEGRATION_UPDATE].includes(e)?"UPDATE":"ALL"}toJSON(){return c.flatten(this)}}class GuildAuditLogsEntry{constructor(e,t,i){const r=GuildAuditLogs.targetType(i.action_type);switch(this.targetType=r,this.actionType=GuildAuditLogs.actionType(i.action_type),this.action=Object.keys(h).find((e=>h[e]===i.action_type)),this.reason=i.reason||null,this.executor=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.user_id}):t.client.users.cache.get(i.user_id),this.changes=i.changes?i.changes.map((e=>({key:e.key,old:e.old_value,new:e.new_value}))):null,this.id=i.id,this.extra=null,i.action_type){case h.MEMBER_PRUNE:this.extra={removed:Number(i.options.members_removed),days:Number(i.options.delete_member_days)};break;case h.MEMBER_MOVE:case h.MESSAGE_DELETE:case h.MESSAGE_BULK_DELETE:this.extra={channel:t.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},count:Number(i.options.count)};break;case h.MESSAGE_PIN:case h.MESSAGE_UNPIN:this.extra={channel:t.client.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},messageID:i.options.message_id};break;case h.MEMBER_DISCONNECT:this.extra={count:Number(i.options.count)};break;case h.CHANNEL_OVERWRITE_CREATE:case h.CHANNEL_OVERWRITE_UPDATE:case h.CHANNEL_OVERWRITE_DELETE:switch(i.options.type){case"member":this.extra=t.members.cache.get(i.options.id)||{id:i.options.id,type:"member"};break;case"role":this.extra=t.roles.cache.get(i.options.id)||{id:i.options.id,name:i.options.role_name,type:"role"}}}this.target=null,r===l.UNKNOWN?(this.target=this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{}),this.target.id=i.target_id):r===l.USER&&i.target_id?this.target=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.target_id}):t.client.users.cache.get(i.target_id):r===l.GUILD?this.target=t.client.guilds.cache.get(i.target_id):r===l.WEBHOOK?this.target=e.webhooks.get(i.target_id)||new n(t.client,this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{id:i.target_id,guild_id:t.id})):r===l.INVITE?this.target=t.members.fetch(t.client.user.id).then((e=>{if(e.permissions.has("MANAGE_GUILD")){const e=this.changes.find((e=>"code"===e.key));return t.fetchInvites().then((t=>{this.target=t.find((t=>t.code===(e.new||e.old)))}))}return this.target=this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{}),this.target})):r===l.MESSAGE?this.target=i.action_type===h.MESSAGE_BULK_DELETE?t.channels.cache.get(i.target_id)||{id:i.target_id}:t.client.users.cache.get(i.target_id):r===l.INTEGRATION?this.target=e.integrations.get(i.target_id)||new s(t.client,this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{id:i.target_id}),t):i.target_id&&(this.target=t[r.toLowerCase()+"s"].cache.get(i.target_id)||{id:i.target_id})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toJSON(){return c.flatten(this,{createdTimestamp:!0})}}GuildAuditLogs.Actions=h,GuildAuditLogs.Targets=l,GuildAuditLogs.Entry=GuildAuditLogsEntry,e.exports=GuildAuditLogs},function(e,t,i){"use strict";const s=i(7),n=i(18),r=i(42),{ChannelTypes:o}=i(0);e.exports=class GuildChannelManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e){const t=this.cache.get(e.id);return t||(this.cache.set(e.id,e),e)}async create(e,t={}){let{type:i,topic:s,nsfw:n,bitrate:a,userLimit:c,parent:l,permissionOverwrites:h,position:u,rateLimitPerUser:d,reason:f}=t;l&&(l=this.client.channels.resolveID(l)),h&&(h=h.map((e=>r.resolve(e,this.guild))));const p=await this.client.api.guilds(this.guild.id).channels.post({data:{name:e,topic:s,type:i?o[i.toUpperCase()]:o.TEXT,nsfw:n,bitrate:a,user_limit:c,parent_id:l,position:u,permission_overwrites:h,rate_limit_per_user:d},reason:f});return this.client.actions.ChannelCreate.handle(p).channel}}},function(e,t,i){"use strict";const s=i(7),{Error:n,TypeError:r,RangeError:o}=i(2),a=i(11),c=i(3),{Events:l,OPCodes:h}=i(0),u=i(6);e.exports=class GuildMemberManager extends s{constructor(e,t){super(e.client,t,a),this.guild=e}add(e,t=!0){return super.add(e,t,{id:e.user.id,extras:[this.guild]})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return i?super.resolve(i):null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}fetch(e){if(!e)return this._fetchMany();const t=this.client.users.resolveID(e);if(t)return this._fetchSingle({user:t,cache:!0});if(e.user){if(Array.isArray(e.user))return e.user=e.user.map((e=>this.client.users.resolveID(e))),this._fetchMany(e);if(e.user=this.client.users.resolveID(e.user),!e.limit&&!e.withPresences)return this._fetchSingle(e)}return this._fetchMany(e)}prune({days:e=7,dry:t=!1,count:i=!0,roles:s=[],reason:n}={}){if("number"!=typeof e)throw new r("PRUNE_DAYS_TYPE");const o={days:e},a=[];for(const e of s){const t=this.guild.roles.resolveID(e);if(!t)return Promise.reject(new r("INVALID_TYPE","roles","Array of Roles or Snowflakes",!0));a.push(t)}a.length&&(o.include_roles=t?a.join(","):a);const c=this.client.api.guilds(this.guild.id).prune;return t?c.get({query:o,reason:n}).then((e=>e.pruned)):c.post({data:{...o,compute_prune_count:i},reason:n}).then((e=>e.pruned))}ban(e,t={days:0}){t.days&&(t.delete_message_days=t.days);const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].put({data:t}).then((()=>{if(e instanceof a)return e;const t=this.client.users.resolve(i);if(t){return this.resolve(t)||t}return i})):Promise.reject(new n("BAN_RESOLVE_ID",!0))}unban(e,t){const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].delete({reason:t}).then((()=>this.client.users.resolve(e))):Promise.reject(new n("BAN_RESOLVE_ID"))}_fetchSingle({user:e,cache:t,force:i=!1}){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return Promise.resolve(t)}return this.client.api.guilds(this.guild.id).members(e).get().then((e=>this.add(e,t)))}_fetchMany({limit:e=0,withPresences:t=!1,user:i,query:s,time:r=12e4,nonce:a=u.generate(),force:d=!1}={}){return new Promise(((u,f)=>{if(!(this.guild.memberCount!==this.cache.size||s||e||t||i||d))return void u(this.cache);if(s||i||(s=""),a.length>32)throw new o("MEMBER_FETCH_NONCE_LENGTH");this.guild.shard.send({op:h.REQUEST_GUILD_MEMBERS,d:{guild_id:this.guild.id,presences:t,user_ids:i,query:s,nonce:a,limit:e}});const p=new c,m=s||e||t||i;let g=0;const handler=(t,s,n)=>{if(E.refresh(),n.nonce===a){g++;for(const e of t.values())m&&p.set(e.id,e);if(this.guild.memberCount<=this.cache.size||m&&t.size<1e3||e&&p.size>=e||g===n.count){this.client.clearTimeout(E),this.client.removeListener(l.GUILD_MEMBERS_CHUNK,handler),this.client.decrementMaxListeners();let e=m?p:this.cache;i&&!Array.isArray(i)&&e.size&&(e=e.first()),u(e)}}},E=this.client.setTimeout((()=>{this.client.removeListener(l.GUILD_MEMBERS_CHUNK,handler),this.client.decrementMaxListeners(),f(new n("GUILD_MEMBERS_TIMEOUT"))}),r);this.client.incrementMaxListeners(),this.client.on(l.GUILD_MEMBERS_CHUNK,handler)}))}}},function(e,t,i){"use strict";const s=i(7),{Presence:n}=i(24);e.exports=class PresenceManager extends s{constructor(e,t){super(e,t,n)}add(e,t){const i=this.cache.get(e.user.id);return i?i.patch(e):super.add(e,t,{id:e.user.id})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return super.resolve(i)||null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}}},function(e,t,i){"use strict";const s=i(12);class ActivityFlags extends s{}ActivityFlags.FLAGS={INSTANCE:1,JOIN:2,SPECTATE:4,JOIN_REQUEST:8,SYNC:16,PLAY:32},e.exports=ActivityFlags},function(e,t,i){"use strict";const s=i(7),n=i(20),r=i(8),{resolveColor:o}=i(4);e.exports=class RoleManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async fetch(e,t=!0,i=!1){if(e&&!i){const t=this.cache.get(e);if(t)return t}const s=await this.client.api.guilds(this.guild.id).roles.get();for(const e of s)this.add(e,t);return e?this.cache.get(e)||null:this}create({data:e={},reason:t}={}){return e.color&&(e.color=o(e.color)),e.permissions&&(e.permissions=r.resolve(e.permissions)),this.guild.client.api.guilds(this.guild.id).roles.post({data:e,reason:t}).then((i=>{const{role:s}=this.client.actions.GuildRoleCreate.handle({guild_id:this.guild.id,role:i});return e.position?s.setPosition(e.position,t):s}))}get everyone(){return this.cache.get(this.guild.id)}get highest(){return this.cache.reduce(((e,t)=>t.comparePositionTo(e)>0?t:e),this.cache.first())}}},function(e,t,i){"use strict";const s=i(12);class SystemChannelFlags extends s{}SystemChannelFlags.FLAGS={WELCOME_MESSAGE_DISABLED:1,BOOST_MESSAGE_DISABLED:2},e.exports=SystemChannelFlags},function(e,t,i){"use strict";const{Presence:s}=i(24),{TypeError:n}=i(2),r=i(3),{ActivityTypes:o,OPCodes:a}=i(0);e.exports=class ClientPresence extends s{constructor(e,t={}){super(e,Object.assign(t,{status:"online",user:{id:null}}))}async set(e){const t=await this._parse(e);if(this.patch(t),void 0===e.shardID)this.client.ws.broadcast({op:a.STATUS_UPDATE,d:t});else if(Array.isArray(e.shardID))for(const i of e.shardID)this.client.ws.shards.get(i).send({op:a.STATUS_UPDATE,d:t});else this.client.ws.shards.get(e.shardID).send({op:a.STATUS_UPDATE,d:t});return this}async _parse({status:e,since:t,afk:i,activity:s}){const a=s&&(s.application?s.application.id||s.application:null);let c=new r;if(s){if("string"!=typeof s.name)throw new n("INVALID_TYPE","name","string");if(s.type||(s.type=0),s.assets&&a)try{const e=await this.client.api.oauth2.applications(a).assets.get();for(const t of e)c.set(t.name,t.id)}catch{}}const l={afk:null!=i&&i,since:null!=t?t:null,status:e||this.status,game:s?{type:s.type,name:s.name,url:s.url,details:s.details||void 0,state:s.state||void 0,assets:s.assets?{large_text:s.assets.largeText||void 0,small_text:s.assets.smallText||void 0,large_image:c.get(s.assets.largeImage)||s.assets.largeImage,small_image:c.get(s.assets.smallImage)||s.assets.smallImage}:void 0,timestamps:s.timestamps||void 0,party:s.party||void 0,application_id:a||void 0,secrets:s.secrets||void 0,instance:s.instance||void 0}:null};return(e||i||t)&&!s&&(l.game=this.activities[0]||null),l.game&&(l.game.type="number"==typeof l.game.type?l.game.type:o.indexOf(l.game.type)),l}}},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(2),{browser:o}=i(0);e.exports=class VoiceState extends s{constructor(e,t){super(e.client),this.guild=e,this.id=t.user_id,this._patch(t)}_patch(e){return this.serverDeaf="deaf"in e?e.deaf:null,this.serverMute="mute"in e?e.mute:null,this.selfDeaf="self_deaf"in e?e.self_deaf:null,this.selfMute="self_mute"in e?e.self_mute:null,this.selfVideo="self_video"in e?e.self_video:null,this.sessionID="session_id"in e?e.session_id:null,this.streaming=e.self_stream||!1,this.channelID=e.channel_id||null,this}get member(){return this.guild.members.cache.get(this.id)||null}get channel(){return this.guild.channels.cache.get(this.channelID)||null}get connection(){return o||this.id!==this.client.user.id?null:this.client.voice.connections.get(this.guild.id)||null}get deaf(){return this.serverDeaf||this.selfDeaf}get mute(){return this.serverMute||this.selfMute}get speaking(){return this.channel&&this.channel.connection?Boolean(this.channel.connection._speaking.get(this.id)):null}setMute(e,t){return this.member?this.member.edit({mute:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}setDeaf(e,t){return this.member?this.member.edit({deaf:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}kick(e){return this.setChannel(null,e)}setChannel(e,t){return this.member?this.member.edit({channel:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}async setSelfMute(e){if(this.id!==this.client.user.id)throw new n("VOICE_STATE_NOT_OWN");if("boolean"!=typeof e)throw new r("VOICE_STATE_INVALID_TYPE","mute");return!!this.connection&&(this.selfMute=e,await this.connection.sendVoiceStateUpdate(),!0)}async setSelfDeaf(e){return this.id!==this.client.user.id?new n("VOICE_STATE_NOT_OWN"):"boolean"!=typeof e?new r("VOICE_STATE_INVALID_TYPE","deaf"):!!this.connection&&(this.selfDeaf=e,await this.connection.sendVoiceStateUpdate(),!0)}toJSON(){return super.toJSON({id:!0,serverDeaf:!0,serverMute:!0,selfDeaf:!0,selfMute:!0,sessionID:!0,channelID:"channel"})}}},function(e,t,i){"use strict";(function(e){const{browser:s}=i(0);let n,r;try{n=i(170),n.pack||(n=null)}catch{}s?(r=window.TextDecoder,t.WebSocket=window.WebSocket):(r=i(85).TextDecoder,t.WebSocket=i(171));const o=new r;t.encoding=n?"etf":"json",t.pack=n?n.pack:JSON.stringify,t.unpack=(i,s)=>"json"===t.encoding||"json"===s?("string"!=typeof i&&(i=o.decode(i)),JSON.parse(i)):(e.isBuffer(i)||(i=e.from(new Uint8Array(i))),n.unpack(i)),t.create=(e,i={},...n)=>{const[r,o]=e.split("?");i.encoding=t.encoding,i=new URLSearchParams(i),o&&new URLSearchParams(o).forEach(((e,t)=>i.set(t,e)));const a=new t.WebSocket(`${r}?${i}`,...n);return s&&(a.binaryType="arraybuffer"),a};for(const e of["CONNECTING","OPEN","CLOSING","CLOSED"])t[e]=t.WebSocket[e]}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const{WSEvents:s}=i(0),n={};for(const e of Object.keys(s))try{n[e]=i(173)(`./${e}.js`)}catch{}e.exports=n},function(e,t,i){"use strict";const s=i(9),n=i(10);class ClientUser extends(n.get("User")){constructor(e,t){super(e,t),this._typing=new Map}_patch(e){super._patch(e),"verified"in e&&(this.verified=e.verified),"mfa_enabled"in e?this.mfaEnabled="boolean"==typeof e.mfa_enabled?e.mfa_enabled:null:void 0===this.mfaEnabled&&(this.mfaEnabled=null),e.token&&(this.client.token=e.token)}get presence(){return this.client.presence}edit(e){return this.client.api.users("@me").patch({data:e}).then((e=>{this.client.token=e.token;const{updated:t}=this.client.actions.UserUpdate.handle(e);return t||this}))}setUsername(e){return this.edit({username:e})}async setAvatar(e){return this.edit({avatar:await s.resolveImage(e)})}setPresence(e){return this.client.presence.set(e)}setStatus(e,t){return this.setPresence({status:e,shardID:t})}setActivity(e,t={}){if(!e)return this.setPresence({activity:null,shardID:t.shardID});const i=Object.assign({},t,"object"==typeof e?e:{name:e});return this.setPresence({activity:i,shardID:i.shardID})}setAFK(e){return this.setPresence({afk:e})}}e.exports=ClientUser},function(e,t,i){"use strict";const s=i(7),n=i(17),{Events:r}=i(0);e.exports=class ChannelManager extends s{constructor(e,t){super(e,t,n)}add(e,t,i=!0){const s=this.cache.get(e.id);if(s)return s._patch&&i&&s._patch(e),t&&t.channels.add(s),s;const o=n.create(this.client,e,t);return o?(i&&this.cache.set(o.id,o),o):(this.client.emit(r.DEBUG,`Failed to find guild, or unknown type for channel ${e.id} ${e.type}`),null)}remove(e){const t=this.cache.get(e);t.guild&&t.guild.channels.cache.delete(e),this.cache.delete(e)}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.channels(e).get();return this.add(s,null,t)}}},function(e,t,i){"use strict";const s=i(7),n=i(54),r=i(18),o=i(25),a=i(11),c=i(19),l=i(20),{ChannelTypes:h,Events:u,VerificationLevels:d,DefaultMessageNotifications:f,ExplicitContentFilterLevels:p}=i(0),m=i(9),g=i(8),{resolveColor:E}=i(4);e.exports=class GuildManager extends s{constructor(e,t){super(e,t,n)}resolve(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolve(e.guild):super.resolve(e)}resolveID(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolveID(e.guild.id):super.resolveID(e)}async create(e,{afkChannelID:t,afkTimeout:i,channels:s=[],defaultMessageNotifications:n,explicitContentFilter:r,icon:o=null,region:a,roles:c=[],systemChannelID:l,verificationLevel:_}={}){o=await m.resolveImage(o),void 0!==_&&"number"!=typeof _&&(_=d.indexOf(_)),void 0!==n&&"number"!=typeof n&&(n=f.indexOf(n)),void 0!==r&&"number"!=typeof r&&(r=p.indexOf(r));for(const e of s)if(e.type&&(e.type=h[e.type.toUpperCase()]),e.parent_id=e.parentID,delete e.parentID,e.permissionOverwrites){for(const t of e.permissionOverwrites)t.allow&&(t.allow=g.resolve(t.allow)),t.deny&&(t.deny=g.resolve(t.deny));e.permission_overwrites=e.permissionOverwrites,delete e.permissionOverwrites}for(const e of c)e.color&&(e.color=E(e.color)),e.permissions&&(e.permissions=g.resolve(e.permissions));return new Promise(((h,d)=>this.client.api.guilds.post({data:{name:e,region:a,icon:o,verification_level:_,default_message_notifications:n,explicit_content_filter:r,roles:c,channels:s,afk_channel_id:t,afk_timeout:i,system_channel_id:l}}).then((e=>{if(this.client.guilds.cache.has(e.id))return h(this.client.guilds.cache.get(e.id));const handleGuild=i=>{i.id===e.id&&(this.client.clearTimeout(t),this.client.removeListener(u.GUILD_CREATE,handleGuild),this.client.decrementMaxListeners(),h(i))};this.client.incrementMaxListeners(),this.client.on(u.GUILD_CREATE,handleGuild);const t=this.client.setTimeout((()=>{this.client.removeListener(u.GUILD_CREATE,handleGuild),this.client.decrementMaxListeners(),h(this.client.guilds.add(e))}),1e4)}),d)))}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t)return t}const s=await this.client.api.guilds(e).get({query:{with_counts:!0}});return this.add(s,t)}}},function(e,t,i){"use strict";const s=i(7),n=i(11),r=i(28),o=i(27);e.exports=class UserManager extends s{constructor(e,t){super(e,t,o)}resolve(e){return e instanceof n?e.user:e instanceof r?e.author:super.resolve(e)}resolveID(e){return e instanceof n?e.user.id:e instanceof r?e.author.id:super.resolveID(e)}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.users(e).get();return this.add(s,t)}}},function(e,t,i){"use strict";const s=i(12);class Intents extends s{}Intents.FLAGS={GUILDS:1,GUILD_MEMBERS:2,GUILD_BANS:4,GUILD_EMOJIS:8,GUILD_INTEGRATIONS:16,GUILD_WEBHOOKS:32,GUILD_INVITES:64,GUILD_VOICE_STATES:128,GUILD_PRESENCES:256,GUILD_MESSAGES:512,GUILD_MESSAGE_REACTIONS:1024,GUILD_MESSAGE_TYPING:2048,DIRECT_MESSAGES:4096,DIRECT_MESSAGE_REACTIONS:8192,DIRECT_MESSAGE_TYPING:16384},Intents.PRIVILEGED=Intents.FLAGS.GUILD_MEMBERS|Intents.FLAGS.GUILD_PRESENCES,Intents.ALL=Object.values(Intents.FLAGS).reduce(((e,t)=>e|t),0),Intents.NON_PRIVILEGED=Intents.ALL&~Intents.PRIVILEGED,e.exports=Intents},function(e,t,i){"use strict";const s=i(4);e.exports={BaseClient:i(37),Client:i(115),Shard:i(212),ShardClientUtil:i(213),ShardingManager:i(214),WebhookClient:i(48),ActivityFlags:i(90),BitField:i(12),Collection:i(3),Constants:i(0),DataResolver:i(9),BaseManager:i(7),DiscordAPIError:i(64),HTTPError:i(65),MessageFlags:i(47),Intents:i(101),Permissions:i(8),Speaking:i(215),Snowflake:i(6),SnowflakeUtil:i(6),Structures:i(10),SystemChannelFlags:i(92),UserFlags:i(80),Util:s,version:i(61).version,ChannelManager:i(98),GuildChannelManager:i(87),GuildEmojiManager:i(59),GuildEmojiRoleManager:i(66),GuildMemberManager:i(88),GuildMemberRoleManager:i(73),GuildManager:i(99),ReactionManager:i(78),ReactionUserManager:i(79),MessageManager:i(34),PresenceManager:i(89),RoleManager:i(91),UserManager:i(100),discordSort:s.discordSort,escapeMarkdown:s.escapeMarkdown,fetchRecommendedShards:s.fetchRecommendedShards,resolveColor:s.resolveColor,resolveString:s.resolveString,splitMessage:s.splitMessage,Application:i(51),Base:i(5),Activity:i(24).Activity,APIMessage:i(30),BaseGuildEmoji:i(40),CategoryChannel:i(82),Channel:i(17),ClientApplication:i(50),get ClientUser(){return i(97)},Collector:i(49),DMChannel:i(39),Emoji:i(29),Guild:i(54),GuildAuditLogs:i(86),GuildChannel:i(18),GuildEmoji:i(25),GuildMember:i(11),GuildPreview:i(56),GuildTemplate:i(57),Integration:i(55),Invite:i(19),Message:i(28),MessageAttachment:i(43),MessageCollector:i(72),MessageEmbed:i(44),MessageMentions:i(76),MessageReaction:i(52),NewsChannel:i(83),PermissionOverwrites:i(42),Presence:i(24).Presence,ClientPresence:i(93),ReactionCollector:i(77),ReactionEmoji:i(53),RichPresenceAssets:i(24).RichPresenceAssets,Role:i(20),StoreChannel:i(84),Team:i(74),TeamMember:i(75),TextChannel:i(41),User:i(27),VoiceChannel:i(81),VoiceRegion:i(58),VoiceState:i(94),Webhook:i(13),WebSocket:i(95)}},function(e,t,i){"use strict";t.byteLength=function byteLength(e){var t=getLens(e),i=t[0],s=t[1];return 3*(i+s)/4-s},t.toByteArray=function toByteArray(e){var t,i,s=getLens(e),o=s[0],a=s[1],c=new r(function _byteLength(e,t,i){return 3*(t+i)/4-i}(0,o,a)),l=0,h=a>0?o-4:o;for(i=0;i>16&255,c[l++]=t>>8&255,c[l++]=255&t;2===a&&(t=n[e.charCodeAt(i)]<<2|n[e.charCodeAt(i+1)]>>4,c[l++]=255&t);1===a&&(t=n[e.charCodeAt(i)]<<10|n[e.charCodeAt(i+1)]<<4|n[e.charCodeAt(i+2)]>>2,c[l++]=t>>8&255,c[l++]=255&t);return c},t.fromByteArray=function fromByteArray(e){for(var t,i=e.length,n=i%3,r=[],o=16383,a=0,c=i-n;ac?c:a+o));1===n?(t=e[i-1],r.push(s[t>>2]+s[t<<4&63]+"==")):2===n&&(t=(e[i-2]<<8)+e[i-1],r.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return r.join("")};for(var s=[],n=[],r="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=o.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var i=e.indexOf("=");return-1===i&&(i=t),[i,i===t?0:4-i%4]}function encodeChunk(e,t,i){for(var n,r,o=[],a=t;a>18&63]+s[r>>12&63]+s[r>>6&63]+s[63&r]);return o.join("")}n["-".charCodeAt(0)]=62,n["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,i,s,n){var r,o,a=8*n-s-1,c=(1<>1,h=-7,u=i?n-1:0,d=i?-1:1,f=e[t+u];for(u+=d,r=f&(1<<-h)-1,f>>=-h,h+=a;h>0;r=256*r+e[t+u],u+=d,h-=8);for(o=r&(1<<-h)-1,r>>=-h,h+=s;h>0;o=256*o+e[t+u],u+=d,h-=8);if(0===r)r=1-l;else{if(r===c)return o?NaN:1/0*(f?-1:1);o+=Math.pow(2,s),r-=l}return(f?-1:1)*o*Math.pow(2,r-s)},t.write=function(e,t,i,s,n,r){var o,a,c,l=8*r-n-1,h=(1<>1,d=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,f=s?0:r-1,p=s?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=h):(o=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-o))<1&&(o--,c*=2),(t+=o+u>=1?d/c:d*Math.pow(2,1-u))*c>=2&&(o++,c/=2),o+u>=h?(a=0,o=h):o+u>=1?(a=(t*c-1)*Math.pow(2,n),o+=u):(a=t*Math.pow(2,u-1)*Math.pow(2,n),o=0));n>=8;e[i+f]=255&a,f+=p,a/=256,n-=8);for(o=o<0;e[i+f]=255&o,f+=p,o/=256,l-=8);e[i+f-p]|=128*m}},function(e,t,i){"use strict";const{register:s}=i(62),n={CLIENT_INVALID_OPTION:(e,t)=>`The ${e} option must be ${t}`,CLIENT_INVALID_PROVIDED_SHARDS:"None of the provided shards were valid.",TOKEN_INVALID:"An invalid token was provided.",TOKEN_MISSING:"Request to use token, but token was unavailable to the client.",WS_CLOSE_REQUESTED:"WebSocket closed due to user request.",WS_CONNECTION_EXISTS:"There is already an existing WebSocket connection.",WS_NOT_OPEN:(e="data")=>"Websocket not open to send "+e,BITFIELD_INVALID:"Invalid bitfield flag or number.",SHARDING_INVALID:"Invalid shard settings were provided.",SHARDING_REQUIRED:"This session would have handled too many guilds - Sharding is required.",INVALID_INTENTS:"Invalid intent provided for WebSocket intents.",DISALLOWED_INTENTS:"Privileged intent provided is not enabled or whitelisted.",SHARDING_NO_SHARDS:"No shards have been spawned.",SHARDING_IN_PROCESS:"Shards are still being spawned.",SHARDING_SHARD_NOT_FOUND:e=>`Shard ${e} could not be found.`,SHARDING_ALREADY_SPAWNED:e=>`Already spawned ${e} shards.`,SHARDING_PROCESS_EXISTS:e=>`Shard ${e} already has an active process.`,SHARDING_WORKER_EXISTS:e=>`Shard ${e} already has an active worker.`,SHARDING_READY_TIMEOUT:e=>`Shard ${e}'s Client took too long to become ready.`,SHARDING_READY_DISCONNECTED:e=>`Shard ${e}'s Client disconnected before becoming ready.`,SHARDING_READY_DIED:e=>`Shard ${e}'s process exited before its Client became ready.`,SHARDING_NO_CHILD_EXISTS:e=>`Shard ${e} has no active process or worker.`,SHARDING_SHARD_MISCALCULATION:(e,t,i)=>`Calculated invalid shard ${e} for guild ${t} with ${i} shards.`,COLOR_RANGE:"Color must be within the range 0 - 16777215 (0xFFFFFF).",COLOR_CONVERT:"Unable to convert color to a number.",EMBED_FIELD_NAME:"MessageEmbed field names may not be empty.",EMBED_FIELD_VALUE:"MessageEmbed field values may not be empty.",FILE_NOT_FOUND:e=>"File could not be found: "+e,USER_NO_DMCHANNEL:"No DM Channel exists!",VOICE_INVALID_HEARTBEAT:"Tried to set voice heartbeat but no valid interval was specified.",VOICE_USER_MISSING:"Couldn't resolve the user to create stream.",VOICE_JOIN_CHANNEL:(e=!1)=>"You do not have permission to join this voice channel"+(e?"; it is full.":"."),VOICE_CONNECTION_TIMEOUT:"Connection not established within 15 seconds.",VOICE_TOKEN_ABSENT:"Token not provided from voice server packet.",VOICE_SESSION_ABSENT:"Session ID not supplied.",VOICE_INVALID_ENDPOINT:"Invalid endpoint received.",VOICE_NO_BROWSER:"Voice connections are not available in browsers.",VOICE_CONNECTION_ATTEMPTS_EXCEEDED:e=>`Too many connection attempts (${e}).`,VOICE_JOIN_SOCKET_CLOSED:"Tried to send join packet, but the WebSocket is not open.",VOICE_PLAY_INTERFACE_NO_BROADCAST:"A broadcast cannot be played in this context.",VOICE_PLAY_INTERFACE_BAD_TYPE:"Unknown stream type",VOICE_PRISM_DEMUXERS_NEED_STREAM:"To play a webm/ogg stream, you need to pass a ReadableStream.",VOICE_STATE_UNCACHED_MEMBER:"The member of this voice state is uncached.",VOICE_STATE_NOT_OWN:"You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.",VOICE_STATE_INVALID_TYPE:e=>e+" must be a boolean.",UDP_SEND_FAIL:"Tried to send a UDP packet, but there is no socket available.",UDP_ADDRESS_MALFORMED:"Malformed UDP address or port.",UDP_CONNECTION_EXISTS:"There is already an existing UDP connection.",REQ_RESOURCE_TYPE:"The resource must be a string, Buffer or a valid file stream.",IMAGE_FORMAT:e=>"Invalid image format: "+e,IMAGE_SIZE:e=>"Invalid image size: "+e,MESSAGE_BULK_DELETE_TYPE:"The messages must be an Array, Collection, or number.",MESSAGE_NONCE_TYPE:"Message nonce must fit in an unsigned 64-bit integer.",TYPING_COUNT:"Count must be at least 1",SPLIT_MAX_LEN:"Chunk exceeds the max length and contains no split characters.",BAN_RESOLVE_ID:(e=!1)=>`Couldn't resolve the user ID to ${e?"ban":"unban"}.`,FETCH_BAN_RESOLVE_ID:"Couldn't resolve the user ID to fetch the ban.",PRUNE_DAYS_TYPE:"Days must be a number",GUILD_CHANNEL_RESOLVE:"Could not resolve channel to a guild channel.",GUILD_VOICE_CHANNEL_RESOLVE:"Could not resolve channel to a guild voice channel.",GUILD_CHANNEL_ORPHAN:"Could not find a parent to this guild channel.",GUILD_OWNED:"Guild is owned by the client.",GUILD_MEMBERS_TIMEOUT:"Members didn't arrive in time.",GUILD_UNCACHED_ME:"The client user as a member of this guild is uncached.",INVALID_TYPE:(e,t,i=!1)=>`Supplied ${e} is not a${i?"n":""} ${t}.`,WEBHOOK_MESSAGE:"The message was not sent by a webhook.",EMOJI_TYPE:"Emoji must be a string or GuildEmoji/ReactionEmoji",EMOJI_MANAGED:"Emoji is managed and has no Author.",MISSING_MANAGE_EMOJIS_PERMISSION:e=>`Client must have Manage Emoji permission in guild ${e} to see emoji authors.`,REACTION_RESOLVE_USER:"Couldn't resolve the user ID to remove from the reaction.",VANITY_URL:"This guild does not have the VANITY_URL feature enabled.",DELETE_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot delete them",FETCH_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot fetch them",MEMBER_FETCH_NONCE_LENGTH:"Nonce length must not exceed 32 characters."};for(const[e,t]of Object.entries(n))s(e,t)},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Collection=void 0;class Collection extends Map{constructor(e){super(e),Object.defineProperty(this,"_array",{value:null,writable:!0,configurable:!0}),Object.defineProperty(this,"_keyArray",{value:null,writable:!0,configurable:!0})}get(e){return super.get(e)}set(e,t){return this._array=null,this._keyArray=null,super.set(e,t)}has(e){return super.has(e)}delete(e){return this._array=null,this._keyArray=null,super.delete(e)}clear(){return super.clear()}array(){return this._array&&this._array.length===this.size||(this._array=[...this.values()]),this._array}keyArray(){return this._keyArray&&this._keyArray.length===this.size||(this._keyArray=[...this.keys()]),this._keyArray}first(e){if(void 0===e)return this.values().next().value;if(e<0)return this.last(-1*e);e=Math.min(this.size,e);const t=this.values();return Array.from({length:e},(()=>t.next().value))}firstKey(e){if(void 0===e)return this.keys().next().value;if(e<0)return this.lastKey(-1*e);e=Math.min(this.size,e);const t=this.keys();return Array.from({length:e},(()=>t.next().value))}last(e){const t=this.array();return void 0===e?t[t.length-1]:e<0?this.first(-1*e):e?t.slice(-e):[]}lastKey(e){const t=this.keyArray();return void 0===e?t[t.length-1]:e<0?this.firstKey(-1*e):e?t.slice(-e):[]}random(e){let t=this.array();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},(()=>t.splice(Math.floor(Math.random()*t.length),1)[0]))):[]}randomKey(e){let t=this.keyArray();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},(()=>t.splice(Math.floor(Math.random()*t.length),1)[0]))):[]}find(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return i}findKey(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return t}sweep(e,t){void 0!==t&&(e=e.bind(t));const i=this.size;for(const[t,i]of this)e(i,t,this)&&this.delete(t);return i-this.size}filter(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)e(s,t,this)&&i.set(t,s);return i}partition(e,t){void 0!==t&&(e=e.bind(t));const i=[new this.constructor[Symbol.species],new this.constructor[Symbol.species]];for(const[t,s]of this)e(s,t,this)?i[0].set(t,s):i[1].set(t,s);return i}flatMap(e,t){const i=this.map(e,t);return(new this.constructor[Symbol.species]).concat(...i)}map(e,t){void 0!==t&&(e=e.bind(t));const i=this.entries();return Array.from({length:this.size},(()=>{const[t,s]=i.next().value;return e(s,t,this)}))}mapValues(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)i.set(t,e(s,t,this));return i}some(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return!0;return!1}every(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(!e(i,t,this))return!1;return!0}reduce(e,t){let i;if(void 0!==t){i=t;for(const[t,s]of this)i=e(i,s,t,this);return i}let s=!0;for(const[t,n]of this)s?(i=n,s=!1):i=e(i,n,t,this);if(s)throw new TypeError("Reduce of empty collection with no initial value");return i}each(e,t){return this.forEach(e,t),this}tap(e,t){return void 0!==t&&(e=e.bind(t)),e(this),this}clone(){return new this.constructor[Symbol.species](this)}concat(...e){const t=this.clone();for(const i of e)for(const[e,s]of i)t.set(e,s);return t}equals(e){if(!e)return!1;if(this===e)return!0;if(this.size!==e.size)return!1;for(const[t,i]of this)if(!e.has(t)||i!==e.get(t))return!1;return!0}sort(e=((e,t)=>Number(e>t)||Number(e===t)-1)){const t=[...this.entries()];t.sort(((t,i)=>e(t[1],i[1],t[0],i[0]))),super.clear(),this._array=null,this._keyArray=null;for(const[e,i]of t)super.set(e,i);return this}intersect(e){return e.filter(((e,t)=>this.has(t)))}difference(e){return e.filter(((e,t)=>!this.has(t))).concat(this.filter(((t,i)=>!e.has(i))))}sorted(e=((e,t)=>Number(e>t)||Number(e===t)-1)){return new this.constructor[Symbol.species]([...this.entries()]).sort(((t,i,s,n)=>e(t,i,s,n)))}}t.Collection=Collection,Collection.default=Collection,e.exports=Collection,t.default=Collection},function(e,t,i){"use strict";const s=i(108),n=i(112),r=i(113),{Error:o}=i(2),a=i(3),{Endpoints:c}=i(0);e.exports=class RESTManager{constructor(e,t="Bot"){this.client=e,this.handlers=new a,this.tokenPrefix=t,this.versioned=!0,this.globalTimeout=null,e.options.restSweepInterval>0&&e.setInterval((()=>{this.handlers.sweep((e=>e._inactive))}),1e3*e.options.restSweepInterval)}get api(){return n(this)}getAuth(){const e=this.client.token||this.client.accessToken;if(e)return`${this.tokenPrefix} ${e}`;throw new o("TOKEN_MISSING")}get cdn(){return c.CDN(this.client.options.http.cdn)}request(e,t,i={}){const n=new s(this,e,t,i);let o=this.handlers.get(n.route);return o||(o=new r(this),this.handlers.set(n.route,o)),o.push(n)}get endpoint(){return this.client.options.http.api}set endpoint(e){this.client.options.http.api=e}}},function(e,t,i){"use strict";const s=i(109),n=i(110),r=i(111),o=i(36),{browser:a,UserAgent:c}=i(0);if(s.Agent)var l=new s.Agent({keepAlive:!0});e.exports=class APIRequest{constructor(e,t,i,s){this.rest=e,this.client=e.client,this.method=t,this.route=s.route,this.options=s,this.retries=0;let n="";if(s.query){const e=Object.entries(s.query).filter((([,e])=>![null,"null","undefined"].includes(e)&&void 0!==e)).flatMap((([e,t])=>Array.isArray(t)?t.map((t=>[e,t])):[[e,t]]));n=new URLSearchParams(e).toString()}this.path=`${i}${n&&"?"+n}`}make(){const e=(!1===this.options.versioned?this.client.options.http.api:`${this.client.options.http.api}/v${this.client.options.http.version}`)+this.path;let t,i={};if(!1!==this.options.auth&&(i.Authorization=this.rest.getAuth()),this.options.reason&&(i["X-Audit-Log-Reason"]=encodeURIComponent(this.options.reason)),a||(i["User-Agent"]=c),this.options.headers&&(i=Object.assign(i,this.options.headers)),this.options.files&&this.options.files.length){t=new n;for(const e of this.options.files)e&&e.file&&t.append(e.name,e.file,e.name);void 0!==this.options.data&&t.append("payload_json",JSON.stringify(this.options.data)),a||(i=Object.assign(i,t.getHeaders()))}else null!=this.options.data&&(t=JSON.stringify(this.options.data),i["Content-Type"]="application/json");const s=new r,h=this.client.setTimeout((()=>s.abort()),this.client.options.restRequestTimeout);return o(e,{method:this.method,headers:i,agent:l,body:t,signal:s.signal}).finally((()=>this.client.clearTimeout(h)))}}},function(e,t){},function(e,t){e.exports="object"==typeof self?self.FormData:window.FormData},function(e,t,i){"use strict";const{AbortController:s,AbortSignal:n}="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0;e.exports=s,e.exports.AbortSignal=n,e.exports.default=s},function(e,t,i){"use strict";const noop=()=>{},s=["get","post","delete","patch","put"],n=["toString","valueOf","inspect","constructor",Symbol.toPrimitive,Symbol.for("nodejs.util.inspect.custom")];e.exports=function buildRoute(e){const t=[""],i={get(r,o){if(n.includes(o))return()=>t.join("/");if(s.includes(o)){const i=[];for(let e=0;ee.request(o,t.join("/"),Object.assign({versioned:e.versioned,route:i.join("/")},s))}return t.push(o),new Proxy(noop,i)},apply:(e,s,n)=>(t.push(...n.filter((e=>null!=e))),new Proxy(noop,i))};return new Proxy(noop,i)}},function(e,t,i){"use strict";const s=i(114),n=i(64),r=i(65),{Events:{RATE_LIMIT:o},browser:a}=i(0),c=i(4);function parseResponse(e){return e.headers.get("content-type").startsWith("application/json")?e.json():a?e.blob():e.buffer()}function getAPIOffset(e){return new Date(e).getTime()-Date.now()}e.exports=class RequestHandler{constructor(e){this.manager=e,this.queue=new s,this.reset=-1,this.remaining=-1,this.limit=-1,this.retryAfter=-1}async push(e){await this.queue.wait();try{return await this.execute(e)}finally{this.queue.shift()}}get limited(){return Boolean(this.manager.globalTimeout)||this.remaining<=0&&Date.now()=400&&t.status<500){if(429===t.status)return this.manager.client.emit("debug","429 hit on route "+e.route),await c.delayFor(this.retryAfter),this.execute(e);let i;try{i=await parseResponse(t)}catch(t){throw new r(t.message,t.constructor.name,t.status,e.method,e.path)}throw new n(e.path,i,e.method,t.status)}if(t.status>=500&&t.status<600){if(e.retries===this.manager.client.options.retryLimit)throw new r(t.statusText,t.constructor.name,t.status,e.method,e.path);return e.retries++,this.execute(e)}return null}}},function(e,t,i){"use strict";e.exports=class AsyncQueue{constructor(){this.promises=[]}get remaining(){return this.promises.length}wait(){const e=this.promises.length?this.promises[this.promises.length-1].promise:Promise.resolve();let t;const i=new Promise((e=>{t=e}));return this.promises.push({resolve:t,promise:i}),e}shift(){const e=this.promises.shift();void 0!==e&&e.resolve()}}},function(module,exports,__webpack_require__){"use strict";(function(process){const BaseClient=__webpack_require__(37),ActionsManager=__webpack_require__(116),ClientVoiceManager=__webpack_require__(167),WebSocketManager=__webpack_require__(168),{Error:Error,TypeError:TypeError,RangeError:RangeError}=__webpack_require__(2),ChannelManager=__webpack_require__(98),GuildEmojiManager=__webpack_require__(59),GuildManager=__webpack_require__(99),UserManager=__webpack_require__(100),ShardClientUtil=__webpack_require__(210),ClientApplication=__webpack_require__(50),GuildPreview=__webpack_require__(56),GuildTemplate=__webpack_require__(57),Invite=__webpack_require__(19),VoiceRegion=__webpack_require__(58),Webhook=__webpack_require__(13),Collection=__webpack_require__(3),{Events:Events,browser:browser,DefaultOptions:DefaultOptions}=__webpack_require__(0),DataResolver=__webpack_require__(9),Intents=__webpack_require__(101),Permissions=__webpack_require__(8),Structures=__webpack_require__(10);class Client extends BaseClient{constructor(e={}){super(Object.assign({_tokenType:"Bot"},e));let t=process.env;try{t=__webpack_require__(211).workerData||t}catch{}this.options.shards===DefaultOptions.shards&&"SHARDS"in t&&(this.options.shards=JSON.parse(t.SHARDS)),this.options.shardCount===DefaultOptions.shardCount&&("SHARD_COUNT"in t?this.options.shardCount=Number(t.SHARD_COUNT):Array.isArray(this.options.shards)&&(this.options.shardCount=this.options.shards.length));const i=typeof this.options.shards;"undefined"===i&&"number"==typeof this.options.shardCount&&(this.options.shards=Array.from({length:this.options.shardCount},((e,t)=>t))),"number"===i&&(this.options.shards=[this.options.shards]),Array.isArray(this.options.shards)&&(this.options.shards=[...new Set(this.options.shards.filter((e=>!isNaN(e)&&e>=0&&e<1/0&&e===(0|e))))]),this._validateOptions(),this.ws=new WebSocketManager(this),this.actions=new ActionsManager(this),this.voice=browser?null:new ClientVoiceManager(this),this.shard=!browser&&process.env.SHARDING_MANAGER?ShardClientUtil.singleton(this,process.env.SHARDING_MANAGER_MODE):null,this.users=new UserManager(this),this.guilds=new GuildManager(this),this.channels=new ChannelManager(this);const s=Structures.get("ClientPresence");this.presence=new s(this),Object.defineProperty(this,"token",{writable:!0}),browser||this.token||!("DISCORD_TOKEN"in process.env)?this.token=null:this.token=process.env.DISCORD_TOKEN,this.user=null,this.readyAt=null,this.options.messageSweepInterval>0&&this.setInterval(this.sweepMessages.bind(this),1e3*this.options.messageSweepInterval)}get emojis(){const e=new GuildEmojiManager({client:this});for(const t of this.guilds.cache.values())if(t.available)for(const i of t.emojis.cache.values())e.cache.set(i.id,i);return e}get readyTimestamp(){return this.readyAt?this.readyAt.getTime():null}get uptime(){return this.readyAt?Date.now()-this.readyAt:null}async login(e=this.token){if(!e||"string"!=typeof e)throw new Error("TOKEN_INVALID");this.token=e=e.replace(/^(Bot|Bearer)\s*/i,""),this.emit(Events.DEBUG,"Provided token: "+e.split(".").map(((e,t)=>t>1?e.replace(/./g,"*"):e)).join(".")),this.options.presence&&(this.options.ws.presence=await this.presence._parse(this.options.presence)),this.emit(Events.DEBUG,"Preparing to connect to the gateway...");try{return await this.ws.connect(),this.token}catch(e){throw this.destroy(),e}}destroy(){super.destroy(),this.ws.destroy(),this.token=null}fetchInvite(e){const t=DataResolver.resolveInviteCode(e);return this.api.invites(t).get({query:{with_counts:!0}}).then((e=>new Invite(this,e)))}fetchGuildTemplate(e){const t=DataResolver.resolveGuildTemplateCode(e);return this.api.guilds.templates(t).get().then((e=>new GuildTemplate(this,e)))}fetchWebhook(e,t){return this.api.webhooks(e,t).get().then((e=>new Webhook(this,e)))}fetchVoiceRegions(){return this.api.voice.regions.get().then((e=>{const t=new Collection;for(const i of e)t.set(i.id,new VoiceRegion(i));return t}))}sweepMessages(e=this.options.messageCacheLifetime){if("number"!=typeof e||isNaN(e))throw new TypeError("INVALID_TYPE","lifetime","number");if(e<=0)return this.emit(Events.DEBUG,"Didn't sweep messages - lifetime is unlimited"),-1;const t=1e3*e,i=Date.now();let s=0,n=0;for(const e of this.channels.cache.values())e.messages&&(s++,n+=e.messages.cache.sweep((e=>i-(e.editedTimestamp||e.createdTimestamp)>t)));return this.emit(Events.DEBUG,`Swept ${n} messages older than ${e} seconds in ${s} text-based channels`),n}fetchApplication(){return this.api.oauth2.applications("@me").get().then((e=>new ClientApplication(this,e)))}fetchGuildPreview(e){const t=this.guilds.resolveID(e);if(!t)throw new TypeError("INVALID_TYPE","guild","GuildResolvable");return this.api.guilds(t).preview.get().then((e=>new GuildPreview(this,e)))}async generateInvite(e={}){(Array.isArray(e)||["string","number"].includes(typeof e)||e instanceof Permissions)&&(process.emitWarning("Client#generateInvite: Generate invite with an options object instead of a PermissionResolvable","DeprecationWarning"),e={permissions:e});const t=await this.fetchApplication(),i=new URLSearchParams({client_id:t.id,permissions:Permissions.resolve(e.permissions),scope:"bot"});if("boolean"==typeof e.disableGuildSelect&&i.set("disable_guild_select",e.disableGuildSelect.toString()),void 0!==e.guild){const t=this.guilds.resolveID(e.guild);if(!t)throw new TypeError("INVALID_TYPE","options.guild","GuildResolvable");i.set("guild_id",t)}return`${this.options.http.api}${this.api.oauth2.authorize}?${i}`}toJSON(){return super.toJSON({readyAt:!1})}_eval(script){return eval(script)}_validateOptions(e=this.options){if(void 0!==e.ws.intents&&(e.ws.intents=Intents.resolve(e.ws.intents)),"number"!=typeof e.shardCount||isNaN(e.shardCount)||e.shardCount<1)throw new TypeError("CLIENT_INVALID_OPTION","shardCount","a number greater than or equal to 1");if(e.shards&&"auto"!==e.shards&&!Array.isArray(e.shards))throw new TypeError("CLIENT_INVALID_OPTION","shards","'auto', a number or array of numbers");if(e.shards&&!e.shards.length)throw new RangeError("CLIENT_INVALID_PROVIDED_SHARDS");if("number"!=typeof e.messageCacheMaxSize||isNaN(e.messageCacheMaxSize))throw new TypeError("CLIENT_INVALID_OPTION","messageCacheMaxSize","a number");if("number"!=typeof e.messageCacheLifetime||isNaN(e.messageCacheLifetime))throw new TypeError("CLIENT_INVALID_OPTION","The messageCacheLifetime","a number");if("number"!=typeof e.messageSweepInterval||isNaN(e.messageSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","messageSweepInterval","a number");if("number"!=typeof e.messageEditHistoryMaxSize||isNaN(e.messageEditHistoryMaxSize)||e.messageEditHistoryMaxSize<-1)throw new TypeError("CLIENT_INVALID_OPTION","messageEditHistoryMaxSize","a number greater than or equal to -1");if("boolean"!=typeof e.fetchAllMembers)throw new TypeError("CLIENT_INVALID_OPTION","fetchAllMembers","a boolean");if("string"!=typeof e.disableMentions)throw new TypeError("CLIENT_INVALID_OPTION","disableMentions","a string");if(!Array.isArray(e.partials))throw new TypeError("CLIENT_INVALID_OPTION","partials","an Array");if("number"!=typeof e.restWsBridgeTimeout||isNaN(e.restWsBridgeTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restWsBridgeTimeout","a number");if("number"!=typeof e.restRequestTimeout||isNaN(e.restRequestTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restRequestTimeout","a number");if("number"!=typeof e.restSweepInterval||isNaN(e.restSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","restSweepInterval","a number");if("number"!=typeof e.retryLimit||isNaN(e.retryLimit))throw new TypeError("CLIENT_INVALID_OPTION","retryLimit","a number")}}module.exports=Client}).call(this,__webpack_require__(15))},function(e,t,i){"use strict";e.exports=class ActionsManager{constructor(e){this.client=e,this.register(i(117)),this.register(i(118)),this.register(i(119)),this.register(i(120)),this.register(i(121)),this.register(i(122)),this.register(i(123)),this.register(i(124)),this.register(i(125)),this.register(i(126)),this.register(i(144)),this.register(i(145)),this.register(i(146)),this.register(i(147)),this.register(i(148)),this.register(i(149)),this.register(i(150)),this.register(i(151)),this.register(i(152)),this.register(i(153)),this.register(i(154)),this.register(i(155)),this.register(i(156)),this.register(i(157)),this.register(i(158)),this.register(i(159)),this.register(i(160)),this.register(i(161)),this.register(i(162)),this.register(i(163)),this.register(i(164)),this.register(i(165)),this.register(i(166))}register(e){this[e.name.replace(/Action$/,"")]=new e(this.client)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=i.messages.cache.get(e.id);if(s)return{message:s};const r=i.messages.add(e),o=r.author;let a=r.member;return i.lastMessageID=e.id,o&&(o.lastMessageID=e.id,o.lastMessageChannelID=i.id),a&&(a.lastMessageID=e.id,a.lastMessageChannelID=i.id),t.emit(n.MESSAGE_CREATE,r),{message:r}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageDeleteAction extends s{handle(e){const t=this.client,i=this.getChannel(e);let s;return i&&(s=this.getMessage(e,i),s&&(i.messages.cache.delete(s.id),s.deleted=!0,t.emit(n.MESSAGE_DELETE,s))),{message:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(3),{Events:r}=i(0);e.exports=class MessageDeleteBulkAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=e.ids,o=new n;for(const t of s){const s=this.getMessage({id:t,guild_id:e.guild_id},i,!1);s&&(s.deleted=!0,o.set(s.id,s),i.messages.cache.delete(t))}return o.size>0&&t.emit(r.MESSAGE_BULK_DELETE,o),{messages:o}}return{}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class MessageUpdateAction extends s{handle(e){const t=this.getChannel(e);if(t){const{id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a}=e,c=this.getMessage({id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a},t);if(c){return{old:c.patch(e),updated:c}}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),{PartialTypes:r}=i(0);e.exports=class MessageReactionAdd extends s{handle(e){if(!e.emoji)return!1;const t=this.getUserFromMember(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;if(s.partial&&!this.client.options.partials.includes(r.REACTION))return!1;const o=s.reactions.cache.get(e.emoji.id||e.emoji.name);if(o&&o.users.cache.has(t.id))return{message:s,reaction:o,user:t};const a=s.reactions.add({emoji:e.emoji,count:s.partial?null:0,me:t.id===this.client.user.id});return!!a&&(a._add(t),this.client.emit(n.MESSAGE_REACTION_ADD,a,t),{message:s,reaction:a,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemove extends s{handle(e){if(!e.emoji)return!1;const t=this.getUser(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;const r=this.getReaction(e,s,t);return!!r&&(r._remove(t),this.client.emit(n.MESSAGE_REACTION_REMOVE,r,t),{message:s,reaction:r,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveAll extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);return!!i&&(i.reactions.cache.clear(),this.client.emit(n.MESSAGE_REACTION_REMOVE_ALL,i),{message:i})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveEmoji extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);if(!i)return!1;const s=this.getReaction(e,i);return!!s&&(i.partial||i.reactions.cache.delete(s.emoji.id||s.emoji.name),this.client.emit(n.MESSAGE_REACTION_REMOVE_EMOJI,s),{reaction:s})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class ChannelCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.has(e.id),s=t.channels.add(e);return!i&&s&&t.emit(n.CHANNEL_CREATE,s),{channel:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(39),{Events:r}=i(0);e.exports=class ChannelDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.channels.cache.get(e.id);if(i){if(t.channels.remove(i.id),i.deleted=!0,i.messages&&!(i instanceof n))for(const e of i.messages.cache.values())e.deleted=!0;t.emit(r.CHANNEL_DELETE,i)}return{channel:i}}}},function(e,t,i){e.exports=Stream;var s=i(16).EventEmitter;function Stream(){s.call(this)}i(23)(Stream,s),Stream.Readable=i(45),Stream.Writable=i(133),Stream.Duplex=i(134),Stream.Transform=i(135),Stream.PassThrough=i(136),Stream.Stream=Stream,Stream.prototype.pipe=function(e,t){var i=this;function ondata(t){e.writable&&!1===e.write(t)&&i.pause&&i.pause()}function ondrain(){i.readable&&i.resume&&i.resume()}i.on("data",ondata),e.on("drain",ondrain),e._isStdio||t&&!1===t.end||(i.on("end",onend),i.on("close",onclose));var n=!1;function onend(){n||(n=!0,e.end())}function onclose(){n||(n=!0,"function"==typeof e.destroy&&e.destroy())}function onerror(e){if(cleanup(),0===s.listenerCount(this,"error"))throw e}function cleanup(){i.removeListener("data",ondata),e.removeListener("drain",ondrain),i.removeListener("end",onend),i.removeListener("close",onclose),i.removeListener("error",onerror),e.removeListener("error",onerror),i.removeListener("end",cleanup),i.removeListener("close",cleanup),e.removeListener("close",cleanup)}return i.on("error",onerror),e.on("error",onerror),i.on("end",cleanup),i.on("close",cleanup),e.on("close",cleanup),e.emit("pipe",i),e}},function(e,t){},function(e,t,i){"use strict";var s=i(32).Buffer,n=i(130);e.exports=function(){function BufferList(){!function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,BufferList),this.head=null,this.tail=null,this.length=0}return BufferList.prototype.push=function push(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},BufferList.prototype.unshift=function unshift(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},BufferList.prototype.shift=function shift(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},BufferList.prototype.clear=function clear(){this.head=this.tail=null,this.length=0},BufferList.prototype.join=function join(e){if(0===this.length)return"";for(var t=this.head,i=""+t.data;t=t.next;)i+=e+t.data;return i},BufferList.prototype.concat=function concat(e){if(0===this.length)return s.alloc(0);if(1===this.length)return this.head.data;for(var t,i,n,r=s.allocUnsafe(e>>>0),o=this.head,a=0;o;)t=o.data,i=r,n=a,t.copy(i,n),a+=o.data.length,o=o.next;return r},BufferList}(),n&&n.inspect&&n.inspect.custom&&(e.exports.prototype[n.inspect.custom]=function(){var e=n.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,i){(function(t){function config(e){try{if(!t.localStorage)return!1}catch(e){return!1}var i=t.localStorage[e];return null!=i&&"true"===String(i).toLowerCase()}e.exports=function deprecate(e,t){if(config("noDeprecation"))return e;var i=!1;return function deprecated(){if(!i){if(config("throwDeprecation"))throw new Error(t);config("traceDeprecation")?console.trace(t):console.warn(t),i=!0}return e.apply(this,arguments)}}}).call(this,i(22))},function(e,t,i){"use strict";e.exports=PassThrough;var s=i(71),n=Object.create(i(26));function PassThrough(e){if(!(this instanceof PassThrough))return new PassThrough(e);s.call(this,e)}n.inherits=i(23),n.inherits(PassThrough,s),PassThrough.prototype._transform=function(e,t,i){i(null,e)}},function(e,t,i){e.exports=i(46)},function(e,t,i){e.exports=i(21)},function(e,t,i){e.exports=i(45).Transform},function(e,t,i){e.exports=i(45).PassThrough},function(e,t,i){"use strict";const s=i(3);class LimitedCollection extends s{constructor(e=0,t=null){super(t),this.maxSize=e}set(e,t){return 0===this.maxSize?this:(this.size>=this.maxSize&&!this.has(e)&&this.delete(this.firstKey()),super.set(e,t))}static get[Symbol.species](){return s}}e.exports=LimitedCollection},function(e,t){e.exports=function isBuffer(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function inherits(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function inherits(e,t){e.super_=t;var TempCtor=function(){};TempCtor.prototype=t.prototype,e.prototype=new TempCtor,e.prototype.constructor=e}},function(e,t,i){"use strict";const s=i(51);e.exports=class IntegrationApplication extends s{_patch(e){super._patch(e),void 0!==e.bot?this.bot=this.client.users.add(e.bot):this.bot||(this.bot=null)}}},function(e,t,i){"use strict";const s=i(40);e.exports=class GuildPreviewEmoji extends s{get roles(){return new Set(this._roles)}}},function(e,t,i){"use strict";const s=i(7);e.exports=class VoiceStateManager extends s{constructor(e,t){super(e.client,t,{name:"VoiceState"}),this.guild=e}add(e,t=!0){const i=this.cache.get(e.user_id);if(i)return i._patch(e);const s=new this.holds(this.guild,e);return t&&this.cache.set(e.user_id,s),s}}},function(e,t,i){"use strict";const s=i(17),{Error:n}=i(2);e.exports=class PartialGroupDMChannel extends s{constructor(e,t){super(e,t),this.name=t.name,this.icon=t.icon}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.GDMIcon(this.id,this.icon,e,t):null}delete(){return Promise.reject(new n("DELETE_GROUP_DM_CHANNEL"))}fetch(){return Promise.reject(new n("FETCH_GROUP_DM_CHANNEL"))}}},function(e,t,i){"use strict";const s=i(1),n=i(17),{ChannelTypes:r}=i(0);e.exports=class ChannelUpdateAction extends s{handle(e){let t=this.client.channels.cache.get(e.id);if(t){const i=t._update(e);if(r[t.type.toUpperCase()]!==e.type){const i=n.create(this.client,e,t.guild);for(const[e,s]of t.messages.cache)i.messages.cache.set(e,s);i._typing=new Map(t._typing),t=i,this.client.channels.cache.set(t.id,t)}return{old:i,updated:t}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.guilds.cache.get(e.id);if(i){for(const e of i.channels.cache.values())"text"===e.type&&e.stopTyping(!0);if(e.unavailable)return i.available=!1,t.emit(n.GUILD_UNAVAILABLE,i),{guild:null};for(const e of i.channels.cache.values())this.client.channels.remove(e.id);i.voice&&i.voice.connection&&i.voice.connection.disconnect(),t.guilds.cache.delete(i.id),i.deleted=!0,t.emit(n.GUILD_DELETE,i),this.deleted.set(i.id,i),this.scheduleForDeletion(i.id)}else i=this.deleted.get(e.id)||null;return{guild:i}}scheduleForDeletion(e){this.client.setTimeout((()=>this.deleted.delete(e)),this.client.options.restWsBridgeTimeout)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.id);if(i){const s=i._update(e);return t.emit(n.GUILD_UPDATE,s,i),{old:s,updated:i}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),n=i(19),{Events:r}=i(0);e.exports=class InviteCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_CREATE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),n=i(19),{Events:r}=i(0);e.exports=class InviteDeleteAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_DELETE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),{Events:n,Status:r}=i(0);e.exports=class GuildMemberRemoveAction extends s{handle(e,t){const i=this.client,s=i.guilds.cache.get(e.guild_id);let o=null;return s&&(o=this.getMember({user:e.user},s),s.memberCount--,o&&(o.deleted=!0,s.members.cache.delete(o.id),t.status===r.READY&&i.emit(n.GUILD_MEMBER_REMOVE,o)),s.voiceStates.cache.delete(e.user.id)),{guild:s,member:o}}}},function(e,t,i){"use strict";const s=i(1),{Status:n,Events:r}=i(0);e.exports=class GuildMemberUpdateAction extends s{handle(e,t){const{client:i}=this;if(e.user.username){const t=i.users.cache.get(e.user.id);t?t.equals(e.user)||i.actions.UserUpdate.handle(e.user):i.users.add(e.user)}const s=i.guilds.cache.get(e.guild_id);if(s){const o=this.getMember({user:e.user},s);if(o){const s=o._update(e);t.status===n.READY&&i.emit(r.GUILD_MEMBER_UPDATE,s,o)}else{const t=s.members.add(e);this.client.emit(r.GUILD_MEMBER_AVAILABLE,t)}}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildBanRemove extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id),s=t.users.add(e.user);i&&s&&t.emit(n.GUILD_BAN_REMOVE,i,s)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleCreate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;if(i){const r=i.roles.cache.has(e.role.id);s=i.roles.add(e.role),r||t.emit(n.GUILD_ROLE_CREATE,s)}return{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleDeleteAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;return i&&(s=i.roles.cache.get(e.role_id),s&&(i.roles.cache.delete(e.role_id),s.deleted=!0,t.emit(n.GUILD_ROLE_DELETE,s))),{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){let s=null;const r=i.roles.cache.get(e.role.id);return r&&(s=r._update(e.role),t.emit(n.GUILD_ROLE_UPDATE,s,r)),{old:s,updated:r}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class PresenceUpdateAction extends s{handle(e){let t=this.client.users.cache.get(e.user.id);if(!t&&e.user.username&&(t=this.client.users.add(e.user)),!t)return;e.user&&e.user.username&&(t.equals(e.user)||this.client.actions.UserUpdate.handle(e.user));const i=this.client.guilds.cache.get(e.guild_id);if(!i)return;let s=i.presences.cache.get(t.id);s&&(s=s._clone());let r=i.members.cache.get(t.id);r||"offline"===e.status||(r=i.members.add({user:t,roles:e.roles,deaf:!1,mute:!1}),this.client.emit(n.GUILD_MEMBER_AVAILABLE,r)),i.presences.add(Object.assign(e,{guild:i})),r&&this.client.listenerCount(n.PRESENCE_UPDATE)&&this.client.emit(n.PRESENCE_UPDATE,s,r.presence)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class UserUpdateAction extends s{handle(e){const t=this.client,i=t.users.cache.get(e.id),s=i._update(e);return s.equals(i)?{old:null,updated:null}:(t.emit(n.USER_UPDATE,s,i),{old:s,updated:i})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),r=i(10);e.exports=class VoiceStateUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){const s=r.get("VoiceState"),o=i.voiceStates.cache.has(e.user_id)?i.voiceStates.cache.get(e.user_id)._clone():new s(i,{user_id:e.user_id}),a=i.voiceStates.add(e);let c=i.members.cache.get(e.user_id);c&&e.member?c._patch(e.member):e.member&&e.member.user&&e.member.joined_at&&(c=i.members.add(e.member)),c&&c.user.id===t.user.id&&(t.emit("debug","[VOICE] received voice state update: "+JSON.stringify(e)),t.voice.onVoiceStateUpdate(e)),t.emit(n.VOICE_STATE_UPDATE,o,a)}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiCreateAction extends s{handle(e,t){const i=e.emojis.cache.has(t.id),s=e.emojis.add(t);return i||this.client.emit(n.GUILD_EMOJI_CREATE,s),{emoji:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiDeleteAction extends s{handle(e){return e.guild.emojis.cache.delete(e.id),e.deleted=!0,this.client.emit(n.GUILD_EMOJI_DELETE,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiUpdateAction extends s{handle(e,t){const i=e._update(t);return this.client.emit(n.GUILD_EMOJI_UPDATE,i,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildEmojisUpdateAction extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(!t||!t.emojis)return;const i=new Map(t.emojis.cache);for(const s of e.emojis){const e=t.emojis.cache.get(s.id);e?(i.delete(s.id),e.equals(s)||this.client.actions.GuildEmojiUpdate.handle(e,s)):this.client.actions.GuildEmojiCreate.handle(t,s)}for(const e of i.values())this.client.actions.GuildEmojiDelete.handle(e)}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildRolesPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.roles){const e=t.roles.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildChannelsPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.channels){const e=t.channels.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildIntegrationsUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);i&&t.emit(n.GUILD_INTEGRATIONS_UPDATE,i)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class WebhooksUpdate extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);i&&t.emit(n.WEBHOOKS_UPDATE,i)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),r=["dm","text","news"];e.exports=class TypingStart extends s{handle(e){const t=this.getChannel(e);if(!t)return;if(!r.includes(t.type))return void this.client.emit(n.WARN,`Discord sent a typing packet to a ${t.type} channel ${t.id}`);const i=this.getUserFromMember(e),s=new Date(1e3*e.timestamp);if(t&&i)if(t._typing.has(i.id)){const e=t._typing.get(i.id);e.lastTimestamp=s,e.elapsedTime=Date.now()-e.since,this.client.clearTimeout(e.timeout),e.timeout=this.tooLate(t,i)}else{const e=new Date,s=new Date;t._typing.set(i.id,{user:i,since:e,lastTimestamp:s,elapsedTime:Date.now()-e,timeout:this.tooLate(t,i)}),this.client.emit(n.TYPING_START,t,i)}}tooLate(e,t){return e.client.setTimeout((()=>{e._typing.delete(t.id)}),1e4)}}},function(e,t){},function(e,t,i){"use strict";const s=i(16),n=i(169),r=i(96),{Error:o}=i(2),a=i(3),{Events:c,ShardEvents:l,Status:h,WSCodes:u,WSEvents:d}=i(0),f=i(4),p=[d.READY,d.RESUMED,d.GUILD_CREATE,d.GUILD_DELETE,d.GUILD_MEMBERS_CHUNK,d.GUILD_MEMBER_ADD,d.GUILD_MEMBER_REMOVE],m=Object.keys(u).slice(1).map(Number),g=[1e3,4006,4007];e.exports=class WebSocketManager extends s{constructor(e){super(),Object.defineProperty(this,"client",{value:e}),this.gateway=null,this.totalShards=this.client.options.shards.length,this.shards=new a,Object.defineProperty(this,"shardQueue",{value:new Set,writable:!0}),Object.defineProperty(this,"packetQueue",{value:[]}),this.status=h.IDLE,this.destroyed=!1,this.reconnecting=!1,this.sessionStartLimit=null}get ping(){return this.shards.reduce(((e,t)=>e+t.ping),0)/this.shards.size}debug(e,t){this.client.emit(c.DEBUG,`[WS => ${t?"Shard "+t.id:"Manager"}] ${e}`)}async connect(){const e=new o(u[4004]),{url:t,shards:i,session_start_limit:s}=await this.client.api.gateway.bot.get().catch((t=>{throw 401===t.httpStatus?e:t}));this.sessionStartLimit=s;const{total:r,remaining:a,reset_after:c}=s;this.debug(`Fetched Gateway Information\n URL: ${t}\n Recommended Shards: ${i}`),this.debug(`Session Limit Information\n Total: ${r}\n Remaining: ${a}`),this.gateway=t+"/";let{shards:l}=this.client.options;return"auto"===l&&(this.debug("Using the recommended shard count provided by Discord: "+i),this.totalShards=this.client.options.shardCount=i,l=this.client.options.shards=Array.from({length:i},((e,t)=>t))),this.totalShards=l.length,this.debug("Spawning shards: "+l.join(", ")),this.shardQueue=new Set(l.map((e=>new n(this,e)))),await this._handleSessionLimit(a,c),this.createShards()}async createShards(){if(!this.shardQueue.size)return!1;const[e]=this.shardQueue;this.shardQueue.delete(e),e.eventsAttached||(e.on(l.ALL_READY,(t=>{this.client.emit(c.SHARD_READY,e.id,t),this.shardQueue.size||(this.reconnecting=!1),this.checkShardsReady()})),e.on(l.CLOSE,(t=>{if(1e3===t.code?this.destroyed:m.includes(t.code))return this.client.emit(c.SHARD_DISCONNECT,t,e.id),void this.debug(u[t.code],e);g.includes(t.code)&&(e.sessionID=null),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),e.sessionID?(this.debug("Session ID is present, attempting an immediate reconnect...",e),this.reconnect(!0)):(e.destroy({reset:!0,emit:!1,log:!1}),this.reconnect())})),e.on(l.INVALID_SESSION,(()=>{this.client.emit(c.SHARD_RECONNECTING,e.id)})),e.on(l.DESTROYED,(()=>{this.debug("Shard was destroyed but no WebSocket connection was present! Reconnecting...",e),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),this.reconnect()})),e.eventsAttached=!0),this.shards.set(e.id,e);try{await e.connect()}catch(t){if(t&&t.code&&m.includes(t.code))throw new o(u[t.code]);if(t&&!t.code)throw t;this.debug("Failed to connect to the gateway, requeueing...",e),this.shardQueue.add(e)}return!this.shardQueue.size||(this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`),await f.delayFor(5e3),await this._handleSessionLimit(),this.createShards())}async reconnect(e=!1){if(this.reconnecting||this.status!==h.READY)return!1;this.reconnecting=!0;try{e||await this._handleSessionLimit(),await this.createShards()}catch(e){if(this.debug("Couldn't reconnect or fetch information about the gateway. "+e),401!==e.httpStatus)return this.debug("Possible network error occurred. Retrying in 5s..."),await f.delayFor(5e3),this.reconnecting=!1,this.reconnect();this.client.listenerCount(c.INVALIDATED)?(this.client.emit(c.INVALIDATED),this.destroy()):this.client.destroy()}finally{this.reconnecting=!1}return!0}broadcast(e){for(const t of this.shards.values())t.send(e)}destroy(){if(!this.destroyed){this.debug("Manager was destroyed. Called by:\n"+new Error("MANAGER_DESTROYED").stack),this.destroyed=!0,this.shardQueue.clear();for(const e of this.shards.values())e.destroy({closeCode:1e3,reset:!0,emit:!1,log:!1})}}async _handleSessionLimit(e,t){if(void 0===e&&void 0===t){const{session_start_limit:i}=await this.client.api.gateway.bot.get();this.sessionStartLimit=i,e=i.remaining,t=i.reset_after,this.debug(`Session Limit Information\n Total: ${i.total}\n Remaining: ${e}`)}e||(this.debug(`Exceeded identify threshold. Will attempt a connection in ${t}ms`),await f.delayFor(t))}handlePacket(e,t){if(e&&this.status!==h.READY&&!p.includes(e.t))return this.packetQueue.push({packet:e,shard:t}),!1;if(this.packetQueue.length){const e=this.packetQueue.shift();this.client.setImmediate((()=>{this.handlePacket(e.packet,e.shard)}))}return e&&r[e.t]&&r[e.t](this.client,e,t),!0}async checkShardsReady(){if(this.status!==h.READY&&this.shards.size===this.totalShards&&!this.shards.some((e=>e.status!==h.READY))){if(this.status=h.NEARLY,this.client.options.fetchAllMembers)try{const e=this.client.guilds.cache.map((e=>e.available?e.members.fetch():Promise.resolve()));await Promise.all(e)}catch(e){this.debug(`Failed to fetch all members before ready! ${e}\n${e.stack}`)}this.triggerClientReady()}}triggerClientReady(){this.status=h.READY,this.client.readyAt=new Date,this.client.emit(c.CLIENT_READY),this.handlePacket()}}},function(e,t,i){"use strict";const s=i(16),n=i(95),{browser:r,Status:o,Events:a,ShardEvents:c,OPCodes:l,WSEvents:h}=i(0),u=Object.keys(o),d=Object.keys(n.WebSocket);let f;if(!r)try{f=i(172)}catch{}e.exports=class WebSocketShard extends s{constructor(e,t){super(),this.manager=e,this.id=t,this.status=o.IDLE,this.sequence=-1,this.closeSequence=0,this.sessionID=null,this.ping=-1,this.lastPingTimestamp=-1,this.lastHeartbeatAcked=!0,Object.defineProperty(this,"ratelimit",{value:{queue:[],total:120,remaining:120,time:6e4,timer:null}}),Object.defineProperty(this,"connection",{value:null,writable:!0}),Object.defineProperty(this,"inflate",{value:null,writable:!0}),Object.defineProperty(this,"helloTimeout",{value:null,writable:!0}),Object.defineProperty(this,"eventsAttached",{value:!1,writable:!0}),Object.defineProperty(this,"expectedGuilds",{value:null,writable:!0}),Object.defineProperty(this,"readyTimeout",{value:null,writable:!0}),Object.defineProperty(this,"connectedAt",{value:0,writable:!0})}debug(e){this.manager.debug(e,this)}connect(){const{gateway:e,client:t}=this.manager;return this.connection&&this.connection.readyState===n.OPEN&&this.status===o.READY?Promise.resolve():new Promise(((i,s)=>{const cleanup=()=>{this.removeListener(c.CLOSE,onClose),this.removeListener(c.READY,onReady),this.removeListener(c.RESUMED,onResumed),this.removeListener(c.INVALID_SESSION,onInvalidOrDestroyed),this.removeListener(c.DESTROYED,onInvalidOrDestroyed)},onReady=()=>{cleanup(),i()},onResumed=()=>{cleanup(),i()},onClose=e=>{cleanup(),s(e)},onInvalidOrDestroyed=()=>{cleanup(),s()};if(this.once(c.READY,onReady),this.once(c.RESUMED,onResumed),this.once(c.CLOSE,onClose),this.once(c.INVALID_SESSION,onInvalidOrDestroyed),this.once(c.DESTROYED,onInvalidOrDestroyed),this.connection&&this.connection.readyState===n.OPEN)return this.debug("An open connection was found, attempting an immediate identify."),void this.identify();this.connection&&(this.debug("A connection object was found. Cleaning up before continuing.\n State: "+d[this.connection.readyState]),this.destroy({emit:!1}));const r={v:t.options.ws.version};f&&(this.inflate=new f.Inflate({chunkSize:65535,flush:f.Z_SYNC_FLUSH,to:"json"===n.encoding?"string":""}),r.compress="zlib-stream"),this.debug(`[CONNECT]\n Gateway : ${e}\n Version : ${t.options.ws.version}\n Encoding : ${n.encoding}\n Compression: ${f?"zlib-stream":"none"}`),this.status=this.status===o.DISCONNECTED?o.RECONNECTING:o.CONNECTING,this.setHelloTimeout(),this.connectedAt=Date.now();const a=this.connection=n.create(e,r);a.onopen=this.onOpen.bind(this),a.onmessage=this.onMessage.bind(this),a.onerror=this.onError.bind(this),a.onclose=this.onClose.bind(this)}))}onOpen(){this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now()-this.connectedAt}ms`),this.status=o.NEARLY}onMessage({data:e}){let t,i;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),f){const i=e.length,s=i>=4&&0===e[i-4]&&0===e[i-3]&&255===e[i-2]&&255===e[i-1];if(this.inflate.push(e,s&&f.Z_SYNC_FLUSH),!s)return;t=this.inflate.result}else t=e;try{i=n.unpack(t),this.manager.client.emit(a.RAW,i,this.id),i.op===l.DISPATCH&&this.manager.emit(i.t,i.d,this.id)}catch(e){return void this.manager.client.emit(a.SHARD_ERROR,e,this.id)}this.onPacket(i)}onError(e){const t=e&&e.error?e.error:e;t&&this.manager.client.emit(a.SHARD_ERROR,t,this.id)}onClose(e){-1!==this.sequence&&(this.closeSequence=this.sequence),this.sequence=-1,this.debug(`[CLOSE]\n Event Code: ${e.code}\n Clean : ${e.wasClean}\n Reason : ${e.reason||"No reason received"}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection&&this._cleanupConnection(),this.status=o.DISCONNECTED,this.emit(c.CLOSE,e)}onPacket(e){if(e){switch(e.t){case h.READY:this.emit(c.READY),this.sessionID=e.d.session_id,this.expectedGuilds=new Set(e.d.guilds.map((e=>e.id))),this.status=o.WAITING_FOR_GUILDS,this.debug(`[READY] Session ${this.sessionID}.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ReadyHeartbeat");break;case h.RESUMED:{this.emit(c.RESUMED),this.status=o.READY;const t=e.s-this.closeSequence;this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${t} events.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ResumeHeartbeat");break}}switch(e.s>this.sequence&&(this.sequence=e.s),e.op){case l.HELLO:this.setHelloTimeout(-1),this.setHeartbeatTimer(e.d.heartbeat_interval),this.identify();break;case l.RECONNECT:this.debug("[RECONNECT] Discord asked us to reconnect"),this.destroy({closeCode:4e3});break;case l.INVALID_SESSION:if(this.debug(`[INVALID SESSION] Resumable: ${e.d}.`),e.d)return void this.identifyResume();this.sequence=-1,this.sessionID=null,this.status=o.RECONNECTING,this.emit(c.INVALID_SESSION);break;case l.HEARTBEAT_ACK:this.ackHeartbeat();break;case l.HEARTBEAT:this.sendHeartbeat("HeartbeatRequest",!0);break;default:this.manager.handlePacket(e,this),this.status===o.WAITING_FOR_GUILDS&&e.t===h.GUILD_CREATE&&(this.expectedGuilds.delete(e.d.id),this.checkReady())}}else this.debug(`Received broken packet: '${e}'.`)}checkReady(){if(this.readyTimeout&&(this.manager.client.clearTimeout(this.readyTimeout),this.readyTimeout=null),!this.expectedGuilds.size)return this.debug("Shard received all its guilds. Marking as fully ready."),this.status=o.READY,void this.emit(c.ALL_READY);this.readyTimeout=this.manager.client.setTimeout((()=>{this.debug("Shard did not receive any more guild packets in 15 seconds.\n Unavailable guild count: "+this.expectedGuilds.size),this.readyTimeout=null,this.status=o.READY,this.emit(c.ALL_READY,this.expectedGuilds)}),15e3)}setHelloTimeout(e){-1!==e?(this.debug("Setting a HELLO timeout for 20s."),this.helloTimeout=this.manager.client.setTimeout((()=>{this.debug("Did not receive HELLO in time. Destroying and connecting again."),this.destroy({reset:!0,closeCode:4009})}),2e4)):this.helloTimeout&&(this.debug("Clearing the HELLO timeout."),this.manager.client.clearTimeout(this.helloTimeout),this.helloTimeout=null)}setHeartbeatTimer(e){-1!==e?(this.debug(`Setting a heartbeat interval for ${e}ms.`),this.heartbeatInterval&&this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=this.manager.client.setInterval((()=>this.sendHeartbeat()),e)):this.heartbeatInterval&&(this.debug("Clearing the heartbeat interval."),this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=null)}sendHeartbeat(e="HeartbeatTimer",t=[o.WAITING_FOR_GUILDS,o.IDENTIFYING,o.RESUMING].includes(this.status)){if(t&&!this.lastHeartbeatAcked)this.debug(`[${e}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);else if(!this.lastHeartbeatAcked)return this.debug(`[${e}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.\n Status : ${u[this.status]}\n Sequence : ${this.sequence}\n Connection State: ${this.connection?d[this.connection.readyState]:"No Connection??"}`),void this.destroy({closeCode:4009,reset:!0});this.debug(`[${e}] Sending a heartbeat.`),this.lastHeartbeatAcked=!1,this.lastPingTimestamp=Date.now(),this.send({op:l.HEARTBEAT,d:this.sequence},!0)}ackHeartbeat(){this.lastHeartbeatAcked=!0;const e=Date.now()-this.lastPingTimestamp;this.debug(`Heartbeat acknowledged, latency of ${e}ms.`),this.ping=e}identify(){return this.sessionID?this.identifyResume():this.identifyNew()}identifyNew(){const{client:e}=this.manager;if(!e.token)return void this.debug("[IDENTIFY] No token available to identify a new session.");this.status=o.IDENTIFYING;const t={...e.options.ws,token:e.token,shard:[this.id,Number(e.options.shardCount)]};this.debug(`[IDENTIFY] Shard ${this.id}/${e.options.shardCount}`),this.send({op:l.IDENTIFY,d:t},!0)}identifyResume(){if(!this.sessionID)return this.debug("[RESUME] No session ID was present; identifying as a new session."),void this.identifyNew();this.status=o.RESUMING,this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`);const e={token:this.manager.client.token,session_id:this.sessionID,seq:this.closeSequence};this.send({op:l.RESUME,d:e},!0)}send(e,t=!1){this.ratelimit.queue[t?"unshift":"push"](e),this.processQueue()}_send(e){if(!this.connection||this.connection.readyState!==n.OPEN)return this.debug(`Tried to send packet '${JSON.stringify(e)}' but no WebSocket is available!`),void this.destroy({close:4e3});this.connection.send(n.pack(e),(e=>{e&&this.manager.client.emit(a.SHARD_ERROR,e,this.id)}))}processQueue(){if(0!==this.ratelimit.remaining&&0!==this.ratelimit.queue.length)for(this.ratelimit.remaining===this.ratelimit.total&&(this.ratelimit.timer=this.manager.client.setTimeout((()=>{this.ratelimit.remaining=this.ratelimit.total,this.processQueue()}),this.ratelimit.time));this.ratelimit.remaining>0;){const e=this.ratelimit.queue.shift();if(!e)return;this._send(e),this.ratelimit.remaining--}}destroy({closeCode:e=1e3,reset:t=!1,emit:i=!0,log:s=!0}={}){if(s&&this.debug(`[DESTROY]\n Close Code : ${e}\n Reset : ${t}\n Emit DESTROYED: ${i}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection)if(this.connection.readyState===n.OPEN)this.connection.close(e);else{this.debug("WS State: "+d[this.connection.readyState]),this._cleanupConnection();try{this.connection.close(e)}catch{}i&&this._emitDestroyed()}else i&&this._emitDestroyed();this.connection=null,this.status=o.DISCONNECTED,-1!==this.sequence&&(this.closeSequence=this.sequence),t&&(this.sequence=-1,this.sessionID=null),this.ratelimit.remaining=this.ratelimit.total,this.ratelimit.queue.length=0,this.ratelimit.timer&&(this.manager.client.clearTimeout(this.ratelimit.timer),this.ratelimit.timer=null)}_cleanupConnection(){this.connection.onopen=this.connection.onclose=this.connection.onerror=this.connection.onmessage=null}_emitDestroyed(){this.emit(c.DESTROYED)}}},function(e,t){},function(e,t){},function(e,t){},function(e,t,i){var s={"./CHANNEL_CREATE.js":174,"./CHANNEL_DELETE.js":175,"./CHANNEL_PINS_UPDATE.js":176,"./CHANNEL_UPDATE.js":177,"./GUILD_BAN_ADD.js":178,"./GUILD_BAN_REMOVE.js":179,"./GUILD_CREATE.js":180,"./GUILD_DELETE.js":181,"./GUILD_EMOJIS_UPDATE.js":182,"./GUILD_INTEGRATIONS_UPDATE.js":183,"./GUILD_MEMBERS_CHUNK.js":184,"./GUILD_MEMBER_ADD.js":185,"./GUILD_MEMBER_REMOVE.js":186,"./GUILD_MEMBER_UPDATE.js":187,"./GUILD_ROLE_CREATE.js":188,"./GUILD_ROLE_DELETE.js":189,"./GUILD_ROLE_UPDATE.js":190,"./GUILD_UPDATE.js":191,"./INVITE_CREATE.js":192,"./INVITE_DELETE.js":193,"./MESSAGE_CREATE.js":194,"./MESSAGE_DELETE.js":195,"./MESSAGE_DELETE_BULK.js":196,"./MESSAGE_REACTION_ADD.js":197,"./MESSAGE_REACTION_REMOVE.js":198,"./MESSAGE_REACTION_REMOVE_ALL.js":199,"./MESSAGE_REACTION_REMOVE_EMOJI.js":200,"./MESSAGE_UPDATE.js":201,"./PRESENCE_UPDATE.js":202,"./READY.js":203,"./RESUMED.js":204,"./TYPING_START.js":205,"./USER_UPDATE.js":206,"./VOICE_SERVER_UPDATE.js":207,"./VOICE_STATE_UPDATE.js":208,"./WEBHOOKS_UPDATE.js":209,"./index.js":96};function webpackContext(e){var t=webpackContextResolve(e);return i(t)}function webpackContextResolve(e){if(!i.o(s,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return s[e]}webpackContext.keys=function webpackContextKeys(){return Object.keys(s)},webpackContext.resolve=webpackContextResolve,e.exports=webpackContext,webpackContext.id=173},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelDelete.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.channels.cache.get(t.channel_id),n=new Date(t.last_pin_timestamp);i&&!Number.isNaN(n.getTime())&&(i.lastPinTimestamp=n.getTime()||null,e.emit(s.CHANNEL_PINS_UPDATE,i,n))}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.ChannelUpdate.handle(t.d);i&&n&&e.emit(s.CHANNEL_UPDATE,i,n)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id),n=e.users.add(t.user);i&&n&&e.emit(s.GUILD_BAN_ADD,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildBanRemove.handle(t.d)}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=async(e,{d:t},i)=>{let r=e.guilds.cache.get(t.id);r?r.available||t.unavailable||(r._patch(t),e.ws.status===n.READY&&e.options.fetchAllMembers&&await r.members.fetch().catch((t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`)))):(t.shardID=i.id,r=e.guilds.add(t),e.ws.status===n.READY&&(e.options.fetchAllMembers&&await r.members.fetch().catch((t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`))),e.emit(s.GUILD_CREATE,r)))}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildEmojisUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildIntegrationsUpdate.handle(t.d)}},function(e,t,i){"use strict";const s=i(3),{Events:n}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id);if(!i)return;const r=new s;for(const e of t.members)r.set(e.user.id,i.members.add(e));if(t.presences)for(const e of t.presences)i.presences.add(Object.assign(e,{guild:i}));e.emit(n.GUILD_MEMBERS_CHUNK,r,i,{count:t.chunk_count,index:t.chunk_index,nonce:t.nonce})}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=(e,{d:t},i)=>{const r=e.guilds.cache.get(t.guild_id);if(r){r.memberCount++;const o=r.members.add(t);i.status===n.READY&&e.emit(s.GUILD_MEMBER_ADD,o)}}},function(e,t,i){"use strict";e.exports=(e,t,i)=>{e.actions.GuildMemberRemove.handle(t.d,i)}},function(e,t,i){"use strict";e.exports=(e,t,i)=>{e.actions.GuildMemberUpdate.handle(t.d,i)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDeleteBulk.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionAdd.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemove.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveAll.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveEmoji.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.MessageUpdate.handle(t.d);i&&n&&e.emit(s.MESSAGE_UPDATE,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.PresenceUpdate.handle(t.d)}},function(e,t,i){"use strict";let s;e.exports=(e,{d:t},n)=>{if(e.user)e.user._patch(t.user);else{s||(s=i(97));const n=new s(e,t.user);e.user=n,e.users.cache.set(n.id,n)}for(const i of t.guilds)i.shardID=n.id,e.guilds.add(i);n.checkReady()}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t,i)=>{const n=i.sequence-i.closeSequence;e.emit(s.SHARD_RESUME,i.id,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.TypingStart.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.UserUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.emit("debug","[VOICE] received voice server: "+JSON.stringify(t)),e.voice.onVoiceServer(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.VoiceStateUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.WebhooksUpdate.handle(t.d)}},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t,i){"use strict";const s=i(12);class Speaking extends s{}Speaking.FLAGS={SPEAKING:1,SOUNDSHARE:2,PRIORITY_SPEAKING:4},e.exports=Speaking}])})); \ No newline at end of file diff --git a/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt b/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt new file mode 100644 index 0000000..e874b73 --- /dev/null +++ b/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt @@ -0,0 +1,6 @@ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ diff --git a/node_modules/end-of-stream/LICENSE b/node_modules/end-of-stream/LICENSE new file mode 100644 index 0000000..757562e --- /dev/null +++ b/node_modules/end-of-stream/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/end-of-stream/README.md b/node_modules/end-of-stream/README.md new file mode 100644 index 0000000..857b14b --- /dev/null +++ b/node_modules/end-of-stream/README.md @@ -0,0 +1,54 @@ +# end-of-stream + +A node module that calls a callback when a readable/writable/duplex stream has completed or failed. + + npm install end-of-stream + +[![Build status](https://travis-ci.org/mafintosh/end-of-stream.svg?branch=master)](https://travis-ci.org/mafintosh/end-of-stream) + +## Usage + +Simply pass a stream and a callback to the `eos`. +Both legacy streams, streams2 and stream3 are supported. + +``` js +var eos = require('end-of-stream'); + +eos(readableStream, function(err) { + // this will be set to the stream instance + if (err) return console.log('stream had an error or closed early'); + console.log('stream has ended', this === readableStream); +}); + +eos(writableStream, function(err) { + if (err) return console.log('stream had an error or closed early'); + console.log('stream has finished', this === writableStream); +}); + +eos(duplexStream, function(err) { + if (err) return console.log('stream had an error or closed early'); + console.log('stream has ended and finished', this === duplexStream); +}); + +eos(duplexStream, {readable:false}, function(err) { + if (err) return console.log('stream had an error or closed early'); + console.log('stream has finished but might still be readable'); +}); + +eos(duplexStream, {writable:false}, function(err) { + if (err) return console.log('stream had an error or closed early'); + console.log('stream has ended but might still be writable'); +}); + +eos(readableStream, {error:false}, function(err) { + // do not treat emit('error', err) as a end-of-stream +}); +``` + +## License + +MIT + +## Related + +`end-of-stream` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one. diff --git a/node_modules/end-of-stream/index.js b/node_modules/end-of-stream/index.js new file mode 100644 index 0000000..c77f0d5 --- /dev/null +++ b/node_modules/end-of-stream/index.js @@ -0,0 +1,94 @@ +var once = require('once'); + +var noop = function() {}; + +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; + +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; + +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + + callback = once(callback || noop); + + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + var cancelled = false; + + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; + + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; + + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + + var onerror = function(err) { + callback.call(stream, err); + }; + + var onclose = function() { + process.nextTick(onclosenexttick); + }; + + var onclosenexttick = function() { + if (cancelled) return; + if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); + }; + + var onrequest = function() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + if (isChildProcess(stream)) stream.on('exit', onexit); + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + + return function() { + cancelled = true; + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; + +module.exports = eos; diff --git a/node_modules/end-of-stream/package.json b/node_modules/end-of-stream/package.json new file mode 100644 index 0000000..b75bbf0 --- /dev/null +++ b/node_modules/end-of-stream/package.json @@ -0,0 +1,37 @@ +{ + "name": "end-of-stream", + "version": "1.4.4", + "description": "Call a callback when a readable/writable/duplex stream has completed or failed.", + "repository": { + "type": "git", + "url": "git://github.com/mafintosh/end-of-stream.git" + }, + "dependencies": { + "once": "^1.4.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "stream", + "streams", + "callback", + "finish", + "close", + "end", + "wait" + ], + "bugs": { + "url": "https://github.com/mafintosh/end-of-stream/issues" + }, + "homepage": "https://github.com/mafintosh/end-of-stream", + "main": "index.js", + "author": "Mathias Buus ", + "license": "MIT", + "devDependencies": { + "tape": "^4.11.0" + } +} diff --git a/node_modules/event-target-shim/LICENSE b/node_modules/event-target-shim/LICENSE new file mode 100644 index 0000000..c39e694 --- /dev/null +++ b/node_modules/event-target-shim/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Toru Nagashima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/event-target-shim/README.md b/node_modules/event-target-shim/README.md new file mode 100644 index 0000000..a4f9c1b --- /dev/null +++ b/node_modules/event-target-shim/README.md @@ -0,0 +1,293 @@ +# event-target-shim + +[![npm version](https://img.shields.io/npm/v/event-target-shim.svg)](https://www.npmjs.com/package/event-target-shim) +[![Downloads/month](https://img.shields.io/npm/dm/event-target-shim.svg)](http://www.npmtrends.com/event-target-shim) +[![Build Status](https://travis-ci.org/mysticatea/event-target-shim.svg?branch=master)](https://travis-ci.org/mysticatea/event-target-shim) +[![Coverage Status](https://codecov.io/gh/mysticatea/event-target-shim/branch/master/graph/badge.svg)](https://codecov.io/gh/mysticatea/event-target-shim) +[![Dependency Status](https://david-dm.org/mysticatea/event-target-shim.svg)](https://david-dm.org/mysticatea/event-target-shim) + +An implementation of [WHATWG EventTarget interface](https://dom.spec.whatwg.org/#interface-eventtarget), plus few extensions. + +- This provides `EventTarget` constructor that can inherit for your custom object. +- This provides an utility that defines properties of attribute listeners (e.g. `obj.onclick`). + +```js +import {EventTarget, defineEventAttribute} from "event-target-shim" + +class Foo extends EventTarget { + // ... +} + +// Define `foo.onhello` property. +defineEventAttribute(Foo.prototype, "hello") + +// Use +const foo = new Foo() +foo.addEventListener("hello", e => console.log("hello", e)) +foo.onhello = e => console.log("onhello:", e) +foo.dispatchEvent(new CustomEvent("hello")) +``` + +## 💿 Installation + +Use [npm](https://www.npmjs.com/) to install then use a bundler. + +``` +npm install event-target-shim +``` + +Or download from [`dist` directory](./dist). + +- [dist/event-target-shim.mjs](dist/event-target-shim.mjs) ... ES modules version. +- [dist/event-target-shim.js](dist/event-target-shim.js) ... Common JS version. +- [dist/event-target-shim.umd.js](dist/event-target-shim.umd.js) ... UMD (Universal Module Definition) version. This is transpiled by [Babel](https://babeljs.io/) for IE 11. + +## 📖 Usage + +```js +import {EventTarget, defineEventAttribute} from "event-target-shim" +// or +const {EventTarget, defineEventAttribute} = require("event-target-shim") + +// or UMD version defines a global variable: +const {EventTarget, defineEventAttribute} = window.EventTargetShim +``` + +### EventTarget + +> https://dom.spec.whatwg.org/#interface-eventtarget + +#### eventTarget.addEventListener(type, callback, options) + +Register an event listener. + +- `type` is a string. This is the event name to register. +- `callback` is a function. This is the event listener to register. +- `options` is a boolean or an object `{ capture?: boolean, passive?: boolean, once?: boolean }`. If this is a boolean, it's same meaning as `{ capture: options }`. + - `capture` is the flag to register the event listener for capture phase. + - `passive` is the flag to ignore `event.preventDefault()` method in the event listener. + - `once` is the flag to remove the event listener automatically after the first call. + +#### eventTarget.removeEventListener(type, callback, options) + +Unregister an event listener. + +- `type` is a string. This is the event name to unregister. +- `callback` is a function. This is the event listener to unregister. +- `options` is a boolean or an object `{ capture?: boolean }`. If this is a boolean, it's same meaning as `{ capture: options }`. + - `capture` is the flag to register the event listener for capture phase. + +#### eventTarget.dispatchEvent(event) + +Dispatch an event. + +- `event` is a [Event](https://dom.spec.whatwg.org/#event) object or an object `{ type: string, [key: string]: any }`. The latter is non-standard but useful. In both cases, listeners receive the event as implementing [Event](https://dom.spec.whatwg.org/#event) interface. + +### defineEventAttribute(proto, type) + +Define an event attribute (e.g. `onclick`) to `proto`. This is non-standard. + +- `proto` is an object (assuming it's a prototype object). This function defines a getter/setter pair for the event attribute. +- `type` is a string. This is the event name to define. + +For example: + +```js +class AbortSignal extends EventTarget { + constructor() { + this.aborted = false + } +} +// Define `onabort` property. +defineEventAttribute(AbortSignal.prototype, "abort") +``` + +### EventTarget(types) + +Define a custom `EventTarget` class with event attributes. This is non-standard. + +- `types` is a string or an array of strings. This is the event name to define. + +For example: + +```js +// This has `onabort` property. +class AbortSignal extends EventTarget("abort") { + constructor() { + this.aborted = false + } +} +``` + +## 📚 Examples + +### ES2015 and later + +> https://jsfiddle.net/636vea92/ + +```js +const {EventTarget, defineEventAttribute} = EventTargetShim + +// Define a derived class. +class Foo extends EventTarget { + // ... +} + +// Define `foo.onhello` property. +defineEventAttribute(Foo.prototype, "hello") + +// Register event listeners. +const foo = new Foo() +foo.addEventListener("hello", (e) => { + console.log("hello", e) +}) +foo.onhello = (e) => { + console.log("onhello", e) +} + +// Dispatching events +foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" })) +``` + +### Typescript + +```ts +import { EventTarget, defineEventAttribute } from "event-target-shim"; + +// Define events +type FooEvents = { + hello: CustomEvent +} +type FooEventAttributes = { + onhello: CustomEvent +} + +// Define a derived class. +class Foo extends EventTarget { + // ... +} +// Define `foo.onhello` property's implementation. +defineEventAttribute(Foo.prototype, "hello") + +// Register event listeners. +const foo = new Foo() +foo.addEventListener("hello", (e) => { + console.log("hello", e.detail) +}) +foo.onhello = (e) => { + console.log("onhello", e.detail) +} + +// Dispatching events +foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" })) +``` + +Unfortunately, both `FooEvents` and `FooEventAttributes` are needed because TypeScript doesn't allow the mutation of string literal types. If TypeScript allowed us to compute `"onhello"` from `"hello"` in types, `FooEventAttributes` will be optional. + +This `EventTarget` type is compatible with `EventTarget` interface of `lib.dom.d.ts`. + +#### To disallow unknown events + +By default, methods such as `addEventListener` accept unknown events. You can disallow unknown events by the third type parameter `"strict"`. + +```ts +type FooEvents = { + hello: CustomEvent +} +class Foo extends EventTarget { + // ... +} + +// OK because `hello` is defined in FooEvents. +foo.addEventListener("hello", (e) => { +}) +// Error because `unknown` is not defined in FooEvents. +foo.addEventListener("unknown", (e) => { +}) +``` + +However, if you use `"strict"` parameter, it loses compatibility with `EventTarget` interface of `lib.dom.d.ts`. + +#### To infer the type of `dispatchEvent()` method + +TypeScript cannot infer the event type of `dispatchEvent()` method properly from the argument in most cases. You can improve this behavior with the following steps: + +1. Use the third type parameter `"strict"`. This prevents inferring to `dispatchEvent()`. +2. Make the `type` property of event definitions stricter. + +```ts +type FooEvents = { + hello: CustomEvent & { type: "hello" } + hey: Event & { type: "hey" } +} +class Foo extends EventTarget { + // ... +} + +// Error because `detail` property is lacking. +foo.dispatchEvent({ type: "hello" }) +``` + +### ES5 + +> https://jsfiddle.net/522zc9de/ + +```js +// Define a derived class. +function Foo() { + EventTarget.call(this) +} +Foo.prototype = Object.create(EventTarget.prototype, { + constructor: { value: Foo, configurable: true, writable: true } + // ... +}) + +// Define `foo.onhello` property. +defineEventAttribute(Foo.prototype, "hello") + +// Register event listeners. +var foo = new Foo() +foo.addEventListener("hello", function(e) { + console.log("hello", e) +}) +foo.onhello = function(e) { + console.log("onhello", e) +} + +// Dispatching events +function isSupportEventConstrucor() { // IE does not support. + try { + new CusomEvent("hello") + return true + } catch (_err) { + return false + } +} +if (isSupportEventConstrucor()) { + foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" })) +} else { + var e = document.createEvent("CustomEvent") + e.initCustomEvent("hello", false, false, "detail") + foo.dispatchEvent(e) +} +``` + +## 📰 Changelog + +- See [GitHub releases](https://github.com/mysticatea/event-target-shim/releases). + +## 🍻 Contributing + +Contributing is welcome ❤️ + +Please use GitHub issues/PRs. + +### Development tools + +- `npm install` installs dependencies for development. +- `npm test` runs tests and measures code coverage. +- `npm run clean` removes temporary files of tests. +- `npm run coverage` opens code coverage of the previous test with your default browser. +- `npm run lint` runs ESLint. +- `npm run build` generates `dist` codes. +- `npm run watch` runs tests on each file change. diff --git a/node_modules/event-target-shim/dist/event-target-shim.js b/node_modules/event-target-shim/dist/event-target-shim.js new file mode 100644 index 0000000..53ce220 --- /dev/null +++ b/node_modules/event-target-shim/dist/event-target-shim.js @@ -0,0 +1,871 @@ +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +/** + * @typedef {object} PrivateData + * @property {EventTarget} eventTarget The event target. + * @property {{type:string}} event The original event object. + * @property {number} eventPhase The current event phase. + * @property {EventTarget|null} currentTarget The current event target. + * @property {boolean} canceled The flag to prevent default. + * @property {boolean} stopped The flag to stop propagation. + * @property {boolean} immediateStopped The flag to stop propagation immediately. + * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null. + * @property {number} timeStamp The unix time. + * @private + */ + +/** + * Private data for event wrappers. + * @type {WeakMap} + * @private + */ +const privateData = new WeakMap(); + +/** + * Cache for wrapper classes. + * @type {WeakMap} + * @private + */ +const wrappers = new WeakMap(); + +/** + * Get private data. + * @param {Event} event The event object to get private data. + * @returns {PrivateData} The private data of the event. + * @private + */ +function pd(event) { + const retv = privateData.get(event); + console.assert( + retv != null, + "'this' is expected an Event object, but got", + event + ); + return retv +} + +/** + * https://dom.spec.whatwg.org/#set-the-canceled-flag + * @param data {PrivateData} private data. + */ +function setCancelFlag(data) { + if (data.passiveListener != null) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error( + "Unable to preventDefault inside passive event listener invocation.", + data.passiveListener + ); + } + return + } + if (!data.event.cancelable) { + return + } + + data.canceled = true; + if (typeof data.event.preventDefault === "function") { + data.event.preventDefault(); + } +} + +/** + * @see https://dom.spec.whatwg.org/#interface-event + * @private + */ +/** + * The event wrapper. + * @constructor + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Event|{type:string}} event The original event to wrap. + */ +function Event(eventTarget, event) { + privateData.set(this, { + eventTarget, + event, + eventPhase: 2, + currentTarget: eventTarget, + canceled: false, + stopped: false, + immediateStopped: false, + passiveListener: null, + timeStamp: event.timeStamp || Date.now(), + }); + + // https://heycam.github.io/webidl/#Unforgeable + Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); + + // Define accessors + const keys = Object.keys(event); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in this)) { + Object.defineProperty(this, key, defineRedirectDescriptor(key)); + } + } +} + +// Should be enumerable, but class methods are not enumerable. +Event.prototype = { + /** + * The type of this event. + * @type {string} + */ + get type() { + return pd(this).event.type + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get target() { + return pd(this).eventTarget + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get currentTarget() { + return pd(this).currentTarget + }, + + /** + * @returns {EventTarget[]} The composed path of this event. + */ + composedPath() { + const currentTarget = pd(this).currentTarget; + if (currentTarget == null) { + return [] + } + return [currentTarget] + }, + + /** + * Constant of NONE. + * @type {number} + */ + get NONE() { + return 0 + }, + + /** + * Constant of CAPTURING_PHASE. + * @type {number} + */ + get CAPTURING_PHASE() { + return 1 + }, + + /** + * Constant of AT_TARGET. + * @type {number} + */ + get AT_TARGET() { + return 2 + }, + + /** + * Constant of BUBBLING_PHASE. + * @type {number} + */ + get BUBBLING_PHASE() { + return 3 + }, + + /** + * The target of this event. + * @type {number} + */ + get eventPhase() { + return pd(this).eventPhase + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopPropagation() { + const data = pd(this); + + data.stopped = true; + if (typeof data.event.stopPropagation === "function") { + data.event.stopPropagation(); + } + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopImmediatePropagation() { + const data = pd(this); + + data.stopped = true; + data.immediateStopped = true; + if (typeof data.event.stopImmediatePropagation === "function") { + data.event.stopImmediatePropagation(); + } + }, + + /** + * The flag to be bubbling. + * @type {boolean} + */ + get bubbles() { + return Boolean(pd(this).event.bubbles) + }, + + /** + * The flag to be cancelable. + * @type {boolean} + */ + get cancelable() { + return Boolean(pd(this).event.cancelable) + }, + + /** + * Cancel this event. + * @returns {void} + */ + preventDefault() { + setCancelFlag(pd(this)); + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + */ + get defaultPrevented() { + return pd(this).canceled + }, + + /** + * The flag to be composed. + * @type {boolean} + */ + get composed() { + return Boolean(pd(this).event.composed) + }, + + /** + * The unix time of this event. + * @type {number} + */ + get timeStamp() { + return pd(this).timeStamp + }, + + /** + * The target of this event. + * @type {EventTarget} + * @deprecated + */ + get srcElement() { + return pd(this).eventTarget + }, + + /** + * The flag to stop event bubbling. + * @type {boolean} + * @deprecated + */ + get cancelBubble() { + return pd(this).stopped + }, + set cancelBubble(value) { + if (!value) { + return + } + const data = pd(this); + + data.stopped = true; + if (typeof data.event.cancelBubble === "boolean") { + data.event.cancelBubble = true; + } + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + * @deprecated + */ + get returnValue() { + return !pd(this).canceled + }, + set returnValue(value) { + if (!value) { + setCancelFlag(pd(this)); + } + }, + + /** + * Initialize this event object. But do nothing under event dispatching. + * @param {string} type The event type. + * @param {boolean} [bubbles=false] The flag to be possible to bubble up. + * @param {boolean} [cancelable=false] The flag to be possible to cancel. + * @deprecated + */ + initEvent() { + // Do nothing. + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(Event.prototype, "constructor", { + value: Event, + configurable: true, + writable: true, +}); + +// Ensure `event instanceof window.Event` is `true`. +if (typeof window !== "undefined" && typeof window.Event !== "undefined") { + Object.setPrototypeOf(Event.prototype, window.Event.prototype); + + // Make association for wrappers. + wrappers.set(window.Event.prototype, Event); +} + +/** + * Get the property descriptor to redirect a given property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to redirect the property. + * @private + */ +function defineRedirectDescriptor(key) { + return { + get() { + return pd(this).event[key] + }, + set(value) { + pd(this).event[key] = value; + }, + configurable: true, + enumerable: true, + } +} + +/** + * Get the property descriptor to call a given method property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to call the method property. + * @private + */ +function defineCallDescriptor(key) { + return { + value() { + const event = pd(this).event; + return event[key].apply(event, arguments) + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define new wrapper class. + * @param {Function} BaseEvent The base wrapper class. + * @param {Object} proto The prototype of the original event. + * @returns {Function} The defined wrapper class. + * @private + */ +function defineWrapper(BaseEvent, proto) { + const keys = Object.keys(proto); + if (keys.length === 0) { + return BaseEvent + } + + /** CustomEvent */ + function CustomEvent(eventTarget, event) { + BaseEvent.call(this, eventTarget, event); + } + + CustomEvent.prototype = Object.create(BaseEvent.prototype, { + constructor: { value: CustomEvent, configurable: true, writable: true }, + }); + + // Define accessors. + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in BaseEvent.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(proto, key); + const isFunc = typeof descriptor.value === "function"; + Object.defineProperty( + CustomEvent.prototype, + key, + isFunc + ? defineCallDescriptor(key) + : defineRedirectDescriptor(key) + ); + } + } + + return CustomEvent +} + +/** + * Get the wrapper class of a given prototype. + * @param {Object} proto The prototype of the original event to get its wrapper. + * @returns {Function} The wrapper class. + * @private + */ +function getWrapper(proto) { + if (proto == null || proto === Object.prototype) { + return Event + } + + let wrapper = wrappers.get(proto); + if (wrapper == null) { + wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto); + wrappers.set(proto, wrapper); + } + return wrapper +} + +/** + * Wrap a given event to management a dispatching. + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Object} event The event to wrap. + * @returns {Event} The wrapper instance. + * @private + */ +function wrapEvent(eventTarget, event) { + const Wrapper = getWrapper(Object.getPrototypeOf(event)); + return new Wrapper(eventTarget, event) +} + +/** + * Get the immediateStopped flag of a given event. + * @param {Event} event The event to get. + * @returns {boolean} The flag to stop propagation immediately. + * @private + */ +function isStopped(event) { + return pd(event).immediateStopped +} + +/** + * Set the current event phase of a given event. + * @param {Event} event The event to set current target. + * @param {number} eventPhase New event phase. + * @returns {void} + * @private + */ +function setEventPhase(event, eventPhase) { + pd(event).eventPhase = eventPhase; +} + +/** + * Set the current target of a given event. + * @param {Event} event The event to set current target. + * @param {EventTarget|null} currentTarget New current target. + * @returns {void} + * @private + */ +function setCurrentTarget(event, currentTarget) { + pd(event).currentTarget = currentTarget; +} + +/** + * Set a passive listener of a given event. + * @param {Event} event The event to set current target. + * @param {Function|null} passiveListener New passive listener. + * @returns {void} + * @private + */ +function setPassiveListener(event, passiveListener) { + pd(event).passiveListener = passiveListener; +} + +/** + * @typedef {object} ListenerNode + * @property {Function} listener + * @property {1|2|3} listenerType + * @property {boolean} passive + * @property {boolean} once + * @property {ListenerNode|null} next + * @private + */ + +/** + * @type {WeakMap>} + * @private + */ +const listenersMap = new WeakMap(); + +// Listener types +const CAPTURE = 1; +const BUBBLE = 2; +const ATTRIBUTE = 3; + +/** + * Check whether a given value is an object or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if the value is an object. + */ +function isObject(x) { + return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax +} + +/** + * Get listeners. + * @param {EventTarget} eventTarget The event target to get. + * @returns {Map} The listeners. + * @private + */ +function getListeners(eventTarget) { + const listeners = listenersMap.get(eventTarget); + if (listeners == null) { + throw new TypeError( + "'this' is expected an EventTarget object, but got another value." + ) + } + return listeners +} + +/** + * Get the property descriptor for the event attribute of a given event. + * @param {string} eventName The event name to get property descriptor. + * @returns {PropertyDescriptor} The property descriptor. + * @private + */ +function defineEventAttributeDescriptor(eventName) { + return { + get() { + const listeners = getListeners(this); + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + return node.listener + } + node = node.next; + } + return null + }, + + set(listener) { + if (typeof listener !== "function" && !isObject(listener)) { + listener = null; // eslint-disable-line no-param-reassign + } + const listeners = getListeners(this); + + // Traverse to the tail while removing old value. + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + // Remove old value. + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + node = node.next; + } + + // Add new value. + if (listener !== null) { + const newNode = { + listener, + listenerType: ATTRIBUTE, + passive: false, + once: false, + next: null, + }; + if (prev === null) { + listeners.set(eventName, newNode); + } else { + prev.next = newNode; + } + } + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite. + * @param {string} eventName The event name to define. + * @returns {void} + */ +function defineEventAttribute(eventTargetPrototype, eventName) { + Object.defineProperty( + eventTargetPrototype, + `on${eventName}`, + defineEventAttributeDescriptor(eventName) + ); +} + +/** + * Define a custom EventTarget with event attributes. + * @param {string[]} eventNames Event names for event attributes. + * @returns {EventTarget} The custom EventTarget. + * @private + */ +function defineCustomEventTarget(eventNames) { + /** CustomEventTarget */ + function CustomEventTarget() { + EventTarget.call(this); + } + + CustomEventTarget.prototype = Object.create(EventTarget.prototype, { + constructor: { + value: CustomEventTarget, + configurable: true, + writable: true, + }, + }); + + for (let i = 0; i < eventNames.length; ++i) { + defineEventAttribute(CustomEventTarget.prototype, eventNames[i]); + } + + return CustomEventTarget +} + +/** + * EventTarget. + * + * - This is constructor if no arguments. + * - This is a function which returns a CustomEventTarget constructor if there are arguments. + * + * For example: + * + * class A extends EventTarget {} + * class B extends EventTarget("message") {} + * class C extends EventTarget("message", "error") {} + * class D extends EventTarget(["message", "error"]) {} + */ +function EventTarget() { + /*eslint-disable consistent-return */ + if (this instanceof EventTarget) { + listenersMap.set(this, new Map()); + return + } + if (arguments.length === 1 && Array.isArray(arguments[0])) { + return defineCustomEventTarget(arguments[0]) + } + if (arguments.length > 0) { + const types = new Array(arguments.length); + for (let i = 0; i < arguments.length; ++i) { + types[i] = arguments[i]; + } + return defineCustomEventTarget(types) + } + throw new TypeError("Cannot call a class as a function") + /*eslint-enable consistent-return */ +} + +// Should be enumerable, but class methods are not enumerable. +EventTarget.prototype = { + /** + * Add a given listener to this event target. + * @param {string} eventName The event name to add. + * @param {Function} listener The listener to add. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + addEventListener(eventName, listener, options) { + if (listener == null) { + return + } + if (typeof listener !== "function" && !isObject(listener)) { + throw new TypeError("'listener' should be a function or an object.") + } + + const listeners = getListeners(this); + const optionsIsObj = isObject(options); + const capture = optionsIsObj + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + const newNode = { + listener, + listenerType, + passive: optionsIsObj && Boolean(options.passive), + once: optionsIsObj && Boolean(options.once), + next: null, + }; + + // Set it as the first node if the first node is null. + let node = listeners.get(eventName); + if (node === undefined) { + listeners.set(eventName, newNode); + return + } + + // Traverse to the tail while checking duplication.. + let prev = null; + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + // Should ignore duplication. + return + } + prev = node; + node = node.next; + } + + // Add it. + prev.next = newNode; + }, + + /** + * Remove a given listener from this event target. + * @param {string} eventName The event name to remove. + * @param {Function} listener The listener to remove. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + removeEventListener(eventName, listener, options) { + if (listener == null) { + return + } + + const listeners = getListeners(this); + const capture = isObject(options) + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + return + } + + prev = node; + node = node.next; + } + }, + + /** + * Dispatch a given event. + * @param {Event|{type:string}} event The event to dispatch. + * @returns {boolean} `false` if canceled. + */ + dispatchEvent(event) { + if (event == null || typeof event.type !== "string") { + throw new TypeError('"event.type" should be a string.') + } + + // If listeners aren't registered, terminate. + const listeners = getListeners(this); + const eventName = event.type; + let node = listeners.get(eventName); + if (node == null) { + return true + } + + // Since we cannot rewrite several properties, so wrap object. + const wrappedEvent = wrapEvent(this, event); + + // This doesn't process capturing phase and bubbling phase. + // This isn't participating in a tree. + let prev = null; + while (node != null) { + // Remove this listener if it's once + if (node.once) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + // Call this listener + setPassiveListener( + wrappedEvent, + node.passive ? node.listener : null + ); + if (typeof node.listener === "function") { + try { + node.listener.call(this, wrappedEvent); + } catch (err) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error(err); + } + } + } else if ( + node.listenerType !== ATTRIBUTE && + typeof node.listener.handleEvent === "function" + ) { + node.listener.handleEvent(wrappedEvent); + } + + // Break if `event.stopImmediatePropagation` was called. + if (isStopped(wrappedEvent)) { + break + } + + node = node.next; + } + setPassiveListener(wrappedEvent, null); + setEventPhase(wrappedEvent, 0); + setCurrentTarget(wrappedEvent, null); + + return !wrappedEvent.defaultPrevented + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(EventTarget.prototype, "constructor", { + value: EventTarget, + configurable: true, + writable: true, +}); + +// Ensure `eventTarget instanceof window.EventTarget` is `true`. +if ( + typeof window !== "undefined" && + typeof window.EventTarget !== "undefined" +) { + Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype); +} + +exports.defineEventAttribute = defineEventAttribute; +exports.EventTarget = EventTarget; +exports.default = EventTarget; + +module.exports = EventTarget +module.exports.EventTarget = module.exports["default"] = EventTarget +module.exports.defineEventAttribute = defineEventAttribute +//# sourceMappingURL=event-target-shim.js.map diff --git a/node_modules/event-target-shim/dist/event-target-shim.js.map b/node_modules/event-target-shim/dist/event-target-shim.js.map new file mode 100644 index 0000000..83c5f62 --- /dev/null +++ b/node_modules/event-target-shim/dist/event-target-shim.js.map @@ -0,0 +1 @@ +{"version":3,"file":"event-target-shim.js","sources":["../src/event.mjs","../src/event-target.mjs"],"sourcesContent":["/**\n * @typedef {object} PrivateData\n * @property {EventTarget} eventTarget The event target.\n * @property {{type:string}} event The original event object.\n * @property {number} eventPhase The current event phase.\n * @property {EventTarget|null} currentTarget The current event target.\n * @property {boolean} canceled The flag to prevent default.\n * @property {boolean} stopped The flag to stop propagation.\n * @property {boolean} immediateStopped The flag to stop propagation immediately.\n * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.\n * @property {number} timeStamp The unix time.\n * @private\n */\n\n/**\n * Private data for event wrappers.\n * @type {WeakMap}\n * @private\n */\nconst privateData = new WeakMap()\n\n/**\n * Cache for wrapper classes.\n * @type {WeakMap}\n * @private\n */\nconst wrappers = new WeakMap()\n\n/**\n * Get private data.\n * @param {Event} event The event object to get private data.\n * @returns {PrivateData} The private data of the event.\n * @private\n */\nfunction pd(event) {\n const retv = privateData.get(event)\n console.assert(\n retv != null,\n \"'this' is expected an Event object, but got\",\n event\n )\n return retv\n}\n\n/**\n * https://dom.spec.whatwg.org/#set-the-canceled-flag\n * @param data {PrivateData} private data.\n */\nfunction setCancelFlag(data) {\n if (data.passiveListener != null) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(\n \"Unable to preventDefault inside passive event listener invocation.\",\n data.passiveListener\n )\n }\n return\n }\n if (!data.event.cancelable) {\n return\n }\n\n data.canceled = true\n if (typeof data.event.preventDefault === \"function\") {\n data.event.preventDefault()\n }\n}\n\n/**\n * @see https://dom.spec.whatwg.org/#interface-event\n * @private\n */\n/**\n * The event wrapper.\n * @constructor\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Event|{type:string}} event The original event to wrap.\n */\nfunction Event(eventTarget, event) {\n privateData.set(this, {\n eventTarget,\n event,\n eventPhase: 2,\n currentTarget: eventTarget,\n canceled: false,\n stopped: false,\n immediateStopped: false,\n passiveListener: null,\n timeStamp: event.timeStamp || Date.now(),\n })\n\n // https://heycam.github.io/webidl/#Unforgeable\n Object.defineProperty(this, \"isTrusted\", { value: false, enumerable: true })\n\n // Define accessors\n const keys = Object.keys(event)\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in this)) {\n Object.defineProperty(this, key, defineRedirectDescriptor(key))\n }\n }\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEvent.prototype = {\n /**\n * The type of this event.\n * @type {string}\n */\n get type() {\n return pd(this).event.type\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get target() {\n return pd(this).eventTarget\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get currentTarget() {\n return pd(this).currentTarget\n },\n\n /**\n * @returns {EventTarget[]} The composed path of this event.\n */\n composedPath() {\n const currentTarget = pd(this).currentTarget\n if (currentTarget == null) {\n return []\n }\n return [currentTarget]\n },\n\n /**\n * Constant of NONE.\n * @type {number}\n */\n get NONE() {\n return 0\n },\n\n /**\n * Constant of CAPTURING_PHASE.\n * @type {number}\n */\n get CAPTURING_PHASE() {\n return 1\n },\n\n /**\n * Constant of AT_TARGET.\n * @type {number}\n */\n get AT_TARGET() {\n return 2\n },\n\n /**\n * Constant of BUBBLING_PHASE.\n * @type {number}\n */\n get BUBBLING_PHASE() {\n return 3\n },\n\n /**\n * The target of this event.\n * @type {number}\n */\n get eventPhase() {\n return pd(this).eventPhase\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopPropagation() {\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.stopPropagation === \"function\") {\n data.event.stopPropagation()\n }\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopImmediatePropagation() {\n const data = pd(this)\n\n data.stopped = true\n data.immediateStopped = true\n if (typeof data.event.stopImmediatePropagation === \"function\") {\n data.event.stopImmediatePropagation()\n }\n },\n\n /**\n * The flag to be bubbling.\n * @type {boolean}\n */\n get bubbles() {\n return Boolean(pd(this).event.bubbles)\n },\n\n /**\n * The flag to be cancelable.\n * @type {boolean}\n */\n get cancelable() {\n return Boolean(pd(this).event.cancelable)\n },\n\n /**\n * Cancel this event.\n * @returns {void}\n */\n preventDefault() {\n setCancelFlag(pd(this))\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n */\n get defaultPrevented() {\n return pd(this).canceled\n },\n\n /**\n * The flag to be composed.\n * @type {boolean}\n */\n get composed() {\n return Boolean(pd(this).event.composed)\n },\n\n /**\n * The unix time of this event.\n * @type {number}\n */\n get timeStamp() {\n return pd(this).timeStamp\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n * @deprecated\n */\n get srcElement() {\n return pd(this).eventTarget\n },\n\n /**\n * The flag to stop event bubbling.\n * @type {boolean}\n * @deprecated\n */\n get cancelBubble() {\n return pd(this).stopped\n },\n set cancelBubble(value) {\n if (!value) {\n return\n }\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.cancelBubble === \"boolean\") {\n data.event.cancelBubble = true\n }\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n * @deprecated\n */\n get returnValue() {\n return !pd(this).canceled\n },\n set returnValue(value) {\n if (!value) {\n setCancelFlag(pd(this))\n }\n },\n\n /**\n * Initialize this event object. But do nothing under event dispatching.\n * @param {string} type The event type.\n * @param {boolean} [bubbles=false] The flag to be possible to bubble up.\n * @param {boolean} [cancelable=false] The flag to be possible to cancel.\n * @deprecated\n */\n initEvent() {\n // Do nothing.\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(Event.prototype, \"constructor\", {\n value: Event,\n configurable: true,\n writable: true,\n})\n\n// Ensure `event instanceof window.Event` is `true`.\nif (typeof window !== \"undefined\" && typeof window.Event !== \"undefined\") {\n Object.setPrototypeOf(Event.prototype, window.Event.prototype)\n\n // Make association for wrappers.\n wrappers.set(window.Event.prototype, Event)\n}\n\n/**\n * Get the property descriptor to redirect a given property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to redirect the property.\n * @private\n */\nfunction defineRedirectDescriptor(key) {\n return {\n get() {\n return pd(this).event[key]\n },\n set(value) {\n pd(this).event[key] = value\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Get the property descriptor to call a given method property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to call the method property.\n * @private\n */\nfunction defineCallDescriptor(key) {\n return {\n value() {\n const event = pd(this).event\n return event[key].apply(event, arguments)\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define new wrapper class.\n * @param {Function} BaseEvent The base wrapper class.\n * @param {Object} proto The prototype of the original event.\n * @returns {Function} The defined wrapper class.\n * @private\n */\nfunction defineWrapper(BaseEvent, proto) {\n const keys = Object.keys(proto)\n if (keys.length === 0) {\n return BaseEvent\n }\n\n /** CustomEvent */\n function CustomEvent(eventTarget, event) {\n BaseEvent.call(this, eventTarget, event)\n }\n\n CustomEvent.prototype = Object.create(BaseEvent.prototype, {\n constructor: { value: CustomEvent, configurable: true, writable: true },\n })\n\n // Define accessors.\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in BaseEvent.prototype)) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key)\n const isFunc = typeof descriptor.value === \"function\"\n Object.defineProperty(\n CustomEvent.prototype,\n key,\n isFunc\n ? defineCallDescriptor(key)\n : defineRedirectDescriptor(key)\n )\n }\n }\n\n return CustomEvent\n}\n\n/**\n * Get the wrapper class of a given prototype.\n * @param {Object} proto The prototype of the original event to get its wrapper.\n * @returns {Function} The wrapper class.\n * @private\n */\nfunction getWrapper(proto) {\n if (proto == null || proto === Object.prototype) {\n return Event\n }\n\n let wrapper = wrappers.get(proto)\n if (wrapper == null) {\n wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto)\n wrappers.set(proto, wrapper)\n }\n return wrapper\n}\n\n/**\n * Wrap a given event to management a dispatching.\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Object} event The event to wrap.\n * @returns {Event} The wrapper instance.\n * @private\n */\nexport function wrapEvent(eventTarget, event) {\n const Wrapper = getWrapper(Object.getPrototypeOf(event))\n return new Wrapper(eventTarget, event)\n}\n\n/**\n * Get the immediateStopped flag of a given event.\n * @param {Event} event The event to get.\n * @returns {boolean} The flag to stop propagation immediately.\n * @private\n */\nexport function isStopped(event) {\n return pd(event).immediateStopped\n}\n\n/**\n * Set the current event phase of a given event.\n * @param {Event} event The event to set current target.\n * @param {number} eventPhase New event phase.\n * @returns {void}\n * @private\n */\nexport function setEventPhase(event, eventPhase) {\n pd(event).eventPhase = eventPhase\n}\n\n/**\n * Set the current target of a given event.\n * @param {Event} event The event to set current target.\n * @param {EventTarget|null} currentTarget New current target.\n * @returns {void}\n * @private\n */\nexport function setCurrentTarget(event, currentTarget) {\n pd(event).currentTarget = currentTarget\n}\n\n/**\n * Set a passive listener of a given event.\n * @param {Event} event The event to set current target.\n * @param {Function|null} passiveListener New passive listener.\n * @returns {void}\n * @private\n */\nexport function setPassiveListener(event, passiveListener) {\n pd(event).passiveListener = passiveListener\n}\n","import {\n isStopped,\n setCurrentTarget,\n setEventPhase,\n setPassiveListener,\n wrapEvent,\n} from \"./event.mjs\"\n\n/**\n * @typedef {object} ListenerNode\n * @property {Function} listener\n * @property {1|2|3} listenerType\n * @property {boolean} passive\n * @property {boolean} once\n * @property {ListenerNode|null} next\n * @private\n */\n\n/**\n * @type {WeakMap>}\n * @private\n */\nconst listenersMap = new WeakMap()\n\n// Listener types\nconst CAPTURE = 1\nconst BUBBLE = 2\nconst ATTRIBUTE = 3\n\n/**\n * Check whether a given value is an object or not.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is an object.\n */\nfunction isObject(x) {\n return x !== null && typeof x === \"object\" //eslint-disable-line no-restricted-syntax\n}\n\n/**\n * Get listeners.\n * @param {EventTarget} eventTarget The event target to get.\n * @returns {Map} The listeners.\n * @private\n */\nfunction getListeners(eventTarget) {\n const listeners = listenersMap.get(eventTarget)\n if (listeners == null) {\n throw new TypeError(\n \"'this' is expected an EventTarget object, but got another value.\"\n )\n }\n return listeners\n}\n\n/**\n * Get the property descriptor for the event attribute of a given event.\n * @param {string} eventName The event name to get property descriptor.\n * @returns {PropertyDescriptor} The property descriptor.\n * @private\n */\nfunction defineEventAttributeDescriptor(eventName) {\n return {\n get() {\n const listeners = getListeners(this)\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n return node.listener\n }\n node = node.next\n }\n return null\n },\n\n set(listener) {\n if (typeof listener !== \"function\" && !isObject(listener)) {\n listener = null // eslint-disable-line no-param-reassign\n }\n const listeners = getListeners(this)\n\n // Traverse to the tail while removing old value.\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n // Remove old value.\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n node = node.next\n }\n\n // Add new value.\n if (listener !== null) {\n const newNode = {\n listener,\n listenerType: ATTRIBUTE,\n passive: false,\n once: false,\n next: null,\n }\n if (prev === null) {\n listeners.set(eventName, newNode)\n } else {\n prev.next = newNode\n }\n }\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define an event attribute (e.g. `eventTarget.onclick`).\n * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.\n * @param {string} eventName The event name to define.\n * @returns {void}\n */\nfunction defineEventAttribute(eventTargetPrototype, eventName) {\n Object.defineProperty(\n eventTargetPrototype,\n `on${eventName}`,\n defineEventAttributeDescriptor(eventName)\n )\n}\n\n/**\n * Define a custom EventTarget with event attributes.\n * @param {string[]} eventNames Event names for event attributes.\n * @returns {EventTarget} The custom EventTarget.\n * @private\n */\nfunction defineCustomEventTarget(eventNames) {\n /** CustomEventTarget */\n function CustomEventTarget() {\n EventTarget.call(this)\n }\n\n CustomEventTarget.prototype = Object.create(EventTarget.prototype, {\n constructor: {\n value: CustomEventTarget,\n configurable: true,\n writable: true,\n },\n })\n\n for (let i = 0; i < eventNames.length; ++i) {\n defineEventAttribute(CustomEventTarget.prototype, eventNames[i])\n }\n\n return CustomEventTarget\n}\n\n/**\n * EventTarget.\n *\n * - This is constructor if no arguments.\n * - This is a function which returns a CustomEventTarget constructor if there are arguments.\n *\n * For example:\n *\n * class A extends EventTarget {}\n * class B extends EventTarget(\"message\") {}\n * class C extends EventTarget(\"message\", \"error\") {}\n * class D extends EventTarget([\"message\", \"error\"]) {}\n */\nfunction EventTarget() {\n /*eslint-disable consistent-return */\n if (this instanceof EventTarget) {\n listenersMap.set(this, new Map())\n return\n }\n if (arguments.length === 1 && Array.isArray(arguments[0])) {\n return defineCustomEventTarget(arguments[0])\n }\n if (arguments.length > 0) {\n const types = new Array(arguments.length)\n for (let i = 0; i < arguments.length; ++i) {\n types[i] = arguments[i]\n }\n return defineCustomEventTarget(types)\n }\n throw new TypeError(\"Cannot call a class as a function\")\n /*eslint-enable consistent-return */\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEventTarget.prototype = {\n /**\n * Add a given listener to this event target.\n * @param {string} eventName The event name to add.\n * @param {Function} listener The listener to add.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n addEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n if (typeof listener !== \"function\" && !isObject(listener)) {\n throw new TypeError(\"'listener' should be a function or an object.\")\n }\n\n const listeners = getListeners(this)\n const optionsIsObj = isObject(options)\n const capture = optionsIsObj\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n const newNode = {\n listener,\n listenerType,\n passive: optionsIsObj && Boolean(options.passive),\n once: optionsIsObj && Boolean(options.once),\n next: null,\n }\n\n // Set it as the first node if the first node is null.\n let node = listeners.get(eventName)\n if (node === undefined) {\n listeners.set(eventName, newNode)\n return\n }\n\n // Traverse to the tail while checking duplication..\n let prev = null\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n // Should ignore duplication.\n return\n }\n prev = node\n node = node.next\n }\n\n // Add it.\n prev.next = newNode\n },\n\n /**\n * Remove a given listener from this event target.\n * @param {string} eventName The event name to remove.\n * @param {Function} listener The listener to remove.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n removeEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n\n const listeners = getListeners(this)\n const capture = isObject(options)\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n return\n }\n\n prev = node\n node = node.next\n }\n },\n\n /**\n * Dispatch a given event.\n * @param {Event|{type:string}} event The event to dispatch.\n * @returns {boolean} `false` if canceled.\n */\n dispatchEvent(event) {\n if (event == null || typeof event.type !== \"string\") {\n throw new TypeError('\"event.type\" should be a string.')\n }\n\n // If listeners aren't registered, terminate.\n const listeners = getListeners(this)\n const eventName = event.type\n let node = listeners.get(eventName)\n if (node == null) {\n return true\n }\n\n // Since we cannot rewrite several properties, so wrap object.\n const wrappedEvent = wrapEvent(this, event)\n\n // This doesn't process capturing phase and bubbling phase.\n // This isn't participating in a tree.\n let prev = null\n while (node != null) {\n // Remove this listener if it's once\n if (node.once) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n // Call this listener\n setPassiveListener(\n wrappedEvent,\n node.passive ? node.listener : null\n )\n if (typeof node.listener === \"function\") {\n try {\n node.listener.call(this, wrappedEvent)\n } catch (err) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(err)\n }\n }\n } else if (\n node.listenerType !== ATTRIBUTE &&\n typeof node.listener.handleEvent === \"function\"\n ) {\n node.listener.handleEvent(wrappedEvent)\n }\n\n // Break if `event.stopImmediatePropagation` was called.\n if (isStopped(wrappedEvent)) {\n break\n }\n\n node = node.next\n }\n setPassiveListener(wrappedEvent, null)\n setEventPhase(wrappedEvent, 0)\n setCurrentTarget(wrappedEvent, null)\n\n return !wrappedEvent.defaultPrevented\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(EventTarget.prototype, \"constructor\", {\n value: EventTarget,\n configurable: true,\n writable: true,\n})\n\n// Ensure `eventTarget instanceof window.EventTarget` is `true`.\nif (\n typeof window !== \"undefined\" &&\n typeof window.EventTarget !== \"undefined\"\n) {\n Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype)\n}\n\nexport { defineEventAttribute, EventTarget }\nexport default EventTarget\n"],"names":[],"mappings":";;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,WAAW,GAAG,IAAI,OAAO,GAAE;;;;;;;AAOjC,MAAM,QAAQ,GAAG,IAAI,OAAO,GAAE;;;;;;;;AAQ9B,SAAS,EAAE,CAAC,KAAK,EAAE;IACf,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,EAAC;IACnC,OAAO,CAAC,MAAM;QACV,IAAI,IAAI,IAAI;QACZ,6CAA6C;QAC7C,KAAK;MACR;IACD,OAAO,IAAI;CACd;;;;;;AAMD,SAAS,aAAa,CAAC,IAAI,EAAE;IACzB,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE;QAC9B;YACI,OAAO,OAAO,KAAK,WAAW;YAC9B,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;UACrC;YACE,OAAO,CAAC,KAAK;gBACT,oEAAoE;gBACpE,IAAI,CAAC,eAAe;cACvB;SACJ;QACD,MAAM;KACT;IACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;QACxB,MAAM;KACT;;IAED,IAAI,CAAC,QAAQ,GAAG,KAAI;IACpB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,UAAU,EAAE;QACjD,IAAI,CAAC,KAAK,CAAC,cAAc,GAAE;KAC9B;CACJ;;;;;;;;;;;;AAYD,SAAS,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE;IAC/B,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE;QAClB,WAAW;QACX,KAAK;QACL,UAAU,EAAE,CAAC;QACb,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,IAAI;QACrB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;KAC3C,EAAC;;;IAGF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAC;;;IAG5E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAC;QACnB,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE;YAChB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,wBAAwB,CAAC,GAAG,CAAC,EAAC;SAClE;KACJ;CACJ;;;AAGD,KAAK,CAAC,SAAS,GAAG;;;;;IAKd,IAAI,IAAI,GAAG;QACP,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI;KAC7B;;;;;;IAMD,IAAI,MAAM,GAAG;QACT,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW;KAC9B;;;;;;IAMD,IAAI,aAAa,GAAG;QAChB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa;KAChC;;;;;IAKD,YAAY,GAAG;QACX,MAAM,aAAa,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,cAAa;QAC5C,IAAI,aAAa,IAAI,IAAI,EAAE;YACvB,OAAO,EAAE;SACZ;QACD,OAAO,CAAC,aAAa,CAAC;KACzB;;;;;;IAMD,IAAI,IAAI,GAAG;QACP,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,eAAe,GAAG;QAClB,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,SAAS,GAAG;QACZ,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,cAAc,GAAG;QACjB,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,UAAU,GAAG;QACb,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU;KAC7B;;;;;;IAMD,eAAe,GAAG;QACd,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe,KAAK,UAAU,EAAE;YAClD,IAAI,CAAC,KAAK,CAAC,eAAe,GAAE;SAC/B;KACJ;;;;;;IAMD,wBAAwB,GAAG;QACvB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,CAAC,gBAAgB,GAAG,KAAI;QAC5B,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,wBAAwB,KAAK,UAAU,EAAE;YAC3D,IAAI,CAAC,KAAK,CAAC,wBAAwB,GAAE;SACxC;KACJ;;;;;;IAMD,IAAI,OAAO,GAAG;QACV,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;KACzC;;;;;;IAMD,IAAI,UAAU,GAAG;QACb,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;KAC5C;;;;;;IAMD,cAAc,GAAG;QACb,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,EAAC;KAC1B;;;;;;IAMD,IAAI,gBAAgB,GAAG;QACnB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ;KAC3B;;;;;;IAMD,IAAI,QAAQ,GAAG;QACX,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC1C;;;;;;IAMD,IAAI,SAAS,GAAG;QACZ,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS;KAC5B;;;;;;;IAOD,IAAI,UAAU,GAAG;QACb,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW;KAC9B;;;;;;;IAOD,IAAI,YAAY,GAAG;QACf,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO;KAC1B;IACD,IAAI,YAAY,CAAC,KAAK,EAAE;QACpB,IAAI,CAAC,KAAK,EAAE;YACR,MAAM;SACT;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE;YAC9C,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAI;SACjC;KACJ;;;;;;;IAOD,IAAI,WAAW,GAAG;QACd,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ;KAC5B;IACD,IAAI,WAAW,CAAC,KAAK,EAAE;QACnB,IAAI,CAAC,KAAK,EAAE;YACR,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,EAAC;SAC1B;KACJ;;;;;;;;;IASD,SAAS,GAAG;;KAEX;EACJ;;;AAGD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE;IAClD,KAAK,EAAE,KAAK;IACZ,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,IAAI;CACjB,EAAC;;;AAGF,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,WAAW,EAAE;IACtE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAC;;;IAG9D,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAC;CAC9C;;;;;;;;AAQD,SAAS,wBAAwB,CAAC,GAAG,EAAE;IACnC,OAAO;QACH,GAAG,GAAG;YACF,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;SAC7B;QACD,GAAG,CAAC,KAAK,EAAE;YACP,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,MAAK;SAC9B;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;AAQD,SAAS,oBAAoB,CAAC,GAAG,EAAE;IAC/B,OAAO;QACH,KAAK,GAAG;YACJ,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,MAAK;YAC5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;SAC5C;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;;AASD,SAAS,aAAa,CAAC,SAAS,EAAE,KAAK,EAAE;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACnB,OAAO,SAAS;KACnB;;;IAGD,SAAS,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE;QACrC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAC;KAC3C;;IAED,WAAW,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE;QACvD,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;KAC1E,EAAC;;;IAGF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAC;QACnB,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE;YAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,EAAC;YAC9D,MAAM,MAAM,GAAG,OAAO,UAAU,CAAC,KAAK,KAAK,WAAU;YACrD,MAAM,CAAC,cAAc;gBACjB,WAAW,CAAC,SAAS;gBACrB,GAAG;gBACH,MAAM;sBACA,oBAAoB,CAAC,GAAG,CAAC;sBACzB,wBAAwB,CAAC,GAAG,CAAC;cACtC;SACJ;KACJ;;IAED,OAAO,WAAW;CACrB;;;;;;;;AAQD,SAAS,UAAU,CAAC,KAAK,EAAE;IACvB,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,EAAE;QAC7C,OAAO,KAAK;KACf;;IAED,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAC;IACjC,IAAI,OAAO,IAAI,IAAI,EAAE;QACjB,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAC;QACxE,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAC;KAC/B;IACD,OAAO,OAAO;CACjB;;;;;;;;;AASD,AAAO,SAAS,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE;IAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAC;IACxD,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC;CACzC;;;;;;;;AAQD,AAAO,SAAS,SAAS,CAAC,KAAK,EAAE;IAC7B,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,gBAAgB;CACpC;;;;;;;;;AASD,AAAO,SAAS,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE;IAC7C,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,WAAU;CACpC;;;;;;;;;AASD,AAAO,SAAS,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE;IACnD,EAAE,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,cAAa;CAC1C;;;;;;;;;AASD,AAAO,SAAS,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE;IACvD,EAAE,CAAC,KAAK,CAAC,CAAC,eAAe,GAAG,gBAAe;CAC9C;;ACtdD;;;;;;;;;;;;;;AAcA,MAAM,YAAY,GAAG,IAAI,OAAO,GAAE;;;AAGlC,MAAM,OAAO,GAAG,EAAC;AACjB,MAAM,MAAM,GAAG,EAAC;AAChB,MAAM,SAAS,GAAG,EAAC;;;;;;;AAOnB,SAAS,QAAQ,CAAC,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;CAC7C;;;;;;;;AAQD,SAAS,YAAY,CAAC,WAAW,EAAE;IAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,EAAC;IAC/C,IAAI,SAAS,IAAI,IAAI,EAAE;QACnB,MAAM,IAAI,SAAS;YACf,kEAAkE;SACrE;KACJ;IACD,OAAO,SAAS;CACnB;;;;;;;;AAQD,SAAS,8BAA8B,CAAC,SAAS,EAAE;IAC/C,OAAO;QACH,GAAG,GAAG;YACF,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;YACpC,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;YACnC,OAAO,IAAI,IAAI,IAAI,EAAE;gBACjB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;oBACjC,OAAO,IAAI,CAAC,QAAQ;iBACvB;gBACD,IAAI,GAAG,IAAI,CAAC,KAAI;aACnB;YACD,OAAO,IAAI;SACd;;QAED,GAAG,CAAC,QAAQ,EAAE;YACV,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;gBACvD,QAAQ,GAAG,KAAI;aAClB;YACD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;;;YAGpC,IAAI,IAAI,GAAG,KAAI;YACf,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;YACnC,OAAO,IAAI,IAAI,IAAI,EAAE;gBACjB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;;oBAEjC,IAAI,IAAI,KAAK,IAAI,EAAE;wBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;qBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;wBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;qBACtC,MAAM;wBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;qBAC9B;iBACJ,MAAM;oBACH,IAAI,GAAG,KAAI;iBACd;;gBAED,IAAI,GAAG,IAAI,CAAC,KAAI;aACnB;;;YAGD,IAAI,QAAQ,KAAK,IAAI,EAAE;gBACnB,MAAM,OAAO,GAAG;oBACZ,QAAQ;oBACR,YAAY,EAAE,SAAS;oBACvB,OAAO,EAAE,KAAK;oBACd,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,IAAI;kBACb;gBACD,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAC;iBACpC,MAAM;oBACH,IAAI,CAAC,IAAI,GAAG,QAAO;iBACtB;aACJ;SACJ;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;AAQD,SAAS,oBAAoB,CAAC,oBAAoB,EAAE,SAAS,EAAE;IAC3D,MAAM,CAAC,cAAc;QACjB,oBAAoB;QACpB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAChB,8BAA8B,CAAC,SAAS,CAAC;MAC5C;CACJ;;;;;;;;AAQD,SAAS,uBAAuB,CAAC,UAAU,EAAE;;IAEzC,SAAS,iBAAiB,GAAG;QACzB,WAAW,CAAC,IAAI,CAAC,IAAI,EAAC;KACzB;;IAED,iBAAiB,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;QAC/D,WAAW,EAAE;YACT,KAAK,EAAE,iBAAiB;YACxB,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;SACjB;KACJ,EAAC;;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QACxC,oBAAoB,CAAC,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,EAAC;KACnE;;IAED,OAAO,iBAAiB;CAC3B;;;;;;;;;;;;;;;AAeD,SAAS,WAAW,GAAG;;IAEnB,IAAI,IAAI,YAAY,WAAW,EAAE;QAC7B,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAC;QACjC,MAAM;KACT;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;QACvD,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;KAC/C;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;QACtB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACvC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,EAAC;SAC1B;QACD,OAAO,uBAAuB,CAAC,KAAK,CAAC;KACxC;IACD,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC;;CAE3D;;;AAGD,WAAW,CAAC,SAAS,GAAG;;;;;;;;IAQpB,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC3C,IAAI,QAAQ,IAAI,IAAI,EAAE;YAClB,MAAM;SACT;QACD,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACvD,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC;SACvE;;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,EAAC;QACtC,MAAM,OAAO,GAAG,YAAY;cACtB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;cACxB,OAAO,CAAC,OAAO,EAAC;QACtB,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,OAAM;QAC/C,MAAM,OAAO,GAAG;YACZ,QAAQ;YACR,YAAY;YACZ,OAAO,EAAE,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YACjD,IAAI,EAAE,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAC3C,IAAI,EAAE,IAAI;UACb;;;QAGD,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,IAAI,IAAI,KAAK,SAAS,EAAE;YACpB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAC;YACjC,MAAM;SACT;;;QAGD,IAAI,IAAI,GAAG,KAAI;QACf,OAAO,IAAI,IAAI,IAAI,EAAE;YACjB;gBACI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAC1B,IAAI,CAAC,YAAY,KAAK,YAAY;cACpC;;gBAEE,MAAM;aACT;YACD,IAAI,GAAG,KAAI;YACX,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;;;QAGD,IAAI,CAAC,IAAI,GAAG,QAAO;KACtB;;;;;;;;;IASD,mBAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC9C,IAAI,QAAQ,IAAI,IAAI,EAAE;YAClB,MAAM;SACT;;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;cAC3B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;cACxB,OAAO,CAAC,OAAO,EAAC;QACtB,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,OAAM;;QAE/C,IAAI,IAAI,GAAG,KAAI;QACf,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,OAAO,IAAI,IAAI,IAAI,EAAE;YACjB;gBACI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAC1B,IAAI,CAAC,YAAY,KAAK,YAAY;cACpC;gBACE,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;iBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;oBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;iBACtC,MAAM;oBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;iBAC9B;gBACD,MAAM;aACT;;YAED,IAAI,GAAG,KAAI;YACX,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;KACJ;;;;;;;IAOD,aAAa,CAAC,KAAK,EAAE;QACjB,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YACjD,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC;SAC1D;;;QAGD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAI;QAC5B,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,IAAI,IAAI,IAAI,IAAI,EAAE;YACd,OAAO,IAAI;SACd;;;QAGD,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAC;;;;QAI3C,IAAI,IAAI,GAAG,KAAI;QACf,OAAO,IAAI,IAAI,IAAI,EAAE;;YAEjB,IAAI,IAAI,CAAC,IAAI,EAAE;gBACX,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;iBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;oBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;iBACtC,MAAM;oBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;iBAC9B;aACJ,MAAM;gBACH,IAAI,GAAG,KAAI;aACd;;;YAGD,kBAAkB;gBACd,YAAY;gBACZ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI;cACtC;YACD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE;gBACrC,IAAI;oBACA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAC;iBACzC,CAAC,OAAO,GAAG,EAAE;oBACV;wBACI,OAAO,OAAO,KAAK,WAAW;wBAC9B,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;sBACrC;wBACE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAC;qBACrB;iBACJ;aACJ,MAAM;gBACH,IAAI,CAAC,YAAY,KAAK,SAAS;gBAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,UAAU;cACjD;gBACE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAC;aAC1C;;;YAGD,IAAI,SAAS,CAAC,YAAY,CAAC,EAAE;gBACzB,KAAK;aACR;;YAED,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;QACD,kBAAkB,CAAC,YAAY,EAAE,IAAI,EAAC;QACtC,aAAa,CAAC,YAAY,EAAE,CAAC,EAAC;QAC9B,gBAAgB,CAAC,YAAY,EAAE,IAAI,EAAC;;QAEpC,OAAO,CAAC,YAAY,CAAC,gBAAgB;KACxC;EACJ;;;AAGD,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,aAAa,EAAE;IACxD,KAAK,EAAE,WAAW;IAClB,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,IAAI;CACjB,EAAC;;;AAGF;IACI,OAAO,MAAM,KAAK,WAAW;IAC7B,OAAO,MAAM,CAAC,WAAW,KAAK,WAAW;EAC3C;IACE,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,EAAC;CAC7E;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/node_modules/event-target-shim/dist/event-target-shim.mjs b/node_modules/event-target-shim/dist/event-target-shim.mjs new file mode 100644 index 0000000..114f3a1 --- /dev/null +++ b/node_modules/event-target-shim/dist/event-target-shim.mjs @@ -0,0 +1,862 @@ +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */ +/** + * @typedef {object} PrivateData + * @property {EventTarget} eventTarget The event target. + * @property {{type:string}} event The original event object. + * @property {number} eventPhase The current event phase. + * @property {EventTarget|null} currentTarget The current event target. + * @property {boolean} canceled The flag to prevent default. + * @property {boolean} stopped The flag to stop propagation. + * @property {boolean} immediateStopped The flag to stop propagation immediately. + * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null. + * @property {number} timeStamp The unix time. + * @private + */ + +/** + * Private data for event wrappers. + * @type {WeakMap} + * @private + */ +const privateData = new WeakMap(); + +/** + * Cache for wrapper classes. + * @type {WeakMap} + * @private + */ +const wrappers = new WeakMap(); + +/** + * Get private data. + * @param {Event} event The event object to get private data. + * @returns {PrivateData} The private data of the event. + * @private + */ +function pd(event) { + const retv = privateData.get(event); + console.assert( + retv != null, + "'this' is expected an Event object, but got", + event + ); + return retv +} + +/** + * https://dom.spec.whatwg.org/#set-the-canceled-flag + * @param data {PrivateData} private data. + */ +function setCancelFlag(data) { + if (data.passiveListener != null) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error( + "Unable to preventDefault inside passive event listener invocation.", + data.passiveListener + ); + } + return + } + if (!data.event.cancelable) { + return + } + + data.canceled = true; + if (typeof data.event.preventDefault === "function") { + data.event.preventDefault(); + } +} + +/** + * @see https://dom.spec.whatwg.org/#interface-event + * @private + */ +/** + * The event wrapper. + * @constructor + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Event|{type:string}} event The original event to wrap. + */ +function Event(eventTarget, event) { + privateData.set(this, { + eventTarget, + event, + eventPhase: 2, + currentTarget: eventTarget, + canceled: false, + stopped: false, + immediateStopped: false, + passiveListener: null, + timeStamp: event.timeStamp || Date.now(), + }); + + // https://heycam.github.io/webidl/#Unforgeable + Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); + + // Define accessors + const keys = Object.keys(event); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in this)) { + Object.defineProperty(this, key, defineRedirectDescriptor(key)); + } + } +} + +// Should be enumerable, but class methods are not enumerable. +Event.prototype = { + /** + * The type of this event. + * @type {string} + */ + get type() { + return pd(this).event.type + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get target() { + return pd(this).eventTarget + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get currentTarget() { + return pd(this).currentTarget + }, + + /** + * @returns {EventTarget[]} The composed path of this event. + */ + composedPath() { + const currentTarget = pd(this).currentTarget; + if (currentTarget == null) { + return [] + } + return [currentTarget] + }, + + /** + * Constant of NONE. + * @type {number} + */ + get NONE() { + return 0 + }, + + /** + * Constant of CAPTURING_PHASE. + * @type {number} + */ + get CAPTURING_PHASE() { + return 1 + }, + + /** + * Constant of AT_TARGET. + * @type {number} + */ + get AT_TARGET() { + return 2 + }, + + /** + * Constant of BUBBLING_PHASE. + * @type {number} + */ + get BUBBLING_PHASE() { + return 3 + }, + + /** + * The target of this event. + * @type {number} + */ + get eventPhase() { + return pd(this).eventPhase + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopPropagation() { + const data = pd(this); + + data.stopped = true; + if (typeof data.event.stopPropagation === "function") { + data.event.stopPropagation(); + } + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopImmediatePropagation() { + const data = pd(this); + + data.stopped = true; + data.immediateStopped = true; + if (typeof data.event.stopImmediatePropagation === "function") { + data.event.stopImmediatePropagation(); + } + }, + + /** + * The flag to be bubbling. + * @type {boolean} + */ + get bubbles() { + return Boolean(pd(this).event.bubbles) + }, + + /** + * The flag to be cancelable. + * @type {boolean} + */ + get cancelable() { + return Boolean(pd(this).event.cancelable) + }, + + /** + * Cancel this event. + * @returns {void} + */ + preventDefault() { + setCancelFlag(pd(this)); + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + */ + get defaultPrevented() { + return pd(this).canceled + }, + + /** + * The flag to be composed. + * @type {boolean} + */ + get composed() { + return Boolean(pd(this).event.composed) + }, + + /** + * The unix time of this event. + * @type {number} + */ + get timeStamp() { + return pd(this).timeStamp + }, + + /** + * The target of this event. + * @type {EventTarget} + * @deprecated + */ + get srcElement() { + return pd(this).eventTarget + }, + + /** + * The flag to stop event bubbling. + * @type {boolean} + * @deprecated + */ + get cancelBubble() { + return pd(this).stopped + }, + set cancelBubble(value) { + if (!value) { + return + } + const data = pd(this); + + data.stopped = true; + if (typeof data.event.cancelBubble === "boolean") { + data.event.cancelBubble = true; + } + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + * @deprecated + */ + get returnValue() { + return !pd(this).canceled + }, + set returnValue(value) { + if (!value) { + setCancelFlag(pd(this)); + } + }, + + /** + * Initialize this event object. But do nothing under event dispatching. + * @param {string} type The event type. + * @param {boolean} [bubbles=false] The flag to be possible to bubble up. + * @param {boolean} [cancelable=false] The flag to be possible to cancel. + * @deprecated + */ + initEvent() { + // Do nothing. + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(Event.prototype, "constructor", { + value: Event, + configurable: true, + writable: true, +}); + +// Ensure `event instanceof window.Event` is `true`. +if (typeof window !== "undefined" && typeof window.Event !== "undefined") { + Object.setPrototypeOf(Event.prototype, window.Event.prototype); + + // Make association for wrappers. + wrappers.set(window.Event.prototype, Event); +} + +/** + * Get the property descriptor to redirect a given property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to redirect the property. + * @private + */ +function defineRedirectDescriptor(key) { + return { + get() { + return pd(this).event[key] + }, + set(value) { + pd(this).event[key] = value; + }, + configurable: true, + enumerable: true, + } +} + +/** + * Get the property descriptor to call a given method property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to call the method property. + * @private + */ +function defineCallDescriptor(key) { + return { + value() { + const event = pd(this).event; + return event[key].apply(event, arguments) + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define new wrapper class. + * @param {Function} BaseEvent The base wrapper class. + * @param {Object} proto The prototype of the original event. + * @returns {Function} The defined wrapper class. + * @private + */ +function defineWrapper(BaseEvent, proto) { + const keys = Object.keys(proto); + if (keys.length === 0) { + return BaseEvent + } + + /** CustomEvent */ + function CustomEvent(eventTarget, event) { + BaseEvent.call(this, eventTarget, event); + } + + CustomEvent.prototype = Object.create(BaseEvent.prototype, { + constructor: { value: CustomEvent, configurable: true, writable: true }, + }); + + // Define accessors. + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in BaseEvent.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(proto, key); + const isFunc = typeof descriptor.value === "function"; + Object.defineProperty( + CustomEvent.prototype, + key, + isFunc + ? defineCallDescriptor(key) + : defineRedirectDescriptor(key) + ); + } + } + + return CustomEvent +} + +/** + * Get the wrapper class of a given prototype. + * @param {Object} proto The prototype of the original event to get its wrapper. + * @returns {Function} The wrapper class. + * @private + */ +function getWrapper(proto) { + if (proto == null || proto === Object.prototype) { + return Event + } + + let wrapper = wrappers.get(proto); + if (wrapper == null) { + wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto); + wrappers.set(proto, wrapper); + } + return wrapper +} + +/** + * Wrap a given event to management a dispatching. + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Object} event The event to wrap. + * @returns {Event} The wrapper instance. + * @private + */ +function wrapEvent(eventTarget, event) { + const Wrapper = getWrapper(Object.getPrototypeOf(event)); + return new Wrapper(eventTarget, event) +} + +/** + * Get the immediateStopped flag of a given event. + * @param {Event} event The event to get. + * @returns {boolean} The flag to stop propagation immediately. + * @private + */ +function isStopped(event) { + return pd(event).immediateStopped +} + +/** + * Set the current event phase of a given event. + * @param {Event} event The event to set current target. + * @param {number} eventPhase New event phase. + * @returns {void} + * @private + */ +function setEventPhase(event, eventPhase) { + pd(event).eventPhase = eventPhase; +} + +/** + * Set the current target of a given event. + * @param {Event} event The event to set current target. + * @param {EventTarget|null} currentTarget New current target. + * @returns {void} + * @private + */ +function setCurrentTarget(event, currentTarget) { + pd(event).currentTarget = currentTarget; +} + +/** + * Set a passive listener of a given event. + * @param {Event} event The event to set current target. + * @param {Function|null} passiveListener New passive listener. + * @returns {void} + * @private + */ +function setPassiveListener(event, passiveListener) { + pd(event).passiveListener = passiveListener; +} + +/** + * @typedef {object} ListenerNode + * @property {Function} listener + * @property {1|2|3} listenerType + * @property {boolean} passive + * @property {boolean} once + * @property {ListenerNode|null} next + * @private + */ + +/** + * @type {WeakMap>} + * @private + */ +const listenersMap = new WeakMap(); + +// Listener types +const CAPTURE = 1; +const BUBBLE = 2; +const ATTRIBUTE = 3; + +/** + * Check whether a given value is an object or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if the value is an object. + */ +function isObject(x) { + return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax +} + +/** + * Get listeners. + * @param {EventTarget} eventTarget The event target to get. + * @returns {Map} The listeners. + * @private + */ +function getListeners(eventTarget) { + const listeners = listenersMap.get(eventTarget); + if (listeners == null) { + throw new TypeError( + "'this' is expected an EventTarget object, but got another value." + ) + } + return listeners +} + +/** + * Get the property descriptor for the event attribute of a given event. + * @param {string} eventName The event name to get property descriptor. + * @returns {PropertyDescriptor} The property descriptor. + * @private + */ +function defineEventAttributeDescriptor(eventName) { + return { + get() { + const listeners = getListeners(this); + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + return node.listener + } + node = node.next; + } + return null + }, + + set(listener) { + if (typeof listener !== "function" && !isObject(listener)) { + listener = null; // eslint-disable-line no-param-reassign + } + const listeners = getListeners(this); + + // Traverse to the tail while removing old value. + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + // Remove old value. + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + node = node.next; + } + + // Add new value. + if (listener !== null) { + const newNode = { + listener, + listenerType: ATTRIBUTE, + passive: false, + once: false, + next: null, + }; + if (prev === null) { + listeners.set(eventName, newNode); + } else { + prev.next = newNode; + } + } + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite. + * @param {string} eventName The event name to define. + * @returns {void} + */ +function defineEventAttribute(eventTargetPrototype, eventName) { + Object.defineProperty( + eventTargetPrototype, + `on${eventName}`, + defineEventAttributeDescriptor(eventName) + ); +} + +/** + * Define a custom EventTarget with event attributes. + * @param {string[]} eventNames Event names for event attributes. + * @returns {EventTarget} The custom EventTarget. + * @private + */ +function defineCustomEventTarget(eventNames) { + /** CustomEventTarget */ + function CustomEventTarget() { + EventTarget.call(this); + } + + CustomEventTarget.prototype = Object.create(EventTarget.prototype, { + constructor: { + value: CustomEventTarget, + configurable: true, + writable: true, + }, + }); + + for (let i = 0; i < eventNames.length; ++i) { + defineEventAttribute(CustomEventTarget.prototype, eventNames[i]); + } + + return CustomEventTarget +} + +/** + * EventTarget. + * + * - This is constructor if no arguments. + * - This is a function which returns a CustomEventTarget constructor if there are arguments. + * + * For example: + * + * class A extends EventTarget {} + * class B extends EventTarget("message") {} + * class C extends EventTarget("message", "error") {} + * class D extends EventTarget(["message", "error"]) {} + */ +function EventTarget() { + /*eslint-disable consistent-return */ + if (this instanceof EventTarget) { + listenersMap.set(this, new Map()); + return + } + if (arguments.length === 1 && Array.isArray(arguments[0])) { + return defineCustomEventTarget(arguments[0]) + } + if (arguments.length > 0) { + const types = new Array(arguments.length); + for (let i = 0; i < arguments.length; ++i) { + types[i] = arguments[i]; + } + return defineCustomEventTarget(types) + } + throw new TypeError("Cannot call a class as a function") + /*eslint-enable consistent-return */ +} + +// Should be enumerable, but class methods are not enumerable. +EventTarget.prototype = { + /** + * Add a given listener to this event target. + * @param {string} eventName The event name to add. + * @param {Function} listener The listener to add. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + addEventListener(eventName, listener, options) { + if (listener == null) { + return + } + if (typeof listener !== "function" && !isObject(listener)) { + throw new TypeError("'listener' should be a function or an object.") + } + + const listeners = getListeners(this); + const optionsIsObj = isObject(options); + const capture = optionsIsObj + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + const newNode = { + listener, + listenerType, + passive: optionsIsObj && Boolean(options.passive), + once: optionsIsObj && Boolean(options.once), + next: null, + }; + + // Set it as the first node if the first node is null. + let node = listeners.get(eventName); + if (node === undefined) { + listeners.set(eventName, newNode); + return + } + + // Traverse to the tail while checking duplication.. + let prev = null; + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + // Should ignore duplication. + return + } + prev = node; + node = node.next; + } + + // Add it. + prev.next = newNode; + }, + + /** + * Remove a given listener from this event target. + * @param {string} eventName The event name to remove. + * @param {Function} listener The listener to remove. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + removeEventListener(eventName, listener, options) { + if (listener == null) { + return + } + + const listeners = getListeners(this); + const capture = isObject(options) + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + return + } + + prev = node; + node = node.next; + } + }, + + /** + * Dispatch a given event. + * @param {Event|{type:string}} event The event to dispatch. + * @returns {boolean} `false` if canceled. + */ + dispatchEvent(event) { + if (event == null || typeof event.type !== "string") { + throw new TypeError('"event.type" should be a string.') + } + + // If listeners aren't registered, terminate. + const listeners = getListeners(this); + const eventName = event.type; + let node = listeners.get(eventName); + if (node == null) { + return true + } + + // Since we cannot rewrite several properties, so wrap object. + const wrappedEvent = wrapEvent(this, event); + + // This doesn't process capturing phase and bubbling phase. + // This isn't participating in a tree. + let prev = null; + while (node != null) { + // Remove this listener if it's once + if (node.once) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + // Call this listener + setPassiveListener( + wrappedEvent, + node.passive ? node.listener : null + ); + if (typeof node.listener === "function") { + try { + node.listener.call(this, wrappedEvent); + } catch (err) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error(err); + } + } + } else if ( + node.listenerType !== ATTRIBUTE && + typeof node.listener.handleEvent === "function" + ) { + node.listener.handleEvent(wrappedEvent); + } + + // Break if `event.stopImmediatePropagation` was called. + if (isStopped(wrappedEvent)) { + break + } + + node = node.next; + } + setPassiveListener(wrappedEvent, null); + setEventPhase(wrappedEvent, 0); + setCurrentTarget(wrappedEvent, null); + + return !wrappedEvent.defaultPrevented + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(EventTarget.prototype, "constructor", { + value: EventTarget, + configurable: true, + writable: true, +}); + +// Ensure `eventTarget instanceof window.EventTarget` is `true`. +if ( + typeof window !== "undefined" && + typeof window.EventTarget !== "undefined" +) { + Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype); +} + +export default EventTarget; +export { defineEventAttribute, EventTarget }; +//# sourceMappingURL=event-target-shim.mjs.map diff --git a/node_modules/event-target-shim/dist/event-target-shim.mjs.map b/node_modules/event-target-shim/dist/event-target-shim.mjs.map new file mode 100644 index 0000000..57b3e8f --- /dev/null +++ b/node_modules/event-target-shim/dist/event-target-shim.mjs.map @@ -0,0 +1 @@ +{"version":3,"file":"event-target-shim.mjs","sources":["../src/event.mjs","../src/event-target.mjs"],"sourcesContent":["/**\n * @typedef {object} PrivateData\n * @property {EventTarget} eventTarget The event target.\n * @property {{type:string}} event The original event object.\n * @property {number} eventPhase The current event phase.\n * @property {EventTarget|null} currentTarget The current event target.\n * @property {boolean} canceled The flag to prevent default.\n * @property {boolean} stopped The flag to stop propagation.\n * @property {boolean} immediateStopped The flag to stop propagation immediately.\n * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.\n * @property {number} timeStamp The unix time.\n * @private\n */\n\n/**\n * Private data for event wrappers.\n * @type {WeakMap}\n * @private\n */\nconst privateData = new WeakMap()\n\n/**\n * Cache for wrapper classes.\n * @type {WeakMap}\n * @private\n */\nconst wrappers = new WeakMap()\n\n/**\n * Get private data.\n * @param {Event} event The event object to get private data.\n * @returns {PrivateData} The private data of the event.\n * @private\n */\nfunction pd(event) {\n const retv = privateData.get(event)\n console.assert(\n retv != null,\n \"'this' is expected an Event object, but got\",\n event\n )\n return retv\n}\n\n/**\n * https://dom.spec.whatwg.org/#set-the-canceled-flag\n * @param data {PrivateData} private data.\n */\nfunction setCancelFlag(data) {\n if (data.passiveListener != null) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(\n \"Unable to preventDefault inside passive event listener invocation.\",\n data.passiveListener\n )\n }\n return\n }\n if (!data.event.cancelable) {\n return\n }\n\n data.canceled = true\n if (typeof data.event.preventDefault === \"function\") {\n data.event.preventDefault()\n }\n}\n\n/**\n * @see https://dom.spec.whatwg.org/#interface-event\n * @private\n */\n/**\n * The event wrapper.\n * @constructor\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Event|{type:string}} event The original event to wrap.\n */\nfunction Event(eventTarget, event) {\n privateData.set(this, {\n eventTarget,\n event,\n eventPhase: 2,\n currentTarget: eventTarget,\n canceled: false,\n stopped: false,\n immediateStopped: false,\n passiveListener: null,\n timeStamp: event.timeStamp || Date.now(),\n })\n\n // https://heycam.github.io/webidl/#Unforgeable\n Object.defineProperty(this, \"isTrusted\", { value: false, enumerable: true })\n\n // Define accessors\n const keys = Object.keys(event)\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in this)) {\n Object.defineProperty(this, key, defineRedirectDescriptor(key))\n }\n }\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEvent.prototype = {\n /**\n * The type of this event.\n * @type {string}\n */\n get type() {\n return pd(this).event.type\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get target() {\n return pd(this).eventTarget\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get currentTarget() {\n return pd(this).currentTarget\n },\n\n /**\n * @returns {EventTarget[]} The composed path of this event.\n */\n composedPath() {\n const currentTarget = pd(this).currentTarget\n if (currentTarget == null) {\n return []\n }\n return [currentTarget]\n },\n\n /**\n * Constant of NONE.\n * @type {number}\n */\n get NONE() {\n return 0\n },\n\n /**\n * Constant of CAPTURING_PHASE.\n * @type {number}\n */\n get CAPTURING_PHASE() {\n return 1\n },\n\n /**\n * Constant of AT_TARGET.\n * @type {number}\n */\n get AT_TARGET() {\n return 2\n },\n\n /**\n * Constant of BUBBLING_PHASE.\n * @type {number}\n */\n get BUBBLING_PHASE() {\n return 3\n },\n\n /**\n * The target of this event.\n * @type {number}\n */\n get eventPhase() {\n return pd(this).eventPhase\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopPropagation() {\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.stopPropagation === \"function\") {\n data.event.stopPropagation()\n }\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopImmediatePropagation() {\n const data = pd(this)\n\n data.stopped = true\n data.immediateStopped = true\n if (typeof data.event.stopImmediatePropagation === \"function\") {\n data.event.stopImmediatePropagation()\n }\n },\n\n /**\n * The flag to be bubbling.\n * @type {boolean}\n */\n get bubbles() {\n return Boolean(pd(this).event.bubbles)\n },\n\n /**\n * The flag to be cancelable.\n * @type {boolean}\n */\n get cancelable() {\n return Boolean(pd(this).event.cancelable)\n },\n\n /**\n * Cancel this event.\n * @returns {void}\n */\n preventDefault() {\n setCancelFlag(pd(this))\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n */\n get defaultPrevented() {\n return pd(this).canceled\n },\n\n /**\n * The flag to be composed.\n * @type {boolean}\n */\n get composed() {\n return Boolean(pd(this).event.composed)\n },\n\n /**\n * The unix time of this event.\n * @type {number}\n */\n get timeStamp() {\n return pd(this).timeStamp\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n * @deprecated\n */\n get srcElement() {\n return pd(this).eventTarget\n },\n\n /**\n * The flag to stop event bubbling.\n * @type {boolean}\n * @deprecated\n */\n get cancelBubble() {\n return pd(this).stopped\n },\n set cancelBubble(value) {\n if (!value) {\n return\n }\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.cancelBubble === \"boolean\") {\n data.event.cancelBubble = true\n }\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n * @deprecated\n */\n get returnValue() {\n return !pd(this).canceled\n },\n set returnValue(value) {\n if (!value) {\n setCancelFlag(pd(this))\n }\n },\n\n /**\n * Initialize this event object. But do nothing under event dispatching.\n * @param {string} type The event type.\n * @param {boolean} [bubbles=false] The flag to be possible to bubble up.\n * @param {boolean} [cancelable=false] The flag to be possible to cancel.\n * @deprecated\n */\n initEvent() {\n // Do nothing.\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(Event.prototype, \"constructor\", {\n value: Event,\n configurable: true,\n writable: true,\n})\n\n// Ensure `event instanceof window.Event` is `true`.\nif (typeof window !== \"undefined\" && typeof window.Event !== \"undefined\") {\n Object.setPrototypeOf(Event.prototype, window.Event.prototype)\n\n // Make association for wrappers.\n wrappers.set(window.Event.prototype, Event)\n}\n\n/**\n * Get the property descriptor to redirect a given property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to redirect the property.\n * @private\n */\nfunction defineRedirectDescriptor(key) {\n return {\n get() {\n return pd(this).event[key]\n },\n set(value) {\n pd(this).event[key] = value\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Get the property descriptor to call a given method property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to call the method property.\n * @private\n */\nfunction defineCallDescriptor(key) {\n return {\n value() {\n const event = pd(this).event\n return event[key].apply(event, arguments)\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define new wrapper class.\n * @param {Function} BaseEvent The base wrapper class.\n * @param {Object} proto The prototype of the original event.\n * @returns {Function} The defined wrapper class.\n * @private\n */\nfunction defineWrapper(BaseEvent, proto) {\n const keys = Object.keys(proto)\n if (keys.length === 0) {\n return BaseEvent\n }\n\n /** CustomEvent */\n function CustomEvent(eventTarget, event) {\n BaseEvent.call(this, eventTarget, event)\n }\n\n CustomEvent.prototype = Object.create(BaseEvent.prototype, {\n constructor: { value: CustomEvent, configurable: true, writable: true },\n })\n\n // Define accessors.\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in BaseEvent.prototype)) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key)\n const isFunc = typeof descriptor.value === \"function\"\n Object.defineProperty(\n CustomEvent.prototype,\n key,\n isFunc\n ? defineCallDescriptor(key)\n : defineRedirectDescriptor(key)\n )\n }\n }\n\n return CustomEvent\n}\n\n/**\n * Get the wrapper class of a given prototype.\n * @param {Object} proto The prototype of the original event to get its wrapper.\n * @returns {Function} The wrapper class.\n * @private\n */\nfunction getWrapper(proto) {\n if (proto == null || proto === Object.prototype) {\n return Event\n }\n\n let wrapper = wrappers.get(proto)\n if (wrapper == null) {\n wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto)\n wrappers.set(proto, wrapper)\n }\n return wrapper\n}\n\n/**\n * Wrap a given event to management a dispatching.\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Object} event The event to wrap.\n * @returns {Event} The wrapper instance.\n * @private\n */\nexport function wrapEvent(eventTarget, event) {\n const Wrapper = getWrapper(Object.getPrototypeOf(event))\n return new Wrapper(eventTarget, event)\n}\n\n/**\n * Get the immediateStopped flag of a given event.\n * @param {Event} event The event to get.\n * @returns {boolean} The flag to stop propagation immediately.\n * @private\n */\nexport function isStopped(event) {\n return pd(event).immediateStopped\n}\n\n/**\n * Set the current event phase of a given event.\n * @param {Event} event The event to set current target.\n * @param {number} eventPhase New event phase.\n * @returns {void}\n * @private\n */\nexport function setEventPhase(event, eventPhase) {\n pd(event).eventPhase = eventPhase\n}\n\n/**\n * Set the current target of a given event.\n * @param {Event} event The event to set current target.\n * @param {EventTarget|null} currentTarget New current target.\n * @returns {void}\n * @private\n */\nexport function setCurrentTarget(event, currentTarget) {\n pd(event).currentTarget = currentTarget\n}\n\n/**\n * Set a passive listener of a given event.\n * @param {Event} event The event to set current target.\n * @param {Function|null} passiveListener New passive listener.\n * @returns {void}\n * @private\n */\nexport function setPassiveListener(event, passiveListener) {\n pd(event).passiveListener = passiveListener\n}\n","import {\n isStopped,\n setCurrentTarget,\n setEventPhase,\n setPassiveListener,\n wrapEvent,\n} from \"./event.mjs\"\n\n/**\n * @typedef {object} ListenerNode\n * @property {Function} listener\n * @property {1|2|3} listenerType\n * @property {boolean} passive\n * @property {boolean} once\n * @property {ListenerNode|null} next\n * @private\n */\n\n/**\n * @type {WeakMap>}\n * @private\n */\nconst listenersMap = new WeakMap()\n\n// Listener types\nconst CAPTURE = 1\nconst BUBBLE = 2\nconst ATTRIBUTE = 3\n\n/**\n * Check whether a given value is an object or not.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is an object.\n */\nfunction isObject(x) {\n return x !== null && typeof x === \"object\" //eslint-disable-line no-restricted-syntax\n}\n\n/**\n * Get listeners.\n * @param {EventTarget} eventTarget The event target to get.\n * @returns {Map} The listeners.\n * @private\n */\nfunction getListeners(eventTarget) {\n const listeners = listenersMap.get(eventTarget)\n if (listeners == null) {\n throw new TypeError(\n \"'this' is expected an EventTarget object, but got another value.\"\n )\n }\n return listeners\n}\n\n/**\n * Get the property descriptor for the event attribute of a given event.\n * @param {string} eventName The event name to get property descriptor.\n * @returns {PropertyDescriptor} The property descriptor.\n * @private\n */\nfunction defineEventAttributeDescriptor(eventName) {\n return {\n get() {\n const listeners = getListeners(this)\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n return node.listener\n }\n node = node.next\n }\n return null\n },\n\n set(listener) {\n if (typeof listener !== \"function\" && !isObject(listener)) {\n listener = null // eslint-disable-line no-param-reassign\n }\n const listeners = getListeners(this)\n\n // Traverse to the tail while removing old value.\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n // Remove old value.\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n node = node.next\n }\n\n // Add new value.\n if (listener !== null) {\n const newNode = {\n listener,\n listenerType: ATTRIBUTE,\n passive: false,\n once: false,\n next: null,\n }\n if (prev === null) {\n listeners.set(eventName, newNode)\n } else {\n prev.next = newNode\n }\n }\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define an event attribute (e.g. `eventTarget.onclick`).\n * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.\n * @param {string} eventName The event name to define.\n * @returns {void}\n */\nfunction defineEventAttribute(eventTargetPrototype, eventName) {\n Object.defineProperty(\n eventTargetPrototype,\n `on${eventName}`,\n defineEventAttributeDescriptor(eventName)\n )\n}\n\n/**\n * Define a custom EventTarget with event attributes.\n * @param {string[]} eventNames Event names for event attributes.\n * @returns {EventTarget} The custom EventTarget.\n * @private\n */\nfunction defineCustomEventTarget(eventNames) {\n /** CustomEventTarget */\n function CustomEventTarget() {\n EventTarget.call(this)\n }\n\n CustomEventTarget.prototype = Object.create(EventTarget.prototype, {\n constructor: {\n value: CustomEventTarget,\n configurable: true,\n writable: true,\n },\n })\n\n for (let i = 0; i < eventNames.length; ++i) {\n defineEventAttribute(CustomEventTarget.prototype, eventNames[i])\n }\n\n return CustomEventTarget\n}\n\n/**\n * EventTarget.\n *\n * - This is constructor if no arguments.\n * - This is a function which returns a CustomEventTarget constructor if there are arguments.\n *\n * For example:\n *\n * class A extends EventTarget {}\n * class B extends EventTarget(\"message\") {}\n * class C extends EventTarget(\"message\", \"error\") {}\n * class D extends EventTarget([\"message\", \"error\"]) {}\n */\nfunction EventTarget() {\n /*eslint-disable consistent-return */\n if (this instanceof EventTarget) {\n listenersMap.set(this, new Map())\n return\n }\n if (arguments.length === 1 && Array.isArray(arguments[0])) {\n return defineCustomEventTarget(arguments[0])\n }\n if (arguments.length > 0) {\n const types = new Array(arguments.length)\n for (let i = 0; i < arguments.length; ++i) {\n types[i] = arguments[i]\n }\n return defineCustomEventTarget(types)\n }\n throw new TypeError(\"Cannot call a class as a function\")\n /*eslint-enable consistent-return */\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEventTarget.prototype = {\n /**\n * Add a given listener to this event target.\n * @param {string} eventName The event name to add.\n * @param {Function} listener The listener to add.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n addEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n if (typeof listener !== \"function\" && !isObject(listener)) {\n throw new TypeError(\"'listener' should be a function or an object.\")\n }\n\n const listeners = getListeners(this)\n const optionsIsObj = isObject(options)\n const capture = optionsIsObj\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n const newNode = {\n listener,\n listenerType,\n passive: optionsIsObj && Boolean(options.passive),\n once: optionsIsObj && Boolean(options.once),\n next: null,\n }\n\n // Set it as the first node if the first node is null.\n let node = listeners.get(eventName)\n if (node === undefined) {\n listeners.set(eventName, newNode)\n return\n }\n\n // Traverse to the tail while checking duplication..\n let prev = null\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n // Should ignore duplication.\n return\n }\n prev = node\n node = node.next\n }\n\n // Add it.\n prev.next = newNode\n },\n\n /**\n * Remove a given listener from this event target.\n * @param {string} eventName The event name to remove.\n * @param {Function} listener The listener to remove.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n removeEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n\n const listeners = getListeners(this)\n const capture = isObject(options)\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n return\n }\n\n prev = node\n node = node.next\n }\n },\n\n /**\n * Dispatch a given event.\n * @param {Event|{type:string}} event The event to dispatch.\n * @returns {boolean} `false` if canceled.\n */\n dispatchEvent(event) {\n if (event == null || typeof event.type !== \"string\") {\n throw new TypeError('\"event.type\" should be a string.')\n }\n\n // If listeners aren't registered, terminate.\n const listeners = getListeners(this)\n const eventName = event.type\n let node = listeners.get(eventName)\n if (node == null) {\n return true\n }\n\n // Since we cannot rewrite several properties, so wrap object.\n const wrappedEvent = wrapEvent(this, event)\n\n // This doesn't process capturing phase and bubbling phase.\n // This isn't participating in a tree.\n let prev = null\n while (node != null) {\n // Remove this listener if it's once\n if (node.once) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n // Call this listener\n setPassiveListener(\n wrappedEvent,\n node.passive ? node.listener : null\n )\n if (typeof node.listener === \"function\") {\n try {\n node.listener.call(this, wrappedEvent)\n } catch (err) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(err)\n }\n }\n } else if (\n node.listenerType !== ATTRIBUTE &&\n typeof node.listener.handleEvent === \"function\"\n ) {\n node.listener.handleEvent(wrappedEvent)\n }\n\n // Break if `event.stopImmediatePropagation` was called.\n if (isStopped(wrappedEvent)) {\n break\n }\n\n node = node.next\n }\n setPassiveListener(wrappedEvent, null)\n setEventPhase(wrappedEvent, 0)\n setCurrentTarget(wrappedEvent, null)\n\n return !wrappedEvent.defaultPrevented\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(EventTarget.prototype, \"constructor\", {\n value: EventTarget,\n configurable: true,\n writable: true,\n})\n\n// Ensure `eventTarget instanceof window.EventTarget` is `true`.\nif (\n typeof window !== \"undefined\" &&\n typeof window.EventTarget !== \"undefined\"\n) {\n Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype)\n}\n\nexport { defineEventAttribute, EventTarget }\nexport default EventTarget\n"],"names":[],"mappings":";;;;;AAAA;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,WAAW,GAAG,IAAI,OAAO,GAAE;;;;;;;AAOjC,MAAM,QAAQ,GAAG,IAAI,OAAO,GAAE;;;;;;;;AAQ9B,SAAS,EAAE,CAAC,KAAK,EAAE;IACf,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,EAAC;IACnC,OAAO,CAAC,MAAM;QACV,IAAI,IAAI,IAAI;QACZ,6CAA6C;QAC7C,KAAK;MACR;IACD,OAAO,IAAI;CACd;;;;;;AAMD,SAAS,aAAa,CAAC,IAAI,EAAE;IACzB,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE;QAC9B;YACI,OAAO,OAAO,KAAK,WAAW;YAC9B,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;UACrC;YACE,OAAO,CAAC,KAAK;gBACT,oEAAoE;gBACpE,IAAI,CAAC,eAAe;cACvB;SACJ;QACD,MAAM;KACT;IACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;QACxB,MAAM;KACT;;IAED,IAAI,CAAC,QAAQ,GAAG,KAAI;IACpB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,UAAU,EAAE;QACjD,IAAI,CAAC,KAAK,CAAC,cAAc,GAAE;KAC9B;CACJ;;;;;;;;;;;;AAYD,SAAS,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE;IAC/B,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE;QAClB,WAAW;QACX,KAAK;QACL,UAAU,EAAE,CAAC;QACb,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,IAAI;QACrB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;KAC3C,EAAC;;;IAGF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAC;;;IAG5E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAC;QACnB,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE;YAChB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,wBAAwB,CAAC,GAAG,CAAC,EAAC;SAClE;KACJ;CACJ;;;AAGD,KAAK,CAAC,SAAS,GAAG;;;;;IAKd,IAAI,IAAI,GAAG;QACP,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI;KAC7B;;;;;;IAMD,IAAI,MAAM,GAAG;QACT,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW;KAC9B;;;;;;IAMD,IAAI,aAAa,GAAG;QAChB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa;KAChC;;;;;IAKD,YAAY,GAAG;QACX,MAAM,aAAa,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,cAAa;QAC5C,IAAI,aAAa,IAAI,IAAI,EAAE;YACvB,OAAO,EAAE;SACZ;QACD,OAAO,CAAC,aAAa,CAAC;KACzB;;;;;;IAMD,IAAI,IAAI,GAAG;QACP,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,eAAe,GAAG;QAClB,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,SAAS,GAAG;QACZ,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,cAAc,GAAG;QACjB,OAAO,CAAC;KACX;;;;;;IAMD,IAAI,UAAU,GAAG;QACb,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU;KAC7B;;;;;;IAMD,eAAe,GAAG;QACd,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe,KAAK,UAAU,EAAE;YAClD,IAAI,CAAC,KAAK,CAAC,eAAe,GAAE;SAC/B;KACJ;;;;;;IAMD,wBAAwB,GAAG;QACvB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,CAAC,gBAAgB,GAAG,KAAI;QAC5B,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,wBAAwB,KAAK,UAAU,EAAE;YAC3D,IAAI,CAAC,KAAK,CAAC,wBAAwB,GAAE;SACxC;KACJ;;;;;;IAMD,IAAI,OAAO,GAAG;QACV,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;KACzC;;;;;;IAMD,IAAI,UAAU,GAAG;QACb,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;KAC5C;;;;;;IAMD,cAAc,GAAG;QACb,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,EAAC;KAC1B;;;;;;IAMD,IAAI,gBAAgB,GAAG;QACnB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ;KAC3B;;;;;;IAMD,IAAI,QAAQ,GAAG;QACX,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC1C;;;;;;IAMD,IAAI,SAAS,GAAG;QACZ,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS;KAC5B;;;;;;;IAOD,IAAI,UAAU,GAAG;QACb,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW;KAC9B;;;;;;;IAOD,IAAI,YAAY,GAAG;QACf,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO;KAC1B;IACD,IAAI,YAAY,CAAC,KAAK,EAAE;QACpB,IAAI,CAAC,KAAK,EAAE;YACR,MAAM;SACT;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAC;;QAErB,IAAI,CAAC,OAAO,GAAG,KAAI;QACnB,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE;YAC9C,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAI;SACjC;KACJ;;;;;;;IAOD,IAAI,WAAW,GAAG;QACd,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ;KAC5B;IACD,IAAI,WAAW,CAAC,KAAK,EAAE;QACnB,IAAI,CAAC,KAAK,EAAE;YACR,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,EAAC;SAC1B;KACJ;;;;;;;;;IASD,SAAS,GAAG;;KAEX;EACJ;;;AAGD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE;IAClD,KAAK,EAAE,KAAK;IACZ,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,IAAI;CACjB,EAAC;;;AAGF,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,WAAW,EAAE;IACtE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAC;;;IAG9D,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAC;CAC9C;;;;;;;;AAQD,SAAS,wBAAwB,CAAC,GAAG,EAAE;IACnC,OAAO;QACH,GAAG,GAAG;YACF,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;SAC7B;QACD,GAAG,CAAC,KAAK,EAAE;YACP,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,MAAK;SAC9B;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;AAQD,SAAS,oBAAoB,CAAC,GAAG,EAAE;IAC/B,OAAO;QACH,KAAK,GAAG;YACJ,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,MAAK;YAC5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;SAC5C;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;;AASD,SAAS,aAAa,CAAC,SAAS,EAAE,KAAK,EAAE;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACnB,OAAO,SAAS;KACnB;;;IAGD,SAAS,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE;QACrC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAC;KAC3C;;IAED,WAAW,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE;QACvD,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;KAC1E,EAAC;;;IAGF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAC;QACnB,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE;YAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,EAAC;YAC9D,MAAM,MAAM,GAAG,OAAO,UAAU,CAAC,KAAK,KAAK,WAAU;YACrD,MAAM,CAAC,cAAc;gBACjB,WAAW,CAAC,SAAS;gBACrB,GAAG;gBACH,MAAM;sBACA,oBAAoB,CAAC,GAAG,CAAC;sBACzB,wBAAwB,CAAC,GAAG,CAAC;cACtC;SACJ;KACJ;;IAED,OAAO,WAAW;CACrB;;;;;;;;AAQD,SAAS,UAAU,CAAC,KAAK,EAAE;IACvB,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,EAAE;QAC7C,OAAO,KAAK;KACf;;IAED,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAC;IACjC,IAAI,OAAO,IAAI,IAAI,EAAE;QACjB,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAC;QACxE,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAC;KAC/B;IACD,OAAO,OAAO;CACjB;;;;;;;;;AASD,AAAO,SAAS,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE;IAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAC;IACxD,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC;CACzC;;;;;;;;AAQD,AAAO,SAAS,SAAS,CAAC,KAAK,EAAE;IAC7B,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,gBAAgB;CACpC;;;;;;;;;AASD,AAAO,SAAS,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE;IAC7C,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,WAAU;CACpC;;;;;;;;;AASD,AAAO,SAAS,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE;IACnD,EAAE,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,cAAa;CAC1C;;;;;;;;;AASD,AAAO,SAAS,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE;IACvD,EAAE,CAAC,KAAK,CAAC,CAAC,eAAe,GAAG,gBAAe;CAC9C;;ACtdD;;;;;;;;;;;;;;AAcA,MAAM,YAAY,GAAG,IAAI,OAAO,GAAE;;;AAGlC,MAAM,OAAO,GAAG,EAAC;AACjB,MAAM,MAAM,GAAG,EAAC;AAChB,MAAM,SAAS,GAAG,EAAC;;;;;;;AAOnB,SAAS,QAAQ,CAAC,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;CAC7C;;;;;;;;AAQD,SAAS,YAAY,CAAC,WAAW,EAAE;IAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,EAAC;IAC/C,IAAI,SAAS,IAAI,IAAI,EAAE;QACnB,MAAM,IAAI,SAAS;YACf,kEAAkE;SACrE;KACJ;IACD,OAAO,SAAS;CACnB;;;;;;;;AAQD,SAAS,8BAA8B,CAAC,SAAS,EAAE;IAC/C,OAAO;QACH,GAAG,GAAG;YACF,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;YACpC,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;YACnC,OAAO,IAAI,IAAI,IAAI,EAAE;gBACjB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;oBACjC,OAAO,IAAI,CAAC,QAAQ;iBACvB;gBACD,IAAI,GAAG,IAAI,CAAC,KAAI;aACnB;YACD,OAAO,IAAI;SACd;;QAED,GAAG,CAAC,QAAQ,EAAE;YACV,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;gBACvD,QAAQ,GAAG,KAAI;aAClB;YACD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;;;YAGpC,IAAI,IAAI,GAAG,KAAI;YACf,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;YACnC,OAAO,IAAI,IAAI,IAAI,EAAE;gBACjB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;;oBAEjC,IAAI,IAAI,KAAK,IAAI,EAAE;wBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;qBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;wBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;qBACtC,MAAM;wBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;qBAC9B;iBACJ,MAAM;oBACH,IAAI,GAAG,KAAI;iBACd;;gBAED,IAAI,GAAG,IAAI,CAAC,KAAI;aACnB;;;YAGD,IAAI,QAAQ,KAAK,IAAI,EAAE;gBACnB,MAAM,OAAO,GAAG;oBACZ,QAAQ;oBACR,YAAY,EAAE,SAAS;oBACvB,OAAO,EAAE,KAAK;oBACd,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,IAAI;kBACb;gBACD,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAC;iBACpC,MAAM;oBACH,IAAI,CAAC,IAAI,GAAG,QAAO;iBACtB;aACJ;SACJ;QACD,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACnB;CACJ;;;;;;;;AAQD,SAAS,oBAAoB,CAAC,oBAAoB,EAAE,SAAS,EAAE;IAC3D,MAAM,CAAC,cAAc;QACjB,oBAAoB;QACpB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAChB,8BAA8B,CAAC,SAAS,CAAC;MAC5C;CACJ;;;;;;;;AAQD,SAAS,uBAAuB,CAAC,UAAU,EAAE;;IAEzC,SAAS,iBAAiB,GAAG;QACzB,WAAW,CAAC,IAAI,CAAC,IAAI,EAAC;KACzB;;IAED,iBAAiB,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;QAC/D,WAAW,EAAE;YACT,KAAK,EAAE,iBAAiB;YACxB,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;SACjB;KACJ,EAAC;;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QACxC,oBAAoB,CAAC,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,EAAC;KACnE;;IAED,OAAO,iBAAiB;CAC3B;;;;;;;;;;;;;;;AAeD,SAAS,WAAW,GAAG;;IAEnB,IAAI,IAAI,YAAY,WAAW,EAAE;QAC7B,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAC;QACjC,MAAM;KACT;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;QACvD,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;KAC/C;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;QACtB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACvC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,EAAC;SAC1B;QACD,OAAO,uBAAuB,CAAC,KAAK,CAAC;KACxC;IACD,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC;;CAE3D;;;AAGD,WAAW,CAAC,SAAS,GAAG;;;;;;;;IAQpB,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC3C,IAAI,QAAQ,IAAI,IAAI,EAAE;YAClB,MAAM;SACT;QACD,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACvD,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC;SACvE;;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,EAAC;QACtC,MAAM,OAAO,GAAG,YAAY;cACtB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;cACxB,OAAO,CAAC,OAAO,EAAC;QACtB,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,OAAM;QAC/C,MAAM,OAAO,GAAG;YACZ,QAAQ;YACR,YAAY;YACZ,OAAO,EAAE,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YACjD,IAAI,EAAE,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAC3C,IAAI,EAAE,IAAI;UACb;;;QAGD,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,IAAI,IAAI,KAAK,SAAS,EAAE;YACpB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAC;YACjC,MAAM;SACT;;;QAGD,IAAI,IAAI,GAAG,KAAI;QACf,OAAO,IAAI,IAAI,IAAI,EAAE;YACjB;gBACI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAC1B,IAAI,CAAC,YAAY,KAAK,YAAY;cACpC;;gBAEE,MAAM;aACT;YACD,IAAI,GAAG,KAAI;YACX,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;;;QAGD,IAAI,CAAC,IAAI,GAAG,QAAO;KACtB;;;;;;;;;IASD,mBAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC9C,IAAI,QAAQ,IAAI,IAAI,EAAE;YAClB,MAAM;SACT;;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;cAC3B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;cACxB,OAAO,CAAC,OAAO,EAAC;QACtB,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,OAAM;;QAE/C,IAAI,IAAI,GAAG,KAAI;QACf,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,OAAO,IAAI,IAAI,IAAI,EAAE;YACjB;gBACI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAC1B,IAAI,CAAC,YAAY,KAAK,YAAY;cACpC;gBACE,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;iBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;oBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;iBACtC,MAAM;oBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;iBAC9B;gBACD,MAAM;aACT;;YAED,IAAI,GAAG,KAAI;YACX,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;KACJ;;;;;;;IAOD,aAAa,CAAC,KAAK,EAAE;QACjB,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YACjD,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC;SAC1D;;;QAGD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAC;QACpC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAI;QAC5B,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,EAAC;QACnC,IAAI,IAAI,IAAI,IAAI,EAAE;YACd,OAAO,IAAI;SACd;;;QAGD,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAC;;;;QAI3C,IAAI,IAAI,GAAG,KAAI;QACf,OAAO,IAAI,IAAI,IAAI,EAAE;;YAEjB,IAAI,IAAI,CAAC,IAAI,EAAE;gBACX,IAAI,IAAI,KAAK,IAAI,EAAE;oBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAI;iBACxB,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;oBAC3B,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAC;iBACtC,MAAM;oBACH,SAAS,CAAC,MAAM,CAAC,SAAS,EAAC;iBAC9B;aACJ,MAAM;gBACH,IAAI,GAAG,KAAI;aACd;;;YAGD,kBAAkB;gBACd,YAAY;gBACZ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI;cACtC;YACD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE;gBACrC,IAAI;oBACA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAC;iBACzC,CAAC,OAAO,GAAG,EAAE;oBACV;wBACI,OAAO,OAAO,KAAK,WAAW;wBAC9B,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;sBACrC;wBACE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAC;qBACrB;iBACJ;aACJ,MAAM;gBACH,IAAI,CAAC,YAAY,KAAK,SAAS;gBAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,UAAU;cACjD;gBACE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAC;aAC1C;;;YAGD,IAAI,SAAS,CAAC,YAAY,CAAC,EAAE;gBACzB,KAAK;aACR;;YAED,IAAI,GAAG,IAAI,CAAC,KAAI;SACnB;QACD,kBAAkB,CAAC,YAAY,EAAE,IAAI,EAAC;QACtC,aAAa,CAAC,YAAY,EAAE,CAAC,EAAC;QAC9B,gBAAgB,CAAC,YAAY,EAAE,IAAI,EAAC;;QAEpC,OAAO,CAAC,YAAY,CAAC,gBAAgB;KACxC;EACJ;;;AAGD,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,aAAa,EAAE;IACxD,KAAK,EAAE,WAAW;IAClB,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,IAAI;CACjB,EAAC;;;AAGF;IACI,OAAO,MAAM,KAAK,WAAW;IAC7B,OAAO,MAAM,CAAC,WAAW,KAAK,WAAW;EAC3C;IACE,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,EAAC;CAC7E;;;;;"} \ No newline at end of file diff --git a/node_modules/event-target-shim/dist/event-target-shim.umd.js b/node_modules/event-target-shim/dist/event-target-shim.umd.js new file mode 100644 index 0000000..e7cf5d4 --- /dev/null +++ b/node_modules/event-target-shim/dist/event-target-shim.umd.js @@ -0,0 +1,6 @@ +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a=a||self,b(a.EventTargetShim={}))})(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){var b=u.get(a);return console.assert(null!=b,"'this' is expected an Event object, but got",a),b}function d(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 e(a,b){u.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}\n * @private\n */\nconst privateData = new WeakMap()\n\n/**\n * Cache for wrapper classes.\n * @type {WeakMap}\n * @private\n */\nconst wrappers = new WeakMap()\n\n/**\n * Get private data.\n * @param {Event} event The event object to get private data.\n * @returns {PrivateData} The private data of the event.\n * @private\n */\nfunction pd(event) {\n const retv = privateData.get(event)\n console.assert(\n retv != null,\n \"'this' is expected an Event object, but got\",\n event\n )\n return retv\n}\n\n/**\n * https://dom.spec.whatwg.org/#set-the-canceled-flag\n * @param data {PrivateData} private data.\n */\nfunction setCancelFlag(data) {\n if (data.passiveListener != null) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(\n \"Unable to preventDefault inside passive event listener invocation.\",\n data.passiveListener\n )\n }\n return\n }\n if (!data.event.cancelable) {\n return\n }\n\n data.canceled = true\n if (typeof data.event.preventDefault === \"function\") {\n data.event.preventDefault()\n }\n}\n\n/**\n * @see https://dom.spec.whatwg.org/#interface-event\n * @private\n */\n/**\n * The event wrapper.\n * @constructor\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Event|{type:string}} event The original event to wrap.\n */\nfunction Event(eventTarget, event) {\n privateData.set(this, {\n eventTarget,\n event,\n eventPhase: 2,\n currentTarget: eventTarget,\n canceled: false,\n stopped: false,\n immediateStopped: false,\n passiveListener: null,\n timeStamp: event.timeStamp || Date.now(),\n })\n\n // https://heycam.github.io/webidl/#Unforgeable\n Object.defineProperty(this, \"isTrusted\", { value: false, enumerable: true })\n\n // Define accessors\n const keys = Object.keys(event)\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in this)) {\n Object.defineProperty(this, key, defineRedirectDescriptor(key))\n }\n }\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEvent.prototype = {\n /**\n * The type of this event.\n * @type {string}\n */\n get type() {\n return pd(this).event.type\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get target() {\n return pd(this).eventTarget\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n */\n get currentTarget() {\n return pd(this).currentTarget\n },\n\n /**\n * @returns {EventTarget[]} The composed path of this event.\n */\n composedPath() {\n const currentTarget = pd(this).currentTarget\n if (currentTarget == null) {\n return []\n }\n return [currentTarget]\n },\n\n /**\n * Constant of NONE.\n * @type {number}\n */\n get NONE() {\n return 0\n },\n\n /**\n * Constant of CAPTURING_PHASE.\n * @type {number}\n */\n get CAPTURING_PHASE() {\n return 1\n },\n\n /**\n * Constant of AT_TARGET.\n * @type {number}\n */\n get AT_TARGET() {\n return 2\n },\n\n /**\n * Constant of BUBBLING_PHASE.\n * @type {number}\n */\n get BUBBLING_PHASE() {\n return 3\n },\n\n /**\n * The target of this event.\n * @type {number}\n */\n get eventPhase() {\n return pd(this).eventPhase\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopPropagation() {\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.stopPropagation === \"function\") {\n data.event.stopPropagation()\n }\n },\n\n /**\n * Stop event bubbling.\n * @returns {void}\n */\n stopImmediatePropagation() {\n const data = pd(this)\n\n data.stopped = true\n data.immediateStopped = true\n if (typeof data.event.stopImmediatePropagation === \"function\") {\n data.event.stopImmediatePropagation()\n }\n },\n\n /**\n * The flag to be bubbling.\n * @type {boolean}\n */\n get bubbles() {\n return Boolean(pd(this).event.bubbles)\n },\n\n /**\n * The flag to be cancelable.\n * @type {boolean}\n */\n get cancelable() {\n return Boolean(pd(this).event.cancelable)\n },\n\n /**\n * Cancel this event.\n * @returns {void}\n */\n preventDefault() {\n setCancelFlag(pd(this))\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n */\n get defaultPrevented() {\n return pd(this).canceled\n },\n\n /**\n * The flag to be composed.\n * @type {boolean}\n */\n get composed() {\n return Boolean(pd(this).event.composed)\n },\n\n /**\n * The unix time of this event.\n * @type {number}\n */\n get timeStamp() {\n return pd(this).timeStamp\n },\n\n /**\n * The target of this event.\n * @type {EventTarget}\n * @deprecated\n */\n get srcElement() {\n return pd(this).eventTarget\n },\n\n /**\n * The flag to stop event bubbling.\n * @type {boolean}\n * @deprecated\n */\n get cancelBubble() {\n return pd(this).stopped\n },\n set cancelBubble(value) {\n if (!value) {\n return\n }\n const data = pd(this)\n\n data.stopped = true\n if (typeof data.event.cancelBubble === \"boolean\") {\n data.event.cancelBubble = true\n }\n },\n\n /**\n * The flag to indicate cancellation state.\n * @type {boolean}\n * @deprecated\n */\n get returnValue() {\n return !pd(this).canceled\n },\n set returnValue(value) {\n if (!value) {\n setCancelFlag(pd(this))\n }\n },\n\n /**\n * Initialize this event object. But do nothing under event dispatching.\n * @param {string} type The event type.\n * @param {boolean} [bubbles=false] The flag to be possible to bubble up.\n * @param {boolean} [cancelable=false] The flag to be possible to cancel.\n * @deprecated\n */\n initEvent() {\n // Do nothing.\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(Event.prototype, \"constructor\", {\n value: Event,\n configurable: true,\n writable: true,\n})\n\n// Ensure `event instanceof window.Event` is `true`.\nif (typeof window !== \"undefined\" && typeof window.Event !== \"undefined\") {\n Object.setPrototypeOf(Event.prototype, window.Event.prototype)\n\n // Make association for wrappers.\n wrappers.set(window.Event.prototype, Event)\n}\n\n/**\n * Get the property descriptor to redirect a given property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to redirect the property.\n * @private\n */\nfunction defineRedirectDescriptor(key) {\n return {\n get() {\n return pd(this).event[key]\n },\n set(value) {\n pd(this).event[key] = value\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Get the property descriptor to call a given method property.\n * @param {string} key Property name to define property descriptor.\n * @returns {PropertyDescriptor} The property descriptor to call the method property.\n * @private\n */\nfunction defineCallDescriptor(key) {\n return {\n value() {\n const event = pd(this).event\n return event[key].apply(event, arguments)\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define new wrapper class.\n * @param {Function} BaseEvent The base wrapper class.\n * @param {Object} proto The prototype of the original event.\n * @returns {Function} The defined wrapper class.\n * @private\n */\nfunction defineWrapper(BaseEvent, proto) {\n const keys = Object.keys(proto)\n if (keys.length === 0) {\n return BaseEvent\n }\n\n /** CustomEvent */\n function CustomEvent(eventTarget, event) {\n BaseEvent.call(this, eventTarget, event)\n }\n\n CustomEvent.prototype = Object.create(BaseEvent.prototype, {\n constructor: { value: CustomEvent, configurable: true, writable: true },\n })\n\n // Define accessors.\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i]\n if (!(key in BaseEvent.prototype)) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key)\n const isFunc = typeof descriptor.value === \"function\"\n Object.defineProperty(\n CustomEvent.prototype,\n key,\n isFunc\n ? defineCallDescriptor(key)\n : defineRedirectDescriptor(key)\n )\n }\n }\n\n return CustomEvent\n}\n\n/**\n * Get the wrapper class of a given prototype.\n * @param {Object} proto The prototype of the original event to get its wrapper.\n * @returns {Function} The wrapper class.\n * @private\n */\nfunction getWrapper(proto) {\n if (proto == null || proto === Object.prototype) {\n return Event\n }\n\n let wrapper = wrappers.get(proto)\n if (wrapper == null) {\n wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto)\n wrappers.set(proto, wrapper)\n }\n return wrapper\n}\n\n/**\n * Wrap a given event to management a dispatching.\n * @param {EventTarget} eventTarget The event target of this dispatching.\n * @param {Object} event The event to wrap.\n * @returns {Event} The wrapper instance.\n * @private\n */\nexport function wrapEvent(eventTarget, event) {\n const Wrapper = getWrapper(Object.getPrototypeOf(event))\n return new Wrapper(eventTarget, event)\n}\n\n/**\n * Get the immediateStopped flag of a given event.\n * @param {Event} event The event to get.\n * @returns {boolean} The flag to stop propagation immediately.\n * @private\n */\nexport function isStopped(event) {\n return pd(event).immediateStopped\n}\n\n/**\n * Set the current event phase of a given event.\n * @param {Event} event The event to set current target.\n * @param {number} eventPhase New event phase.\n * @returns {void}\n * @private\n */\nexport function setEventPhase(event, eventPhase) {\n pd(event).eventPhase = eventPhase\n}\n\n/**\n * Set the current target of a given event.\n * @param {Event} event The event to set current target.\n * @param {EventTarget|null} currentTarget New current target.\n * @returns {void}\n * @private\n */\nexport function setCurrentTarget(event, currentTarget) {\n pd(event).currentTarget = currentTarget\n}\n\n/**\n * Set a passive listener of a given event.\n * @param {Event} event The event to set current target.\n * @param {Function|null} passiveListener New passive listener.\n * @returns {void}\n * @private\n */\nexport function setPassiveListener(event, passiveListener) {\n pd(event).passiveListener = passiveListener\n}\n","import {\n isStopped,\n setCurrentTarget,\n setEventPhase,\n setPassiveListener,\n wrapEvent,\n} from \"./event.mjs\"\n\n/**\n * @typedef {object} ListenerNode\n * @property {Function} listener\n * @property {1|2|3} listenerType\n * @property {boolean} passive\n * @property {boolean} once\n * @property {ListenerNode|null} next\n * @private\n */\n\n/**\n * @type {WeakMap>}\n * @private\n */\nconst listenersMap = new WeakMap()\n\n// Listener types\nconst CAPTURE = 1\nconst BUBBLE = 2\nconst ATTRIBUTE = 3\n\n/**\n * Check whether a given value is an object or not.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is an object.\n */\nfunction isObject(x) {\n return x !== null && typeof x === \"object\" //eslint-disable-line no-restricted-syntax\n}\n\n/**\n * Get listeners.\n * @param {EventTarget} eventTarget The event target to get.\n * @returns {Map} The listeners.\n * @private\n */\nfunction getListeners(eventTarget) {\n const listeners = listenersMap.get(eventTarget)\n if (listeners == null) {\n throw new TypeError(\n \"'this' is expected an EventTarget object, but got another value.\"\n )\n }\n return listeners\n}\n\n/**\n * Get the property descriptor for the event attribute of a given event.\n * @param {string} eventName The event name to get property descriptor.\n * @returns {PropertyDescriptor} The property descriptor.\n * @private\n */\nfunction defineEventAttributeDescriptor(eventName) {\n return {\n get() {\n const listeners = getListeners(this)\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n return node.listener\n }\n node = node.next\n }\n return null\n },\n\n set(listener) {\n if (typeof listener !== \"function\" && !isObject(listener)) {\n listener = null // eslint-disable-line no-param-reassign\n }\n const listeners = getListeners(this)\n\n // Traverse to the tail while removing old value.\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (node.listenerType === ATTRIBUTE) {\n // Remove old value.\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n node = node.next\n }\n\n // Add new value.\n if (listener !== null) {\n const newNode = {\n listener,\n listenerType: ATTRIBUTE,\n passive: false,\n once: false,\n next: null,\n }\n if (prev === null) {\n listeners.set(eventName, newNode)\n } else {\n prev.next = newNode\n }\n }\n },\n configurable: true,\n enumerable: true,\n }\n}\n\n/**\n * Define an event attribute (e.g. `eventTarget.onclick`).\n * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.\n * @param {string} eventName The event name to define.\n * @returns {void}\n */\nfunction defineEventAttribute(eventTargetPrototype, eventName) {\n Object.defineProperty(\n eventTargetPrototype,\n `on${eventName}`,\n defineEventAttributeDescriptor(eventName)\n )\n}\n\n/**\n * Define a custom EventTarget with event attributes.\n * @param {string[]} eventNames Event names for event attributes.\n * @returns {EventTarget} The custom EventTarget.\n * @private\n */\nfunction defineCustomEventTarget(eventNames) {\n /** CustomEventTarget */\n function CustomEventTarget() {\n EventTarget.call(this)\n }\n\n CustomEventTarget.prototype = Object.create(EventTarget.prototype, {\n constructor: {\n value: CustomEventTarget,\n configurable: true,\n writable: true,\n },\n })\n\n for (let i = 0; i < eventNames.length; ++i) {\n defineEventAttribute(CustomEventTarget.prototype, eventNames[i])\n }\n\n return CustomEventTarget\n}\n\n/**\n * EventTarget.\n *\n * - This is constructor if no arguments.\n * - This is a function which returns a CustomEventTarget constructor if there are arguments.\n *\n * For example:\n *\n * class A extends EventTarget {}\n * class B extends EventTarget(\"message\") {}\n * class C extends EventTarget(\"message\", \"error\") {}\n * class D extends EventTarget([\"message\", \"error\"]) {}\n */\nfunction EventTarget() {\n /*eslint-disable consistent-return */\n if (this instanceof EventTarget) {\n listenersMap.set(this, new Map())\n return\n }\n if (arguments.length === 1 && Array.isArray(arguments[0])) {\n return defineCustomEventTarget(arguments[0])\n }\n if (arguments.length > 0) {\n const types = new Array(arguments.length)\n for (let i = 0; i < arguments.length; ++i) {\n types[i] = arguments[i]\n }\n return defineCustomEventTarget(types)\n }\n throw new TypeError(\"Cannot call a class as a function\")\n /*eslint-enable consistent-return */\n}\n\n// Should be enumerable, but class methods are not enumerable.\nEventTarget.prototype = {\n /**\n * Add a given listener to this event target.\n * @param {string} eventName The event name to add.\n * @param {Function} listener The listener to add.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n addEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n if (typeof listener !== \"function\" && !isObject(listener)) {\n throw new TypeError(\"'listener' should be a function or an object.\")\n }\n\n const listeners = getListeners(this)\n const optionsIsObj = isObject(options)\n const capture = optionsIsObj\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n const newNode = {\n listener,\n listenerType,\n passive: optionsIsObj && Boolean(options.passive),\n once: optionsIsObj && Boolean(options.once),\n next: null,\n }\n\n // Set it as the first node if the first node is null.\n let node = listeners.get(eventName)\n if (node === undefined) {\n listeners.set(eventName, newNode)\n return\n }\n\n // Traverse to the tail while checking duplication..\n let prev = null\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n // Should ignore duplication.\n return\n }\n prev = node\n node = node.next\n }\n\n // Add it.\n prev.next = newNode\n },\n\n /**\n * Remove a given listener from this event target.\n * @param {string} eventName The event name to remove.\n * @param {Function} listener The listener to remove.\n * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.\n * @returns {void}\n */\n removeEventListener(eventName, listener, options) {\n if (listener == null) {\n return\n }\n\n const listeners = getListeners(this)\n const capture = isObject(options)\n ? Boolean(options.capture)\n : Boolean(options)\n const listenerType = capture ? CAPTURE : BUBBLE\n\n let prev = null\n let node = listeners.get(eventName)\n while (node != null) {\n if (\n node.listener === listener &&\n node.listenerType === listenerType\n ) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n return\n }\n\n prev = node\n node = node.next\n }\n },\n\n /**\n * Dispatch a given event.\n * @param {Event|{type:string}} event The event to dispatch.\n * @returns {boolean} `false` if canceled.\n */\n dispatchEvent(event) {\n if (event == null || typeof event.type !== \"string\") {\n throw new TypeError('\"event.type\" should be a string.')\n }\n\n // If listeners aren't registered, terminate.\n const listeners = getListeners(this)\n const eventName = event.type\n let node = listeners.get(eventName)\n if (node == null) {\n return true\n }\n\n // Since we cannot rewrite several properties, so wrap object.\n const wrappedEvent = wrapEvent(this, event)\n\n // This doesn't process capturing phase and bubbling phase.\n // This isn't participating in a tree.\n let prev = null\n while (node != null) {\n // Remove this listener if it's once\n if (node.once) {\n if (prev !== null) {\n prev.next = node.next\n } else if (node.next !== null) {\n listeners.set(eventName, node.next)\n } else {\n listeners.delete(eventName)\n }\n } else {\n prev = node\n }\n\n // Call this listener\n setPassiveListener(\n wrappedEvent,\n node.passive ? node.listener : null\n )\n if (typeof node.listener === \"function\") {\n try {\n node.listener.call(this, wrappedEvent)\n } catch (err) {\n if (\n typeof console !== \"undefined\" &&\n typeof console.error === \"function\"\n ) {\n console.error(err)\n }\n }\n } else if (\n node.listenerType !== ATTRIBUTE &&\n typeof node.listener.handleEvent === \"function\"\n ) {\n node.listener.handleEvent(wrappedEvent)\n }\n\n // Break if `event.stopImmediatePropagation` was called.\n if (isStopped(wrappedEvent)) {\n break\n }\n\n node = node.next\n }\n setPassiveListener(wrappedEvent, null)\n setEventPhase(wrappedEvent, 0)\n setCurrentTarget(wrappedEvent, null)\n\n return !wrappedEvent.defaultPrevented\n },\n}\n\n// `constructor` is not enumerable.\nObject.defineProperty(EventTarget.prototype, \"constructor\", {\n value: EventTarget,\n configurable: true,\n writable: true,\n})\n\n// Ensure `eventTarget instanceof window.EventTarget` is `true`.\nif (\n typeof window !== \"undefined\" &&\n typeof window.EventTarget !== \"undefined\"\n) {\n Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype)\n}\n\nexport { defineEventAttribute, EventTarget }\nexport default EventTarget\n"],"names":["pd","event","retv","privateData","get","console","assert","setCancelFlag","data","passiveListener","cancelable","canceled","preventDefault","error","Event","eventTarget","set","eventPhase","currentTarget","stopped","immediateStopped","timeStamp","Date","now","Object","defineProperty","value","enumerable","key","keys","i","length","defineRedirectDescriptor","configurable","defineCallDescriptor","apply","arguments","defineWrapper","BaseEvent","proto","CustomEvent","call","prototype","create","constructor","writable","descriptor","getOwnPropertyDescriptor","isFunc","getWrapper","wrapper","wrappers","getPrototypeOf","wrapEvent","Wrapper","isStopped","setEventPhase","setCurrentTarget","setPassiveListener","isObject","x","_typeof","getListeners","listeners","listenersMap","TypeError","defineEventAttributeDescriptor","eventName","node","listenerType","listener","next","prev","delete","newNode","passive","once","defineEventAttribute","eventTargetPrototype","defineCustomEventTarget","eventNames","CustomEventTarget","EventTarget","Map","Array","isArray","types","WeakMap","type","target","composedPath","NONE","CAPTURING_PHASE","AT_TARGET","BUBBLING_PHASE","stopPropagation","stopImmediatePropagation","bubbles","defaultPrevented","composed","srcElement","cancelBubble","returnValue","initEvent","window","setPrototypeOf","CAPTURE","BUBBLE","addEventListener","options","optionsIsObj","capture","removeEventListener","dispatchEvent","wrappedEvent","err","handleEvent"],"mappings":";;;;wbAkCA,QAASA,CAAAA,CAAT,CAAYC,CAAZ,CAAmB,IACTC,CAAAA,CAAI,CAAGC,CAAW,CAACC,GAAZD,CAAgBF,CAAhBE,QACbE,CAAAA,OAAO,CAACC,MAARD,CACY,IAARH,EAAAA,CADJG,CAEI,6CAFJA,CAGIJ,CAHJI,EAKOH,EAOX,QAASK,CAAAA,CAAT,CAAuBC,CAAvB,CAA6B,OACG,KAAxBA,EAAAA,CAAI,CAACC,eADgB,MAarB,CAACD,CAAI,CAACP,KAALO,CAAWE,UAbS,GAiBzBF,CAAI,CAACG,QAALH,GAjByB,CAkBgB,UAArC,QAAOA,CAAAA,CAAI,CAACP,KAALO,CAAWI,cAlBG,EAmBrBJ,CAAI,CAACP,KAALO,CAAWI,cAAXJ,EAnBqB,QAGE,WAAnB,QAAOH,CAAAA,OAAP,EACyB,UAAzB,QAAOA,CAAAA,OAAO,CAACQ,KAJE,EAMjBR,OAAO,CAACQ,KAARR,CACI,oEADJA,CAEIG,CAAI,CAACC,eAFTJ,CANiB,EAiC7B,QAASS,CAAAA,CAAT,CAAeC,CAAf,CAA4Bd,CAA5B,CAAmC,CAC/BE,CAAW,CAACa,GAAZb,CAAgB,IAAhBA,CAAsB,CAClBY,WAAW,CAAXA,CADkB,CAElBd,KAAK,CAALA,CAFkB,CAGlBgB,UAAU,CAAE,CAHM,CAIlBC,aAAa,CAAEH,CAJG,CAKlBJ,QAAQ,GALU,CAMlBQ,OAAO,GANW,CAOlBC,gBAAgB,GAPE,CAQlBX,eAAe,CAAE,IARC,CASlBY,SAAS,CAAEpB,CAAK,CAACoB,SAANpB,EAAmBqB,IAAI,CAACC,GAALD,EATZ,CAAtBnB,CAD+B,CAc/BqB,MAAM,CAACC,cAAPD,CAAsB,IAAtBA,CAA4B,WAA5BA,CAAyC,CAAEE,KAAK,GAAP,CAAgBC,UAAU,GAA1B,CAAzCH,CAd+B,QAmBrBI,CAAAA,EAFJC,CAAI,CAAGL,MAAM,CAACK,IAAPL,CAAYvB,CAAZuB,EACJM,CAAC,CAAG,EAAGA,CAAC,CAAGD,CAAI,CAACE,OAAQ,EAAED,EACzBF,EAAMC,CAAI,CAACC,CAAD,EACVF,CAAG,GAAI,OACTJ,MAAM,CAACC,cAAPD,CAAsB,IAAtBA,CAA4BI,CAA5BJ,CAAiCQ,CAAwB,CAACJ,CAAD,CAAzDJ,EAyOZ,QAASQ,CAAAA,CAAT,CAAkCJ,CAAlC,CAAuC,OAC5B,CACHxB,GADG,WACG,OACKJ,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAe4B,CAAf5B,CAFR,CAAA,CAIHgB,GAJG,UAICU,EAAO,CACP1B,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAe4B,CAAf5B,EAAsB0B,CALvB,CAAA,CAOHO,YAAY,GAPT,CAQHN,UAAU,GARP,EAkBX,QAASO,CAAAA,CAAT,CAA8BN,CAA9B,CAAmC,OACxB,CACHF,KADG,WACK,IACEzB,CAAAA,CAAK,CAAGD,CAAE,CAAC,IAAD,CAAFA,CAASC,YAChBA,CAAAA,CAAK,CAAC2B,CAAD,CAAL3B,CAAWkC,KAAXlC,CAAiBA,CAAjBA,CAAwBmC,SAAxBnC,CAHR,CAAA,CAKHgC,YAAY,GALT,CAMHN,UAAU,GANP,EAiBX,QAASU,CAAAA,CAAT,CAAuBC,CAAvB,CAAkCC,CAAlC,CAAyC,SAO5BC,CAAAA,EAAYzB,EAAad,EAAO,CACrCqC,CAAS,CAACG,IAAVH,CAAe,IAAfA,CAAqBvB,CAArBuB,CAAkCrC,CAAlCqC,KAPET,CAAAA,CAAI,CAAGL,MAAM,CAACK,IAAPL,CAAYe,CAAZf,KACO,CAAhBK,GAAAA,CAAI,CAACE,aACEO,CAAAA,EAQXE,CAAW,CAACE,SAAZF,CAAwBhB,MAAM,CAACmB,MAAPnB,CAAcc,CAAS,CAACI,SAAxBlB,CAAmC,CACvDoB,WAAW,CAAE,CAAElB,KAAK,CAAEc,CAAT,CAAsBP,YAAY,GAAlC,CAA0CY,QAAQ,GAAlD,CAD0C,CAAnCrB,CAXa,KAgBhC,GACKI,CAAAA,CADL,CAAIE,CAAC,CAAG,EAAGA,CAAC,CAAGD,CAAI,CAACE,OAAQ,EAAED,KACzBF,EAAMC,CAAI,CAACC,CAAD,EACZ,EAAEF,CAAG,GAAIU,CAAAA,CAAS,CAACI,SAAnB,EAA+B,IACzBI,CAAAA,CAAU,CAAGtB,MAAM,CAACuB,wBAAPvB,CAAgCe,CAAhCf,CAAuCI,CAAvCJ,CADY,CAEzBwB,CAAM,CAA+B,UAA5B,QAAOF,CAAAA,CAAU,CAACpB,KAFF,CAG/BF,MAAM,CAACC,cAAPD,CACIgB,CAAW,CAACE,SADhBlB,CAEII,CAFJJ,CAGIwB,CAAM,CACAd,CAAoB,CAACN,CAAD,CADpB,CAEAI,CAAwB,CAACJ,CAAD,CALlCJ,QAUDgB,CAAAA,EASX,QAASS,CAAAA,CAAT,CAAoBV,CAApB,CAA2B,IACV,IAATA,EAAAA,CAAK,EAAYA,CAAK,GAAKf,MAAM,CAACkB,gBAC3B5B,CAAAA,KAGPoC,CAAAA,CAAO,CAAGC,CAAQ,CAAC/C,GAAT+C,CAAaZ,CAAbY,QACC,KAAXD,EAAAA,IACAA,CAAO,CAAGb,CAAa,CAACY,CAAU,CAACzB,MAAM,CAAC4B,cAAP5B,CAAsBe,CAAtBf,CAAD,CAAX,CAA2Ce,CAA3C,EACvBY,CAAQ,CAACnC,GAATmC,CAAaZ,CAAbY,CAAoBD,CAApBC,GAEGD,EAUJ,QAASG,CAAAA,CAAT,CAAmBtC,CAAnB,CAAgCd,CAAhC,CAAuC,IACpCqD,CAAAA,CAAO,CAAGL,CAAU,CAACzB,MAAM,CAAC4B,cAAP5B,CAAsBvB,CAAtBuB,CAAD,QACnB,IAAI8B,CAAAA,CAAJ,CAAYvC,CAAZ,CAAyBd,CAAzB,EASJ,QAASsD,CAAAA,CAAT,CAAmBtD,CAAnB,CAA0B,OACtBD,CAAAA,CAAE,CAACC,CAAD,CAAFD,CAAUoB,iBAUd,QAASoC,CAAAA,CAAT,CAAuBvD,CAAvB,CAA8BgB,CAA9B,CAA0C,CAC7CjB,CAAE,CAACC,CAAD,CAAFD,CAAUiB,UAAVjB,CAAuBiB,EAUpB,QAASwC,CAAAA,CAAT,CAA0BxD,CAA1B,CAAiCiB,CAAjC,CAAgD,CACnDlB,CAAE,CAACC,CAAD,CAAFD,CAAUkB,aAAVlB,CAA0BkB,EAUvB,QAASwC,CAAAA,CAAT,CAA4BzD,CAA5B,CAAmCQ,CAAnC,CAAoD,CACvDT,CAAE,CAACC,CAAD,CAAFD,CAAUS,eAAVT,CAA4BS,EC3bhC,QAASkD,CAAAA,CAAT,CAAkBC,CAAlB,CAAqB,OACJ,KAANA,GAAAA,CAAC,EAA0B,QAAb,GAAAC,EAAOD,GAShC,QAASE,CAAAA,CAAT,CAAsB/C,CAAtB,CAAmC,IACzBgD,CAAAA,CAAS,CAAGC,CAAY,CAAC5D,GAAb4D,CAAiBjD,CAAjBiD,KACD,IAAbD,EAAAA,OACM,IAAIE,CAAAA,SAAJ,CACF,kEADE,QAIHF,CAAAA,EASX,QAASG,CAAAA,CAAT,CAAwCC,CAAxC,CAAmD,OACxC,CACH/D,GADG,WACG,QACI2D,CAAAA,CAAS,CAAGD,CAAY,CAAC,IAAD,CAD5B,CAEEM,CAAI,CAAGL,CAAS,CAAC3D,GAAV2D,CAAcI,CAAdJ,CAFT,CAGa,IAARK,EAAAA,CAHL,EAGmB,IACbA,IAAAA,CAAI,CAACC,mBACED,CAAAA,CAAI,CAACE,SAEhBF,CAAI,CAAGA,CAAI,CAACG,WAET,KAVR,CAAA,CAaHvD,GAbG,UAaCsD,EAAU,CACc,UAApB,QAAOA,CAAAA,CAAP,EAAmCX,CAAQ,CAACW,CAAD,CADrC,GAENA,CAAQ,CAAG,IAFL,SAIJP,CAAAA,CAAS,CAAGD,CAAY,CAAC,IAAD,CAJpB,CAONU,CAAI,CAAG,IAPD,CAQNJ,CAAI,CAAGL,CAAS,CAAC3D,GAAV2D,CAAcI,CAAdJ,CARD,CASK,IAARK,EAAAA,CATG,EAUFA,IAAAA,CAAI,CAACC,YAVH,CAYW,IAATG,GAAAA,CAZF,CAcuB,IAAdJ,GAAAA,CAAI,CAACG,IAdd,CAiBER,CAAS,CAACU,MAAVV,CAAiBI,CAAjBJ,CAjBF,CAeEA,CAAS,CAAC/C,GAAV+C,CAAcI,CAAdJ,CAAyBK,CAAI,CAACG,IAA9BR,CAfF,CAaES,CAAI,CAACD,IAALC,CAAYJ,CAAI,CAACG,IAbnB,CAoBFC,CAAI,CAAGJ,CApBL,CAuBNA,CAAI,CAAGA,CAAI,CAACG,IAvBN,IA2BO,IAAbD,GAAAA,EAAmB,IACbI,CAAAA,CAAO,CAAG,CACZJ,QAAQ,CAARA,CADY,CAEZD,YAAY,EAFA,CAGZM,OAAO,GAHK,CAIZC,IAAI,GAJQ,CAKZL,IAAI,CAAE,IALM,EAOH,IAATC,GAAAA,CARe,CASfT,CAAS,CAAC/C,GAAV+C,CAAcI,CAAdJ,CAAyBW,CAAzBX,CATe,CAWfS,CAAI,CAACD,IAALC,CAAYE,EAnDrB,CAAA,CAuDHzC,YAAY,GAvDT,CAwDHN,UAAU,GAxDP,EAkEX,QAASkD,CAAAA,CAAT,CAA8BC,CAA9B,CAAoDX,CAApD,CAA+D,CAC3D3C,MAAM,CAACC,cAAPD,CACIsD,CADJtD,aAES2C,EAFT3C,CAGI0C,CAA8B,CAACC,CAAD,CAHlC3C,EAaJ,QAASuD,CAAAA,CAAT,CAAiCC,CAAjC,CAA6C,SAEhCC,CAAAA,GAAoB,CACzBC,CAAW,CAACzC,IAAZyC,CAAiB,IAAjBA,EAGJD,CAAiB,CAACvC,SAAlBuC,CAA8BzD,MAAM,CAACmB,MAAPnB,CAAc0D,CAAW,CAACxC,SAA1BlB,CAAqC,CAC/DoB,WAAW,CAAE,CACTlB,KAAK,CAAEuD,CADE,CAEThD,YAAY,GAFH,CAGTY,QAAQ,GAHC,CADkD,CAArCrB,CANW,KAcpC,GAAIM,CAAAA,CAAC,CAAG,EAAGA,CAAC,CAAGkD,CAAU,CAACjD,OAAQ,EAAED,EACrC+C,CAAoB,CAACI,CAAiB,CAACvC,SAAnB,CAA8BsC,CAAU,CAAClD,CAAD,CAAxC,CAApB+C,OAGGI,CAAAA,EAgBX,QAASC,CAAAA,CAAT,EAAuB,IAEf,eAAgBA,CAAAA,aAChBlB,CAAAA,CAAY,CAAChD,GAAbgD,CAAiB,IAAjBA,CAAuB,GAAImB,CAAAA,GAA3BnB,KAGqB,CAArB5B,GAAAA,SAAS,CAACL,MAAVK,EAA0BgD,KAAK,CAACC,OAAND,CAAchD,SAAS,CAAC,CAAD,CAAvBgD,QACnBL,CAAAA,CAAuB,CAAC3C,SAAS,CAAC,CAAD,CAAV,KAEX,CAAnBA,CAAAA,SAAS,CAACL,OAAY,QAChBuD,CAAAA,CAAK,CAAOF,KAAP,CAAahD,SAAS,CAACL,MAAvB,EACFD,CAAC,CAAG,EAAGA,CAAC,CAAGM,SAAS,CAACL,OAAQ,EAAED,EACpCwD,CAAK,CAACxD,CAAD,CAALwD,CAAWlD,SAAS,CAACN,CAAD,CAApBwD,OAEGP,CAAAA,CAAuB,CAACO,CAAD,OAE5B,IAAIrB,CAAAA,SAAJ,CAAc,mCAAd,KD5KJ9D,CAAAA,CAAW,CAAG,GAAIoF,CAAAA,QAOlBpC,CAAQ,CAAG,GAAIoC,CAAAA,QAkFrBzE,CAAK,CAAC4B,SAAN5B,CAAkB,IAKV0E,CAAAA,MAAO,OACAxF,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAewF,IANZ,CAAA,IAaVC,CAAAA,QAAS,OACFzF,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASe,WAdN,CAAA,IAqBVG,CAAAA,eAAgB,OACTlB,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASkB,aAtBN,CAAA,CA4BdwE,YA5Bc,WA4BC,IACLxE,CAAAA,CAAa,CAAGlB,CAAE,CAAC,IAAD,CAAFA,CAASkB,cADpB,MAEU,KAAjBA,EAAAA,CAFO,CAGA,EAHA,CAKJ,CAACA,CAAD,CAjCG,CAAA,IAwCVyE,CAAAA,MAAO,OACA,EAzCG,CAAA,IAgDVC,CAAAA,iBAAkB,OACX,EAjDG,CAAA,IAwDVC,CAAAA,WAAY,OACL,EAzDG,CAAA,IAgEVC,CAAAA,gBAAiB,OACV,EAjEG,CAAA,IAwEV7E,CAAAA,YAAa,OACNjB,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASiB,UAzEN,CAAA,CAgFd8E,eAhFc,WAgFI,IACRvF,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAALX,GAHc,CAI4B,UAAtC,QAAOA,CAAAA,CAAI,CAACP,KAALO,CAAWuF,eAJR,EAKVvF,CAAI,CAACP,KAALO,CAAWuF,eAAXvF,EArFM,CAAA,CA6FdwF,wBA7Fc,WA6Fa,IACjBxF,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAALX,GAHuB,CAIvBA,CAAI,CAACY,gBAALZ,GAJuB,CAK4B,UAA/C,QAAOA,CAAAA,CAAI,CAACP,KAALO,CAAWwF,wBALC,EAMnBxF,CAAI,CAACP,KAALO,CAAWwF,wBAAXxF,EAnGM,CAAA,IA2GVyF,CAAAA,SAAU,SACKjG,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAeiG,OA5GpB,CAAA,IAmHVvF,CAAAA,YAAa,SACEV,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAeU,UApHpB,CAAA,CA2HdE,cA3Hc,WA2HG,CACbL,CAAa,CAACP,CAAE,CAAC,IAAD,CAAH,CA5HH,CAAA,IAmIVkG,CAAAA,kBAAmB,OACZlG,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASW,QApIN,CAAA,IA2IVwF,CAAAA,UAAW,SACInG,CAAE,CAAC,IAAD,CAAFA,CAASC,KAATD,CAAemG,QA5IpB,CAAA,IAmJV9E,CAAAA,WAAY,OACLrB,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASqB,SApJN,CAAA,IA4JV+E,CAAAA,YAAa,OACNpG,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASe,WA7JN,CAAA,IAqKVsF,CAAAA,cAAe,OACRrG,CAAAA,CAAE,CAAC,IAAD,CAAFA,CAASmB,OAtKN,CAAA,IAwKVkF,CAAAA,aAAa3E,EAAO,IACfA,MAGClB,CAAAA,CAAI,CAAGR,CAAE,CAAC,IAAD,EAEfQ,CAAI,CAACW,OAALX,IACuC,SAAnC,QAAOA,CAAAA,CAAI,CAACP,KAALO,CAAW6F,eAClB7F,CAAI,CAACP,KAALO,CAAW6F,YAAX7F,KAhLM,CAAA,IAyLV8F,CAAAA,aAAc,OACP,CAACtG,CAAE,CAAC,IAAD,CAAFA,CAASW,QA1LP,CAAA,IA4LV2F,CAAAA,YAAY5E,EAAO,CACdA,CADc,EAEfnB,CAAa,CAACP,CAAE,CAAC,IAAD,CAAH,CA9LP,CAAA,CAyMduG,SAzMc,WAyMF,EAzME,EA+MlB/E,MAAM,CAACC,cAAPD,CAAsBV,CAAK,CAAC4B,SAA5BlB,CAAuC,aAAvCA,CAAsD,CAClDE,KAAK,CAAEZ,CAD2C,CAElDmB,YAAY,GAFsC,CAGlDY,QAAQ,GAH0C,CAAtDrB,EAOsB,WAAlB,QAAOgF,CAAAA,MAAP,EAAyD,WAAxB,QAAOA,CAAAA,MAAM,CAAC1F,QAC/CU,MAAM,CAACiF,cAAPjF,CAAsBV,CAAK,CAAC4B,SAA5BlB,CAAuCgF,MAAM,CAAC1F,KAAP0F,CAAa9D,SAApDlB,EAGA2B,CAAQ,CAACnC,GAATmC,CAAaqD,MAAM,CAAC1F,KAAP0F,CAAa9D,SAA1BS,CAAqCrC,CAArCqC,MChTEa,CAAAA,CAAY,CAAG,GAAIuB,CAAAA,QAGnBmB,CAAO,CAAG,EACVC,CAAM,CAAG,KA0KfzB,CAAW,CAACxC,SAAZwC,CAAwB,CAQpB0B,gBARoB,UAQHzC,EAAWG,EAAUuC,EAAS,IAC3B,IAAZvC,EAAAA,MAGoB,UAApB,QAAOA,CAAAA,CAAP,EAAkC,CAACX,CAAQ,CAACW,CAAD,OACrC,IAAIL,CAAAA,SAAJ,CAAc,+CAAd,KAGJF,CAAAA,CAAS,CAAGD,CAAY,CAAC,IAAD,EACxBgD,CAAY,CAAGnD,CAAQ,CAACkD,CAAD,EACvBE,CAAO,CAAGD,CAAY,GACdD,CAAO,CAACE,OADM,GAEdF,EACRxC,CAAY,CAAG0C,CAAO,CAAGL,CAAH,CAAaC,EACnCjC,CAAO,CAAG,CACZJ,QAAQ,CAARA,CADY,CAEZD,YAAY,CAAZA,CAFY,CAGZM,OAAO,CAAEmC,CAAY,IAAYD,CAAO,CAAClC,OAH7B,CAIZC,IAAI,CAAEkC,CAAY,IAAYD,CAAO,CAACjC,IAJ1B,CAKZL,IAAI,CAAE,IALM,EASZH,CAAI,CAAGL,CAAS,CAAC3D,GAAV2D,CAAcI,CAAdJ,KACPK,SAAAA,aACAL,CAAAA,CAAS,CAAC/C,GAAV+C,CAAcI,CAAdJ,CAAyBW,CAAzBX,SAKAS,CAAAA,CAAI,CAAG,KACI,IAARJ,EAAAA,GAAc,IAEbA,CAAI,CAACE,QAALF,GAAkBE,CAAlBF,EACAA,CAAI,CAACC,YAALD,GAAsBC,SAK1BG,CAAI,CAAGJ,CARU,CASjBA,CAAI,CAAGA,CAAI,CAACG,IAxC2B,CA4C3CC,CAAI,CAACD,IAALC,CAAYE,EApDI,CAAA,CA8DpBsC,mBA9DoB,UA8DA7C,EAAWG,EAAUuC,EAAS,IAC9B,IAAZvC,EAAAA,SAIEP,CAAAA,CAAS,CAAGD,CAAY,CAAC,IAAD,EACxBiD,CAAO,CAAGpD,CAAQ,CAACkD,CAAD,CAARlD,GACFkD,CAAO,CAACE,OADNpD,GAEFkD,EACRxC,CAAY,CAAG0C,CAAO,CAAGL,CAAH,CAAaC,EAErCnC,CAAI,CAAG,KACPJ,CAAI,CAAGL,CAAS,CAAC3D,GAAV2D,CAAcI,CAAdJ,EACI,IAARK,EAAAA,GAAc,IAEbA,CAAI,CAACE,QAALF,GAAkBE,CAAlBF,EACAA,CAAI,CAACC,YAALD,GAAsBC,cAET,IAATG,GAAAA,EAEqB,IAAdJ,GAAAA,CAAI,CAACG,KAGZR,CAAS,CAACU,MAAVV,CAAiBI,CAAjBJ,EAFAA,CAAS,CAAC/C,GAAV+C,CAAcI,CAAdJ,CAAyBK,CAAI,CAACG,IAA9BR,EAFAS,CAAI,CAACD,IAALC,CAAYJ,CAAI,CAACG,MASzBC,CAAI,CAAGJ,CAfU,CAgBjBA,CAAI,CAAGA,CAAI,CAACG,KA3FA,CAAA,CAoGpB0C,aApGoB,UAoGNhH,EAAO,IACJ,IAATA,EAAAA,CAAK,EAAkC,QAAtB,QAAOA,CAAAA,CAAK,CAACuF,UACxB,IAAIvB,CAAAA,SAAJ,CAAc,oCAAd,EAFO,GAMXF,CAAAA,CAAS,CAAGD,CAAY,CAAC,IAAD,CANb,CAOXK,CAAS,CAAGlE,CAAK,CAACuF,IAPP,CAQbpB,CAAI,CAAGL,CAAS,CAAC3D,GAAV2D,CAAcI,CAAdJ,CARM,IASL,IAARK,EAAAA,WATa,OAcX8C,CAAAA,CAAY,CAAG7D,CAAS,CAAC,IAAD,CAAOpD,CAAP,CAdb,CAkBbuE,CAAI,CAAG,IAlBM,CAmBF,IAARJ,EAAAA,CAnBU,EAmBI,IAEbA,CAAI,CAACQ,KACQ,IAATJ,GAAAA,EAEqB,IAAdJ,GAAAA,CAAI,CAACG,KAGZR,CAAS,CAACU,MAAVV,CAAiBI,CAAjBJ,EAFAA,CAAS,CAAC/C,GAAV+C,CAAcI,CAAdJ,CAAyBK,CAAI,CAACG,IAA9BR,EAFAS,CAAI,CAACD,IAALC,CAAYJ,CAAI,CAACG,KAOrBC,CAAI,CAAGJ,EAIXV,CAAkB,CACdwD,CADc,CAEd9C,CAAI,CAACO,OAALP,CAAeA,CAAI,CAACE,QAApBF,CAA+B,IAFjB,EAIW,UAAzB,QAAOA,CAAAA,CAAI,CAACE,YACR,CACAF,CAAI,CAACE,QAALF,CAAc3B,IAAd2B,CAAmB,IAAnBA,CAAyB8C,CAAzB9C,CADJ,CAEE,MAAO+C,CAAP,CAAY,CAEa,WAAnB,QAAO9G,CAAAA,OAAP,EACyB,UAAzB,QAAOA,CAAAA,OAAO,CAACQ,KAHT,EAKNR,OAAO,CAACQ,KAARR,CAAc8G,CAAd9G,MAIR+D,CAAAA,CAAI,CAACC,YAALD,GA/TE,CA+TFA,EACqC,UAArC,QAAOA,CAAAA,CAAI,CAACE,QAALF,CAAcgD,aAErBhD,CAAI,CAACE,QAALF,CAAcgD,WAAdhD,CAA0B8C,CAA1B9C,KAIAb,CAAS,CAAC2D,CAAD,QAIb9C,CAAI,CAAGA,CAAI,CAACG,WAEhBb,CAAAA,CAAkB,CAACwD,CAAD,CAAe,IAAf,EAClB1D,CAAa,CAAC0D,CAAD,CAAe,CAAf,EACbzD,CAAgB,CAACyD,CAAD,CAAe,IAAf,EAET,CAACA,CAAY,CAAChB,iBAvKL,EA4KxB1E,MAAM,CAACC,cAAPD,CAAsB0D,CAAW,CAACxC,SAAlClB,CAA6C,aAA7CA,CAA4D,CACxDE,KAAK,CAAEwD,CADiD,CAExDjD,YAAY,GAF4C,CAGxDY,QAAQ,GAHgD,CAA5DrB,EAQsB,WAAlB,QAAOgF,CAAAA,MAAP,EAC8B,WAA9B,QAAOA,CAAAA,MAAM,CAACtB,aAEd1D,MAAM,CAACiF,cAAPjF,CAAsB0D,CAAW,CAACxC,SAAlClB,CAA6CgF,MAAM,CAACtB,WAAPsB,CAAmB9D,SAAhElB"} \ No newline at end of file diff --git a/node_modules/event-target-shim/index.d.ts b/node_modules/event-target-shim/index.d.ts new file mode 100644 index 0000000..a303097 --- /dev/null +++ b/node_modules/event-target-shim/index.d.ts @@ -0,0 +1,399 @@ +export as namespace EventTargetShim + +/** + * `Event` interface. + * @see https://dom.spec.whatwg.org/#event + */ +export interface Event { + /** + * The type of this event. + */ + readonly type: string + + /** + * The target of this event. + */ + readonly target: EventTarget<{}, {}, "standard"> | null + + /** + * The current target of this event. + */ + readonly currentTarget: EventTarget<{}, {}, "standard"> | null + + /** + * The target of this event. + * @deprecated + */ + readonly srcElement: any | null + + /** + * The composed path of this event. + */ + composedPath(): EventTarget<{}, {}, "standard">[] + + /** + * Constant of NONE. + */ + readonly NONE: number + + /** + * Constant of CAPTURING_PHASE. + */ + readonly CAPTURING_PHASE: number + + /** + * Constant of BUBBLING_PHASE. + */ + readonly BUBBLING_PHASE: number + + /** + * Constant of AT_TARGET. + */ + readonly AT_TARGET: number + + /** + * Indicates which phase of the event flow is currently being evaluated. + */ + readonly eventPhase: number + + /** + * Stop event bubbling. + */ + stopPropagation(): void + + /** + * Stop event bubbling. + */ + stopImmediatePropagation(): void + + /** + * Initialize event. + * @deprecated + */ + initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void + + /** + * The flag indicating bubbling. + */ + readonly bubbles: boolean + + /** + * Stop event bubbling. + * @deprecated + */ + cancelBubble: boolean + + /** + * Set or get cancellation flag. + * @deprecated + */ + returnValue: boolean + + /** + * The flag indicating whether the event can be canceled. + */ + readonly cancelable: boolean + + /** + * Cancel this event. + */ + preventDefault(): void + + /** + * The flag to indicating whether the event was canceled. + */ + readonly defaultPrevented: boolean + + /** + * The flag to indicating if event is composed. + */ + readonly composed: boolean + + /** + * Indicates whether the event was dispatched by the user agent. + */ + readonly isTrusted: boolean + + /** + * The unix time of this event. + */ + readonly timeStamp: number +} + +/** + * The constructor of `EventTarget` interface. + */ +export type EventTargetConstructor< + TEvents extends EventTarget.EventDefinition = {}, + TEventAttributes extends EventTarget.EventDefinition = {}, + TMode extends EventTarget.Mode = "loose" +> = { + prototype: EventTarget + new(): EventTarget +} + +/** + * `EventTarget` interface. + * @see https://dom.spec.whatwg.org/#interface-eventtarget + */ +export type EventTarget< + TEvents extends EventTarget.EventDefinition = {}, + TEventAttributes extends EventTarget.EventDefinition = {}, + TMode extends EventTarget.Mode = "loose" +> = EventTarget.EventAttributes & { + /** + * Add a given listener to this event target. + * @param eventName The event name to add. + * @param listener The listener to add. + * @param options The options for this listener. + */ + addEventListener>( + type: TEventType, + listener: + | EventTarget.Listener> + | null, + options?: boolean | EventTarget.AddOptions + ): void + + /** + * Remove a given listener from this event target. + * @param eventName The event name to remove. + * @param listener The listener to remove. + * @param options The options for this listener. + */ + removeEventListener>( + type: TEventType, + listener: + | EventTarget.Listener> + | null, + options?: boolean | EventTarget.RemoveOptions + ): void + + /** + * Dispatch a given event. + * @param event The event to dispatch. + * @returns `false` if canceled. + */ + dispatchEvent>( + event: EventTarget.EventData + ): boolean +} + +export const EventTarget: EventTargetConstructor & { + /** + * Create an `EventTarget` instance with detailed event definition. + * + * The detailed event definition requires to use `defineEventAttribute()` + * function later. + * + * Unfortunately, the second type parameter `TEventAttributes` was needed + * because we cannot compute string literal types. + * + * @example + * const signal = new EventTarget<{ abort: Event }, { onabort: Event }>() + * defineEventAttribute(signal, "abort") + */ + new < + TEvents extends EventTarget.EventDefinition, + TEventAttributes extends EventTarget.EventDefinition, + TMode extends EventTarget.Mode = "loose" + >(): EventTarget + + /** + * Define an `EventTarget` constructor with attribute events and detailed event definition. + * + * Unfortunately, the second type parameter `TEventAttributes` was needed + * because we cannot compute string literal types. + * + * @example + * class AbortSignal extends EventTarget<{ abort: Event }, { onabort: Event }>("abort") { + * abort(): void {} + * } + * + * @param events Optional event attributes (e.g. passing in `"click"` adds `onclick` to prototype). + */ + < + TEvents extends EventTarget.EventDefinition = {}, + TEventAttributes extends EventTarget.EventDefinition = {}, + TMode extends EventTarget.Mode = "loose" + >(events: string[]): EventTargetConstructor< + TEvents, + TEventAttributes, + TMode + > + + /** + * Define an `EventTarget` constructor with attribute events and detailed event definition. + * + * Unfortunately, the second type parameter `TEventAttributes` was needed + * because we cannot compute string literal types. + * + * @example + * class AbortSignal extends EventTarget<{ abort: Event }, { onabort: Event }>("abort") { + * abort(): void {} + * } + * + * @param events Optional event attributes (e.g. passing in `"click"` adds `onclick` to prototype). + */ + < + TEvents extends EventTarget.EventDefinition = {}, + TEventAttributes extends EventTarget.EventDefinition = {}, + TMode extends EventTarget.Mode = "loose" + >(event0: string, ...events: string[]): EventTargetConstructor< + TEvents, + TEventAttributes, + TMode + > +} + +export namespace EventTarget { + /** + * Options of `removeEventListener()` method. + */ + export interface RemoveOptions { + /** + * The flag to indicate that the listener is for the capturing phase. + */ + capture?: boolean + } + + /** + * Options of `addEventListener()` method. + */ + export interface AddOptions extends RemoveOptions { + /** + * The flag to indicate that the listener doesn't support + * `event.preventDefault()` operation. + */ + passive?: boolean + /** + * The flag to indicate that the listener will be removed on the first + * event. + */ + once?: boolean + } + + /** + * The type of regular listeners. + */ + export interface FunctionListener { + (event: TEvent): void + } + + /** + * The type of object listeners. + */ + export interface ObjectListener { + handleEvent(event: TEvent): void + } + + /** + * The type of listeners. + */ + export type Listener = + | FunctionListener + | ObjectListener + + /** + * Event definition. + */ + export type EventDefinition = { + readonly [key: string]: Event + } + + /** + * Mapped type for event attributes. + */ + export type EventAttributes = { + [P in keyof TEventAttributes]: + | FunctionListener + | null + } + + /** + * The type of event data for `dispatchEvent()` method. + */ + export type EventData< + TEvents extends EventDefinition, + TEventType extends keyof TEvents | string, + TMode extends Mode + > = + TEventType extends keyof TEvents + ? ( + // Require properties which are not generated automatically. + & Pick< + TEvents[TEventType], + Exclude + > + // Properties which are generated automatically are optional. + & Partial> + ) + : ( + TMode extends "standard" + ? Event + : Event | NonStandardEvent + ) + + /** + * The string literal types of the properties which are generated + * automatically in `dispatchEvent()` method. + */ + export type OmittableEventKeys = Exclude + + /** + * The type of event data. + */ + export type NonStandardEvent = { + [key: string]: any + type: string + } + + /** + * The type of listeners. + */ + export type PickEvent< + TEvents extends EventDefinition, + TEventType extends keyof TEvents | string, + > = + TEventType extends keyof TEvents + ? TEvents[TEventType] + : Event + + /** + * Event type candidates. + */ + export type EventType< + TEvents extends EventDefinition, + TMode extends Mode + > = + TMode extends "strict" + ? keyof TEvents + : keyof TEvents | string + + /** + * - `"strict"` ..... Methods don't accept unknown events. + * `dispatchEvent()` accepts partial objects. + * - `"loose"` ...... Methods accept unknown events. + * `dispatchEvent()` accepts partial objects. + * - `"standard"` ... Methods accept unknown events. + * `dispatchEvent()` doesn't accept partial objects. + */ + export type Mode = "strict" | "standard" | "loose" +} + +/** + * Specialized `type` property. + */ +export type Type = { type: T } + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param prototype The event target prototype to define an event attribute. + * @param eventName The event name to define. + */ +export function defineEventAttribute( + prototype: EventTarget, + eventName: string +): void + +export default EventTarget diff --git a/node_modules/event-target-shim/package.json b/node_modules/event-target-shim/package.json new file mode 100644 index 0000000..40326f3 --- /dev/null +++ b/node_modules/event-target-shim/package.json @@ -0,0 +1,82 @@ +{ + "name": "event-target-shim", + "version": "5.0.1", + "description": "An implementation of WHATWG EventTarget interface.", + "main": "dist/event-target-shim", + "types": "index.d.ts", + "files": [ + "dist", + "index.d.ts" + ], + "engines": { + "node": ">=6" + }, + "scripts": { + "preversion": "npm test", + "version": "npm run build && git add dist/*", + "postversion": "git push && git push --tags", + "clean": "rimraf .nyc_output coverage", + "coverage": "nyc report --reporter lcov && opener coverage/lcov-report/index.html", + "lint": "eslint src test scripts --ext .js,.mjs", + "build": "rollup -c scripts/rollup.config.js", + "pretest": "npm run lint", + "test": "run-s test:*", + "test:mocha": "nyc --require ./scripts/babel-register mocha test/*.mjs", + "test:karma": "karma start scripts/karma.conf.js --single-run", + "watch": "run-p watch:*", + "watch:mocha": "mocha test/*.mjs --require ./scripts/babel-register --watch --watch-extensions js,mjs --growl", + "watch:karma": "karma start scripts/karma.conf.js --watch", + "codecov": "codecov" + }, + "devDependencies": { + "@babel/core": "^7.2.2", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/preset-env": "^7.2.3", + "@babel/register": "^7.0.0", + "@mysticatea/eslint-plugin": "^8.0.1", + "@mysticatea/spy": "^0.1.2", + "assert": "^1.4.1", + "codecov": "^3.1.0", + "eslint": "^5.12.1", + "karma": "^3.1.4", + "karma-chrome-launcher": "^2.2.0", + "karma-coverage": "^1.1.2", + "karma-firefox-launcher": "^1.0.0", + "karma-growl-reporter": "^1.0.0", + "karma-ie-launcher": "^1.0.0", + "karma-mocha": "^1.3.0", + "karma-rollup-preprocessor": "^7.0.0-rc.2", + "mocha": "^5.2.0", + "npm-run-all": "^4.1.5", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "rimraf": "^2.6.3", + "rollup": "^1.1.1", + "rollup-plugin-babel": "^4.3.2", + "rollup-plugin-babel-minify": "^7.0.0", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-json": "^3.1.0", + "rollup-plugin-node-resolve": "^4.0.0", + "rollup-watch": "^4.3.1", + "type-tester": "^1.0.0", + "typescript": "^3.2.4" + }, + "repository": { + "type": "git", + "url": "https://github.com/mysticatea/event-target-shim.git" + }, + "keywords": [ + "w3c", + "whatwg", + "eventtarget", + "event", + "events", + "shim" + ], + "author": "Toru Nagashima", + "license": "MIT", + "bugs": { + "url": "https://github.com/mysticatea/event-target-shim/issues" + }, + "homepage": "https://github.com/mysticatea/event-target-shim" +} diff --git a/node_modules/get-stream/buffer-stream.js b/node_modules/get-stream/buffer-stream.js new file mode 100644 index 0000000..2dd7574 --- /dev/null +++ b/node_modules/get-stream/buffer-stream.js @@ -0,0 +1,52 @@ +'use strict'; +const {PassThrough: PassThroughStream} = require('stream'); + +module.exports = options => { + options = {...options}; + + const {array} = options; + let {encoding} = options; + const isBuffer = encoding === 'buffer'; + let objectMode = false; + + if (array) { + objectMode = !(encoding || isBuffer); + } else { + encoding = encoding || 'utf8'; + } + + if (isBuffer) { + encoding = null; + } + + const stream = new PassThroughStream({objectMode}); + + if (encoding) { + stream.setEncoding(encoding); + } + + let length = 0; + const chunks = []; + + stream.on('data', chunk => { + chunks.push(chunk); + + if (objectMode) { + length = chunks.length; + } else { + length += chunk.length; + } + }); + + stream.getBufferedValue = () => { + if (array) { + return chunks; + } + + return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); + }; + + stream.getBufferedLength = () => length; + + return stream; +}; diff --git a/node_modules/get-stream/index.d.ts b/node_modules/get-stream/index.d.ts new file mode 100644 index 0000000..7b98134 --- /dev/null +++ b/node_modules/get-stream/index.d.ts @@ -0,0 +1,108 @@ +/// +import {Stream} from 'stream'; + +declare class MaxBufferErrorClass extends Error { + readonly name: 'MaxBufferError'; + constructor(); +} + +declare namespace getStream { + interface Options { + /** + Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected with a `MaxBufferError` error. + + @default Infinity + */ + readonly maxBuffer?: number; + } + + interface OptionsWithEncoding extends Options { + /** + [Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream. + + @default 'utf8' + */ + readonly encoding?: EncodingType; + } + + type MaxBufferError = MaxBufferErrorClass; +} + +declare const getStream: { + /** + Get the `stream` as a string. + + @returns A promise that resolves when the end event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode. + + @example + ``` + import * as fs from 'fs'; + import getStream = require('get-stream'); + + (async () => { + const stream = fs.createReadStream('unicorn.txt'); + + console.log(await getStream(stream)); + // ,,))))))));, + // __)))))))))))))), + // \|/ -\(((((''''((((((((. + // -*-==//////(('' . `)))))), + // /|\ ))| o ;-. '((((( ,(, + // ( `| / ) ;))))' ,_))^;(~ + // | | | ,))((((_ _____------~~~-. %,;(;(>';'~ + // o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~ + // ; ''''```` `: `:::|\,__,%% );`'; ~ + // | _ ) / `:|`----' `-' + // ______/\/~ | / / + // /~;;.____/;;' / ___--,-( `;;;/ + // / // _;______;'------~~~~~ /;;/\ / + // // | | / ; \;;,\ + // (<_ | ; /',/-----' _> + // \_| ||_ //~;~~~~~~~~~ + // `\_| (,~~ + // \~\ + // ~~ + })(); + ``` + */ + (stream: Stream, options?: getStream.OptionsWithEncoding): Promise; + + /** + Get the `stream` as a buffer. + + It honors the `maxBuffer` option as above, but it refers to byte length rather than string length. + */ + buffer( + stream: Stream, + options?: getStream.OptionsWithEncoding + ): Promise; + + /** + Get the `stream` as an array of values. + + It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen: + + - When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes). + - When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array. + - When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array. + */ + array( + stream: Stream, + options?: getStream.Options + ): Promise; + array( + stream: Stream, + options: getStream.OptionsWithEncoding<'buffer'> + ): Promise; + array( + stream: Stream, + options: getStream.OptionsWithEncoding + ): Promise; + + MaxBufferError: typeof MaxBufferErrorClass; + + // TODO: Remove this for the next major release + default: typeof getStream; +}; + +export = getStream; diff --git a/node_modules/get-stream/index.js b/node_modules/get-stream/index.js new file mode 100644 index 0000000..71f3991 --- /dev/null +++ b/node_modules/get-stream/index.js @@ -0,0 +1,60 @@ +'use strict'; +const {constants: BufferConstants} = require('buffer'); +const pump = require('pump'); +const bufferStream = require('./buffer-stream'); + +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; + } +} + +async function getStream(inputStream, options) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } + + options = { + maxBuffer: Infinity, + ...options + }; + + const {maxBuffer} = options; + + let stream; + await new Promise((resolve, reject) => { + const rejectPromise = error => { + // Don't retrieve an oversized buffer. + if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { + error.bufferedData = stream.getBufferedValue(); + } + + reject(error); + }; + + stream = pump(inputStream, bufferStream(options), error => { + if (error) { + rejectPromise(error); + return; + } + + resolve(); + }); + + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }); + + return stream.getBufferedValue(); +} + +module.exports = getStream; +// TODO: Remove this for the next major release +module.exports.default = getStream; +module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); +module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); +module.exports.MaxBufferError = MaxBufferError; diff --git a/node_modules/get-stream/license b/node_modules/get-stream/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/get-stream/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/get-stream/package.json b/node_modules/get-stream/package.json new file mode 100644 index 0000000..e2f1687 --- /dev/null +++ b/node_modules/get-stream/package.json @@ -0,0 +1,50 @@ +{ + "name": "get-stream", + "version": "5.2.0", + "description": "Get a stream as a string, buffer, or array", + "license": "MIT", + "repository": "sindresorhus/get-stream", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts", + "buffer-stream.js" + ], + "keywords": [ + "get", + "stream", + "promise", + "concat", + "string", + "text", + "buffer", + "read", + "data", + "consume", + "readable", + "readablestream", + "array", + "object" + ], + "dependencies": { + "pump": "^3.0.0" + }, + "devDependencies": { + "@types/node": "^12.0.7", + "ava": "^2.0.0", + "into-stream": "^5.0.0", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/get-stream/readme.md b/node_modules/get-stream/readme.md new file mode 100644 index 0000000..7d7565d --- /dev/null +++ b/node_modules/get-stream/readme.md @@ -0,0 +1,124 @@ +# get-stream [![Build Status](https://travis-ci.com/sindresorhus/get-stream.svg?branch=master)](https://travis-ci.com/github/sindresorhus/get-stream) + +> Get a stream as a string, buffer, or array + +## Install + +``` +$ npm install get-stream +``` + +## Usage + +```js +const fs = require('fs'); +const getStream = require('get-stream'); + +(async () => { + const stream = fs.createReadStream('unicorn.txt'); + + console.log(await getStream(stream)); + /* + ,,))))))));, + __)))))))))))))), + \|/ -\(((((''''((((((((. + -*-==//////(('' . `)))))), + /|\ ))| o ;-. '((((( ,(, + ( `| / ) ;))))' ,_))^;(~ + | | | ,))((((_ _____------~~~-. %,;(;(>';'~ + o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~ + ; ''''```` `: `:::|\,__,%% );`'; ~ + | _ ) / `:|`----' `-' + ______/\/~ | / / + /~;;.____/;;' / ___--,-( `;;;/ + / // _;______;'------~~~~~ /;;/\ / + // | | / ; \;;,\ + (<_ | ; /',/-----' _> + \_| ||_ //~;~~~~~~~~~ + `\_| (,~~ + \~\ + ~~ + */ +})(); +``` + +## API + +The methods returns a promise that resolves when the `end` event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode. + +### getStream(stream, options?) + +Get the `stream` as a string. + +#### options + +Type: `object` + +##### encoding + +Type: `string`\ +Default: `'utf8'` + +[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream. + +##### maxBuffer + +Type: `number`\ +Default: `Infinity` + +Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected with a `getStream.MaxBufferError` error. + +### getStream.buffer(stream, options?) + +Get the `stream` as a buffer. + +It honors the `maxBuffer` option as above, but it refers to byte length rather than string length. + +### getStream.array(stream, options?) + +Get the `stream` as an array of values. + +It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen: + +- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes). + +- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array. + +- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array. + +## Errors + +If the input stream emits an `error` event, the promise will be rejected with the error. The buffered data will be attached to the `bufferedData` property of the error. + +```js +(async () => { + try { + await getStream(streamThatErrorsAtTheEnd('unicorn')); + } catch (error) { + console.log(error.bufferedData); + //=> 'unicorn' + } +})() +``` + +## FAQ + +### How is this different from [`concat-stream`](https://github.com/maxogden/concat-stream)? + +This module accepts a stream instead of being one and returns a promise instead of using a callback. The API is simpler and it only supports returning a string, buffer, or array. It doesn't have a fragile type inference. You explicitly choose what you want. And it doesn't depend on the huge `readable-stream` package. + +## Related + +- [get-stdin](https://github.com/sindresorhus/get-stdin) - Get stdin as a string or buffer + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/got/dist/source/as-promise/create-rejection.d.ts b/node_modules/got/dist/source/as-promise/create-rejection.d.ts new file mode 100644 index 0000000..f125a77 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/create-rejection.d.ts @@ -0,0 +1,2 @@ +import { CancelableRequest, BeforeErrorHook } from './types'; +export default function createRejection(error: Error, ...beforeErrorGroups: Array): CancelableRequest; diff --git a/node_modules/got/dist/source/as-promise/create-rejection.js b/node_modules/got/dist/source/as-promise/create-rejection.js new file mode 100644 index 0000000..ce62604 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/create-rejection.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const types_1 = require("./types"); +function createRejection(error, ...beforeErrorGroups) { + const promise = (async () => { + if (error instanceof types_1.RequestError) { + try { + for (const hooks of beforeErrorGroups) { + if (hooks) { + for (const hook of hooks) { + // eslint-disable-next-line no-await-in-loop + error = await hook(error); + } + } + } + } + catch (error_) { + error = error_; + } + } + throw error; + })(); + const returnPromise = () => promise; + promise.json = returnPromise; + promise.text = returnPromise; + promise.buffer = returnPromise; + promise.on = returnPromise; + return promise; +} +exports.default = createRejection; diff --git a/node_modules/got/dist/source/as-promise/index.d.ts b/node_modules/got/dist/source/as-promise/index.d.ts new file mode 100644 index 0000000..f06720e --- /dev/null +++ b/node_modules/got/dist/source/as-promise/index.d.ts @@ -0,0 +1,3 @@ +import { NormalizedOptions, CancelableRequest } from './types'; +export default function asPromise(normalizedOptions: NormalizedOptions): CancelableRequest; +export * from './types'; diff --git a/node_modules/got/dist/source/as-promise/index.js b/node_modules/got/dist/source/as-promise/index.js new file mode 100644 index 0000000..9575c09 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/index.js @@ -0,0 +1,175 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = require("events"); +const is_1 = require("@sindresorhus/is"); +const PCancelable = require("p-cancelable"); +const types_1 = require("./types"); +const parse_body_1 = require("./parse-body"); +const core_1 = require("../core"); +const proxy_events_1 = require("../core/utils/proxy-events"); +const get_buffer_1 = require("../core/utils/get-buffer"); +const is_response_ok_1 = require("../core/utils/is-response-ok"); +const proxiedRequestEvents = [ + 'request', + 'response', + 'redirect', + 'uploadProgress', + 'downloadProgress' +]; +function asPromise(normalizedOptions) { + let globalRequest; + let globalResponse; + const emitter = new events_1.EventEmitter(); + const promise = new PCancelable((resolve, reject, onCancel) => { + const makeRequest = (retryCount) => { + const request = new core_1.default(undefined, normalizedOptions); + request.retryCount = retryCount; + request._noPipe = true; + onCancel(() => request.destroy()); + onCancel.shouldReject = false; + onCancel(() => reject(new types_1.CancelError(request))); + globalRequest = request; + request.once('response', async (response) => { + var _a; + response.retryCount = retryCount; + if (response.request.aborted) { + // Canceled while downloading - will throw a `CancelError` or `TimeoutError` error + return; + } + // Download body + let rawBody; + try { + rawBody = await get_buffer_1.default(request); + response.rawBody = rawBody; + } + catch (_b) { + // The same error is caught below. + // See request.once('error') + return; + } + if (request._isAboutToError) { + return; + } + // Parse body + const contentEncoding = ((_a = response.headers['content-encoding']) !== null && _a !== void 0 ? _a : '').toLowerCase(); + const isCompressed = ['gzip', 'deflate', 'br'].includes(contentEncoding); + const { options } = request; + if (isCompressed && !options.decompress) { + response.body = rawBody; + } + else { + try { + response.body = parse_body_1.default(response, options.responseType, options.parseJson, options.encoding); + } + catch (error) { + // Fallback to `utf8` + response.body = rawBody.toString(); + if (is_response_ok_1.isResponseOk(response)) { + request._beforeError(error); + return; + } + } + } + try { + for (const [index, hook] of options.hooks.afterResponse.entries()) { + // @ts-expect-error TS doesn't notice that CancelableRequest is a Promise + // eslint-disable-next-line no-await-in-loop + response = await hook(response, async (updatedOptions) => { + const typedOptions = core_1.default.normalizeArguments(undefined, { + ...updatedOptions, + retry: { + calculateDelay: () => 0 + }, + throwHttpErrors: false, + resolveBodyOnly: false + }, options); + // Remove any further hooks for that request, because we'll call them anyway. + // The loop continues. We don't want duplicates (asPromise recursion). + typedOptions.hooks.afterResponse = typedOptions.hooks.afterResponse.slice(0, index); + for (const hook of typedOptions.hooks.beforeRetry) { + // eslint-disable-next-line no-await-in-loop + await hook(typedOptions); + } + const promise = asPromise(typedOptions); + onCancel(() => { + promise.catch(() => { }); + promise.cancel(); + }); + return promise; + }); + } + } + catch (error) { + request._beforeError(new types_1.RequestError(error.message, error, request)); + return; + } + if (!is_response_ok_1.isResponseOk(response)) { + request._beforeError(new types_1.HTTPError(response)); + return; + } + globalResponse = response; + resolve(request.options.resolveBodyOnly ? response.body : response); + }); + const onError = (error) => { + if (promise.isCanceled) { + return; + } + const { options } = request; + if (error instanceof types_1.HTTPError && !options.throwHttpErrors) { + const { response } = error; + resolve(request.options.resolveBodyOnly ? response.body : response); + return; + } + reject(error); + }; + request.once('error', onError); + const previousBody = request.options.body; + request.once('retry', (newRetryCount, error) => { + var _a, _b; + if (previousBody === ((_a = error.request) === null || _a === void 0 ? void 0 : _a.options.body) && is_1.default.nodeStream((_b = error.request) === null || _b === void 0 ? void 0 : _b.options.body)) { + onError(error); + return; + } + makeRequest(newRetryCount); + }); + proxy_events_1.default(request, emitter, proxiedRequestEvents); + }; + makeRequest(0); + }); + promise.on = (event, fn) => { + emitter.on(event, fn); + return promise; + }; + const shortcut = (responseType) => { + const newPromise = (async () => { + // Wait until downloading has ended + await promise; + const { options } = globalResponse.request; + return parse_body_1.default(globalResponse, responseType, options.parseJson, options.encoding); + })(); + Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise)); + return newPromise; + }; + promise.json = () => { + const { headers } = globalRequest.options; + if (!globalRequest.writableFinished && headers.accept === undefined) { + headers.accept = 'application/json'; + } + return shortcut('json'); + }; + promise.buffer = () => shortcut('buffer'); + promise.text = () => shortcut('text'); + return promise; +} +exports.default = asPromise; +__exportStar(require("./types"), exports); diff --git a/node_modules/got/dist/source/as-promise/normalize-arguments.d.ts b/node_modules/got/dist/source/as-promise/normalize-arguments.d.ts new file mode 100644 index 0000000..0b1e95f --- /dev/null +++ b/node_modules/got/dist/source/as-promise/normalize-arguments.d.ts @@ -0,0 +1,3 @@ +import { NormalizedOptions, Defaults } from './types'; +declare const normalizeArguments: (options: NormalizedOptions, defaults?: Defaults | undefined) => NormalizedOptions; +export default normalizeArguments; diff --git a/node_modules/got/dist/source/as-promise/normalize-arguments.js b/node_modules/got/dist/source/as-promise/normalize-arguments.js new file mode 100644 index 0000000..859feb9 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/normalize-arguments.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const is_1 = require("@sindresorhus/is"); +const normalizeArguments = (options, defaults) => { + if (is_1.default.null_(options.encoding)) { + throw new TypeError('To get a Buffer, set `options.responseType` to `buffer` instead'); + } + is_1.assert.any([is_1.default.string, is_1.default.undefined], options.encoding); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.resolveBodyOnly); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.methodRewriting); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.isStream); + is_1.assert.any([is_1.default.string, is_1.default.undefined], options.responseType); + // `options.responseType` + if (options.responseType === undefined) { + options.responseType = 'text'; + } + // `options.retry` + const { retry } = options; + if (defaults) { + options.retry = { ...defaults.retry }; + } + else { + options.retry = { + calculateDelay: retryObject => retryObject.computedValue, + limit: 0, + methods: [], + statusCodes: [], + errorCodes: [], + maxRetryAfter: undefined + }; + } + if (is_1.default.object(retry)) { + options.retry = { + ...options.retry, + ...retry + }; + options.retry.methods = [...new Set(options.retry.methods.map(method => method.toUpperCase()))]; + options.retry.statusCodes = [...new Set(options.retry.statusCodes)]; + options.retry.errorCodes = [...new Set(options.retry.errorCodes)]; + } + else if (is_1.default.number(retry)) { + options.retry.limit = retry; + } + if (is_1.default.undefined(options.retry.maxRetryAfter)) { + options.retry.maxRetryAfter = Math.min( + // TypeScript is not smart enough to handle `.filter(x => is.number(x))`. + // eslint-disable-next-line unicorn/no-fn-reference-in-iterator + ...[options.timeout.request, options.timeout.connect].filter(is_1.default.number)); + } + // `options.pagination` + if (is_1.default.object(options.pagination)) { + if (defaults) { + options.pagination = { + ...defaults.pagination, + ...options.pagination + }; + } + const { pagination } = options; + if (!is_1.default.function_(pagination.transform)) { + throw new Error('`options.pagination.transform` must be implemented'); + } + if (!is_1.default.function_(pagination.shouldContinue)) { + throw new Error('`options.pagination.shouldContinue` must be implemented'); + } + if (!is_1.default.function_(pagination.filter)) { + throw new TypeError('`options.pagination.filter` must be implemented'); + } + if (!is_1.default.function_(pagination.paginate)) { + throw new Error('`options.pagination.paginate` must be implemented'); + } + } + // JSON mode + if (options.responseType === 'json' && options.headers.accept === undefined) { + options.headers.accept = 'application/json'; + } + return options; +}; +exports.default = normalizeArguments; diff --git a/node_modules/got/dist/source/as-promise/parse-body.d.ts b/node_modules/got/dist/source/as-promise/parse-body.d.ts new file mode 100644 index 0000000..7f01799 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/parse-body.d.ts @@ -0,0 +1,3 @@ +import { ResponseType, Response, ParseJsonFunction } from './types'; +declare const parseBody: (response: Response, responseType: ResponseType, parseJson: ParseJsonFunction, encoding?: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" | undefined) => unknown; +export default parseBody; diff --git a/node_modules/got/dist/source/as-promise/parse-body.js b/node_modules/got/dist/source/as-promise/parse-body.js new file mode 100644 index 0000000..cc2b806 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/parse-body.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const types_1 = require("./types"); +const parseBody = (response, responseType, parseJson, encoding) => { + const { rawBody } = response; + try { + if (responseType === 'text') { + return rawBody.toString(encoding); + } + if (responseType === 'json') { + return rawBody.length === 0 ? '' : parseJson(rawBody.toString()); + } + if (responseType === 'buffer') { + return rawBody; + } + throw new types_1.ParseError({ + message: `Unknown body type '${responseType}'`, + name: 'Error' + }, response); + } + catch (error) { + throw new types_1.ParseError(error, response); + } +}; +exports.default = parseBody; diff --git a/node_modules/got/dist/source/as-promise/types.d.ts b/node_modules/got/dist/source/as-promise/types.d.ts new file mode 100644 index 0000000..16bb4cb --- /dev/null +++ b/node_modules/got/dist/source/as-promise/types.d.ts @@ -0,0 +1,256 @@ +/// +import PCancelable = require('p-cancelable'); +import Request, { Options, Response, RequestError, RequestEvents } from '../core'; +/** +All parsing methods supported by Got. +*/ +export declare type ResponseType = 'json' | 'buffer' | 'text'; +export interface PaginationOptions { + /** + All options accepted by `got.paginate()`. + */ + pagination?: { + /** + A function that transform [`Response`](#response) into an array of items. + This is where you should do the parsing. + + @default response => JSON.parse(response.body) + */ + transform?: (response: Response) => Promise | T[]; + /** + Checks whether the item should be emitted or not. + + @default (item, allItems, currentItems) => true + */ + filter?: (item: T, allItems: T[], currentItems: T[]) => boolean; + /** + The function takes three arguments: + - `response` - The current response object. + - `allItems` - An array of the emitted items. + - `currentItems` - Items from the current response. + + It should return an object representing Got options pointing to the next page. + The options are merged automatically with the previous request, therefore the options returned `pagination.paginate(...)` must reflect changes only. + If there are no more pages, `false` should be returned. + + @example + ``` + const got = require('got'); + + (async () => { + const limit = 10; + + const items = got.paginate('https://example.com/items', { + searchParams: { + limit, + offset: 0 + }, + pagination: { + paginate: (response, allItems, currentItems) => { + const previousSearchParams = response.request.options.searchParams; + const previousOffset = previousSearchParams.get('offset'); + + if (currentItems.length < limit) { + return false; + } + + return { + searchParams: { + ...previousSearchParams, + offset: Number(previousOffset) + limit, + } + }; + } + } + }); + + console.log('Items from all pages:', items); + })(); + ``` + */ + paginate?: (response: Response, allItems: T[], currentItems: T[]) => Options | false; + /** + Checks whether the pagination should continue. + + For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems, currentItems) => !item.flag`. + If you want to stop **after** emitting the entry, you should use `(item, allItems, currentItems) => allItems.some(entry => entry.flag)` instead. + + @default (item, allItems, currentItems) => true + */ + shouldContinue?: (item: T, allItems: T[], currentItems: T[]) => boolean; + /** + The maximum amount of items that should be emitted. + + @default Infinity + */ + countLimit?: number; + /** + Milliseconds to wait before the next request is triggered. + + @default 0 + */ + backoff?: number; + /** + The maximum amount of request that should be triggered. + Retries on failure are not counted towards this limit. + + For example, it can be helpful during development to avoid an infinite number of requests. + + @default 10000 + */ + requestLimit?: number; + /** + Defines how the parameter `allItems` in pagination.paginate, pagination.filter and pagination.shouldContinue is managed. + When set to `false`, the parameter `allItems` is always an empty array. + + This option can be helpful to save on memory usage when working with a large dataset. + */ + stackAllItems?: boolean; + }; +} +export declare type AfterResponseHook = (response: Response, retryWithMergedOptions: (options: Options) => CancelableRequest) => Response | CancelableRequest | Promise>; +export declare namespace PromiseOnly { + interface Hooks { + /** + Called with [response object](#response) and a retry function. + Calling the retry function will trigger `beforeRetry` hooks. + + Each function should return the response. + This is especially useful when you want to refresh an access token. + + __Note__: When using streams, this hook is ignored. + + @example + ``` + const got = require('got'); + + const instance = got.extend({ + hooks: { + afterResponse: [ + (response, retryWithMergedOptions) => { + if (response.statusCode === 401) { // Unauthorized + const updatedOptions = { + headers: { + token: getNewToken() // Refresh the access token + } + }; + + // Save for further requests + instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions); + + // Make a new retry + return retryWithMergedOptions(updatedOptions); + } + + // No changes otherwise + return response; + } + ], + beforeRetry: [ + (options, error, retryCount) => { + // This will be called on `retryWithMergedOptions(...)` + } + ] + }, + mutableDefaults: true + }); + ``` + */ + afterResponse?: AfterResponseHook[]; + } + interface Options extends PaginationOptions { + /** + The parsing method. + + The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body. + + It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise. + + __Note__: When using streams, this option is ignored. + + @example + ``` + (async () => { + const responsePromise = got(url); + const bufferPromise = responsePromise.buffer(); + const jsonPromise = responsePromise.json(); + + const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]); + // `response` is an instance of Got Response + // `buffer` is an instance of Buffer + // `json` is an object + })(); + ``` + + @example + ``` + // This + const body = await got(url).json(); + + // is semantically the same as this + const body = await got(url, {responseType: 'json', resolveBodyOnly: true}); + ``` + */ + responseType?: ResponseType; + /** + When set to `true` the promise will return the Response body instead of the Response object. + + @default false + */ + resolveBodyOnly?: boolean; + /** + Returns a `Stream` instead of a `Promise`. + This is equivalent to calling `got.stream(url, options?)`. + + @default false + */ + isStream?: boolean; + /** + [Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. + + To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set `responseType` to `buffer` instead. + Don't set this option to `null`. + + __Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`. + + @default 'utf-8' + */ + encoding?: BufferEncoding; + } + interface NormalizedOptions { + responseType: ResponseType; + resolveBodyOnly: boolean; + isStream: boolean; + encoding?: BufferEncoding; + pagination?: Required['pagination']>; + } + interface Defaults { + responseType: ResponseType; + resolveBodyOnly: boolean; + isStream: boolean; + pagination?: Required['pagination']>; + } + type HookEvent = 'afterResponse'; +} +/** +An error to be thrown when server response code is 2xx, and parsing body fails. +Includes a `response` property. +*/ +export declare class ParseError extends RequestError { + readonly response: Response; + constructor(error: Error, response: Response); +} +/** +An error to be thrown when the request is aborted with `.cancel()`. +*/ +export declare class CancelError extends RequestError { + readonly response: Response; + constructor(request: Request); + get isCanceled(): boolean; +} +export interface CancelableRequest extends PCancelable, RequestEvents> { + json: () => CancelableRequest; + buffer: () => CancelableRequest; + text: () => CancelableRequest; +} +export * from '../core'; diff --git a/node_modules/got/dist/source/as-promise/types.js b/node_modules/got/dist/source/as-promise/types.js new file mode 100644 index 0000000..9bbd244 --- /dev/null +++ b/node_modules/got/dist/source/as-promise/types.js @@ -0,0 +1,40 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CancelError = exports.ParseError = void 0; +const core_1 = require("../core"); +/** +An error to be thrown when server response code is 2xx, and parsing body fails. +Includes a `response` property. +*/ +class ParseError extends core_1.RequestError { + constructor(error, response) { + const { options } = response.request; + super(`${error.message} in "${options.url.toString()}"`, error, response.request); + this.name = 'ParseError'; + } +} +exports.ParseError = ParseError; +/** +An error to be thrown when the request is aborted with `.cancel()`. +*/ +class CancelError extends core_1.RequestError { + constructor(request) { + super('Promise was canceled', {}, request); + this.name = 'CancelError'; + } + get isCanceled() { + return true; + } +} +exports.CancelError = CancelError; +__exportStar(require("../core"), exports); diff --git a/node_modules/got/dist/source/core/calculate-retry-delay.d.ts b/node_modules/got/dist/source/core/calculate-retry-delay.d.ts new file mode 100644 index 0000000..86eca8f --- /dev/null +++ b/node_modules/got/dist/source/core/calculate-retry-delay.d.ts @@ -0,0 +1,5 @@ +import { RetryFunction } from '.'; +declare type Returns unknown, V> = (...args: Parameters) => V; +export declare const retryAfterStatusCodes: ReadonlySet; +declare const calculateRetryDelay: Returns; +export default calculateRetryDelay; diff --git a/node_modules/got/dist/source/core/calculate-retry-delay.js b/node_modules/got/dist/source/core/calculate-retry-delay.js new file mode 100644 index 0000000..99f604a --- /dev/null +++ b/node_modules/got/dist/source/core/calculate-retry-delay.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.retryAfterStatusCodes = void 0; +exports.retryAfterStatusCodes = new Set([413, 429, 503]); +const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter }) => { + if (attemptCount > retryOptions.limit) { + return 0; + } + const hasMethod = retryOptions.methods.includes(error.options.method); + const hasErrorCode = retryOptions.errorCodes.includes(error.code); + const hasStatusCode = error.response && retryOptions.statusCodes.includes(error.response.statusCode); + if (!hasMethod || (!hasErrorCode && !hasStatusCode)) { + return 0; + } + if (error.response) { + if (retryAfter) { + if (retryOptions.maxRetryAfter === undefined || retryAfter > retryOptions.maxRetryAfter) { + return 0; + } + return retryAfter; + } + if (error.response.statusCode === 413) { + return 0; + } + } + const noise = Math.random() * 100; + return ((2 ** (attemptCount - 1)) * 1000) + noise; +}; +exports.default = calculateRetryDelay; diff --git a/node_modules/got/dist/source/core/index.d.ts b/node_modules/got/dist/source/core/index.d.ts new file mode 100644 index 0000000..fcb4e20 --- /dev/null +++ b/node_modules/got/dist/source/core/index.d.ts @@ -0,0 +1,1124 @@ +/// +import { Duplex, Readable } from 'stream'; +import { URL, URLSearchParams } from 'url'; +import { Socket } from 'net'; +import { SecureContextOptions, DetailedPeerCertificate } from 'tls'; +import http = require('http'); +import { ClientRequest, RequestOptions, ServerResponse, request as httpRequest } from 'http'; +import https = require('https'); +import { Timings, IncomingMessageWithTimings } from '@szmarczak/http-timer'; +import CacheableLookup from 'cacheable-lookup'; +import CacheableRequest = require('cacheable-request'); +import ResponseLike = require('responselike'); +import { Delays, TimeoutError as TimedOutTimeoutError } from './utils/timed-out'; +import { URLOptions } from './utils/options-to-url'; +import { DnsLookupIpVersion } from './utils/dns-ip-version'; +import { PromiseOnly } from '../as-promise/types'; +declare type HttpRequestFunction = typeof httpRequest; +declare type Error = NodeJS.ErrnoException; +declare const kRequest: unique symbol; +declare const kResponse: unique symbol; +declare const kResponseSize: unique symbol; +declare const kDownloadedSize: unique symbol; +declare const kBodySize: unique symbol; +declare const kUploadedSize: unique symbol; +declare const kServerResponsesPiped: unique symbol; +declare const kUnproxyEvents: unique symbol; +declare const kIsFromCache: unique symbol; +declare const kCancelTimeouts: unique symbol; +declare const kStartedReading: unique symbol; +declare const kStopReading: unique symbol; +declare const kTriggerRead: unique symbol; +declare const kBody: unique symbol; +declare const kJobs: unique symbol; +declare const kOriginalResponse: unique symbol; +declare const kRetryTimeout: unique symbol; +export declare const kIsNormalizedAlready: unique symbol; +export interface Agents { + http?: http.Agent; + https?: https.Agent; + http2?: unknown; +} +export declare const withoutBody: ReadonlySet; +export interface ToughCookieJar { + getCookieString: ((currentUrl: string, options: Record, cb: (err: Error | null, cookies: string) => void) => void) & ((url: string, callback: (error: Error | null, cookieHeader: string) => void) => void); + setCookie: ((cookieOrString: unknown, currentUrl: string, options: Record, cb: (err: Error | null, cookie: unknown) => void) => void) & ((rawCookie: string, url: string, callback: (error: Error | null, result: unknown) => void) => void); +} +export interface PromiseCookieJar { + getCookieString: (url: string) => Promise; + setCookie: (rawCookie: string, url: string) => Promise; +} +/** +All available HTTP request methods provided by Got. +*/ +export declare type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'TRACE' | 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options' | 'trace'; +declare type Promisable = T | Promise; +export declare type InitHook = (options: Options) => void; +export declare type BeforeRequestHook = (options: NormalizedOptions) => Promisable; +export declare type BeforeRedirectHook = (options: NormalizedOptions, response: Response) => Promisable; +export declare type BeforeErrorHook = (error: RequestError) => Promisable; +export declare type BeforeRetryHook = (options: NormalizedOptions, error?: RequestError, retryCount?: number) => void | Promise; +interface PlainHooks { + /** + Called with plain request options, right before their normalization. + This is especially useful in conjunction with `got.extend()` when the input needs custom handling. + + __Note #1__: This hook must be synchronous! + + __Note #2__: Errors in this hook will be converted into an instances of `RequestError`. + + __Note #3__: The options object may not have a `url` property. + To modify it, use a `beforeRequest` hook instead. + + @default [] + */ + init?: InitHook[]; + /** + Called with normalized request options. + Got will make no further changes to the request before it is sent. + This is especially useful in conjunction with `got.extend()` when you want to create an API client that, for example, uses HMAC-signing. + + @default [] + */ + beforeRequest?: BeforeRequestHook[]; + /** + Called with normalized request options and the redirect response. + Got will make no further changes to the request. + This is especially useful when you want to avoid dead sites. + + @default [] + + @example + ``` + const got = require('got'); + + got('https://example.com', { + hooks: { + beforeRedirect: [ + (options, response) => { + if (options.hostname === 'deadSite') { + options.hostname = 'fallbackSite'; + } + } + ] + } + }); + ``` + */ + beforeRedirect?: BeforeRedirectHook[]; + /** + Called with an `Error` instance. + The error is passed to the hook right before it's thrown. + This is especially useful when you want to have more detailed errors. + + __Note__: Errors thrown while normalizing input options are thrown directly and not part of this hook. + + @default [] + + @example + ``` + const got = require('got'); + + got('https://api.github.com/some-endpoint', { + hooks: { + beforeError: [ + error => { + const {response} = error; + if (response && response.body) { + error.name = 'GitHubError'; + error.message = `${response.body.message} (${response.statusCode})`; + } + + return error; + } + ] + } + }); + ``` + */ + beforeError?: BeforeErrorHook[]; + /** + Called with normalized request options, the error and the retry count. + Got will make no further changes to the request. + This is especially useful when some extra work is required before the next try. + + __Note__: When using streams, this hook is ignored. + __Note__: When retrying in a `afterResponse` hook, all remaining `beforeRetry` hooks will be called without the `error` and `retryCount` arguments. + + @default [] + + @example + ``` + const got = require('got'); + + got.post('https://example.com', { + hooks: { + beforeRetry: [ + (options, error, retryCount) => { + if (error.response.statusCode === 413) { // Payload too large + options.body = getNewBody(); + } + } + ] + } + }); + ``` + */ + beforeRetry?: BeforeRetryHook[]; +} +/** +All available hook of Got. +*/ +export interface Hooks extends PromiseOnly.Hooks, PlainHooks { +} +declare type PlainHookEvent = 'init' | 'beforeRequest' | 'beforeRedirect' | 'beforeError' | 'beforeRetry'; +/** +All hook events acceptable by Got. +*/ +export declare type HookEvent = PromiseOnly.HookEvent | PlainHookEvent; +export declare const knownHookEvents: HookEvent[]; +declare type AcceptableResponse = IncomingMessageWithTimings | ResponseLike; +declare type AcceptableRequestResult = AcceptableResponse | ClientRequest | Promise | undefined; +export declare type RequestFunction = (url: URL, options: RequestOptions, callback?: (response: AcceptableResponse) => void) => AcceptableRequestResult; +export declare type Headers = Record; +declare type CheckServerIdentityFunction = (hostname: string, certificate: DetailedPeerCertificate) => Error | void; +export declare type ParseJsonFunction = (text: string) => unknown; +export declare type StringifyJsonFunction = (object: unknown) => string; +export interface RetryObject { + attemptCount: number; + retryOptions: RequiredRetryOptions; + error: TimeoutError | RequestError; + computedValue: number; + retryAfter?: number; +} +export declare type RetryFunction = (retryObject: RetryObject) => number | Promise; +/** +An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes. + +Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1). + +The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. +The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry). + +By default, it retries *only* on the specified methods, status codes, and on these network errors: +- `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached. +- `ECONNRESET`: Connection was forcibly closed by a peer. +- `EADDRINUSE`: Could not bind to any free port. +- `ECONNREFUSED`: Connection was refused by the server. +- `EPIPE`: The remote side of the stream being written has been closed. +- `ENOTFOUND`: Couldn't resolve the hostname to an IP address. +- `ENETUNREACH`: No internet connection. +- `EAI_AGAIN`: DNS lookup timed out. + +__Note__: If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. +__Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. +*/ +export interface RequiredRetryOptions { + limit: number; + methods: Method[]; + statusCodes: number[]; + errorCodes: string[]; + calculateDelay: RetryFunction; + maxRetryAfter?: number; +} +export interface CacheOptions { + shared?: boolean; + cacheHeuristic?: number; + immutableMinTimeToLive?: number; + ignoreCargoCult?: boolean; +} +interface PlainOptions extends URLOptions { + /** + Custom request function. + The main purpose of this is to [support HTTP2 using a wrapper](https://github.com/szmarczak/http2-wrapper). + + @default http.request | https.request + */ + request?: RequestFunction; + /** + An object representing `http`, `https` and `http2` keys for [`http.Agent`](https://nodejs.org/api/http.html#http_class_http_agent), [`https.Agent`](https://nodejs.org/api/https.html#https_class_https_agent) and [`http2wrapper.Agent`](https://github.com/szmarczak/http2-wrapper#new-http2agentoptions) instance. + This is necessary because a request to one protocol might redirect to another. + In such a scenario, Got will switch over to the right protocol agent for you. + + If a key is not present, it will default to a global agent. + + @example + ``` + const got = require('got'); + const HttpAgent = require('agentkeepalive'); + const {HttpsAgent} = HttpAgent; + + got('https://sindresorhus.com', { + agent: { + http: new HttpAgent(), + https: new HttpsAgent() + } + }); + ``` + */ + agent?: Agents | false; + /** + Decompress the response automatically. + This will set the `accept-encoding` header to `gzip, deflate, br` on Node.js 11.7.0+ or `gzip, deflate` for older Node.js versions, unless you set it yourself. + + Brotli (`br`) support requires Node.js 11.7.0 or later. + + If this is disabled, a compressed response is returned as a `Buffer`. + This may be useful if you want to handle decompression yourself or stream the raw compressed data. + + @default true + */ + decompress?: boolean; + /** + Milliseconds to wait for the server to end the response before aborting the request with `got.TimeoutError` error (a.k.a. `request` property). + By default, there's no timeout. + + This also accepts an `object` with the following fields to constrain the duration of each phase of the request lifecycle: + + - `lookup` starts when a socket is assigned and ends when the hostname has been resolved. + Does not apply when using a Unix domain socket. + - `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected. + - `secureConnect` starts when `connect` completes and ends when the handshaking process completes (HTTPS only). + - `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback). + - `response` starts when the request has been written to the socket and ends when the response headers are received. + - `send` starts when the socket is connected and ends with the request has been written to the socket. + - `request` starts when the request is initiated and ends when the response's end event fires. + */ + timeout?: Delays | number; + /** + When specified, `prefixUrl` will be prepended to `url`. + The prefix can be any valid URL, either relative or absolute. + A trailing slash `/` is optional - one will be added automatically. + + __Note__: `prefixUrl` will be ignored if the `url` argument is a URL instance. + + __Note__: Leading slashes in `input` are disallowed when using this option to enforce consistency and avoid confusion. + For example, when the prefix URL is `https://example.com/foo` and the input is `/bar`, there's ambiguity whether the resulting URL would become `https://example.com/foo/bar` or `https://example.com/bar`. + The latter is used by browsers. + + __Tip__: Useful when used with `got.extend()` to create niche-specific Got instances. + + __Tip__: You can change `prefixUrl` using hooks as long as the URL still includes the `prefixUrl`. + If the URL doesn't include it anymore, it will throw. + + @example + ``` + const got = require('got'); + + (async () => { + await got('unicorn', {prefixUrl: 'https://cats.com'}); + //=> 'https://cats.com/unicorn' + + const instance = got.extend({ + prefixUrl: 'https://google.com' + }); + + await instance('unicorn', { + hooks: { + beforeRequest: [ + options => { + options.prefixUrl = 'https://cats.com'; + } + ] + } + }); + //=> 'https://cats.com/unicorn' + })(); + ``` + */ + prefixUrl?: string | URL; + /** + __Note #1__: The `body` option cannot be used with the `json` or `form` option. + + __Note #2__: If you provide this option, `got.stream()` will be read-only. + + __Note #3__: If you provide a payload with the `GET` or `HEAD` method, it will throw a `TypeError` unless the method is `GET` and the `allowGetBody` option is set to `true`. + + __Note #4__: This option is not enumerable and will not be merged with the instance defaults. + + The `content-length` header will be automatically set if `body` is a `string` / `Buffer` / `fs.createReadStream` instance / [`form-data` instance](https://github.com/form-data/form-data), and `content-length` and `transfer-encoding` are not manually set in `options.headers`. + */ + body?: string | Buffer | Readable; + /** + The form body is converted to a query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj). + + If the `Content-Type` header is not present, it will be set to `application/x-www-form-urlencoded`. + + __Note #1__: If you provide this option, `got.stream()` will be read-only. + + __Note #2__: This option is not enumerable and will not be merged with the instance defaults. + */ + form?: Record; + /** + JSON body. If the `Content-Type` header is not set, it will be set to `application/json`. + + __Note #1__: If you provide this option, `got.stream()` will be read-only. + + __Note #2__: This option is not enumerable and will not be merged with the instance defaults. + */ + json?: Record; + /** + The URL to request, as a string, a [`https.request` options object](https://nodejs.org/api/https.html#https_https_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url). + + Properties from `options` will override properties in the parsed `url`. + + If no protocol is specified, it will throw a `TypeError`. + + __Note__: The query string is **not** parsed as search params. + + @example + ``` + got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b + got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b + + // The query string is overridden by `searchParams` + got('https://example.com/?query=a b', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b + ``` + */ + url?: string | URL; + /** + Cookie support. You don't have to care about parsing or how to store them. + + __Note__: If you provide this option, `options.headers.cookie` will be overridden. + */ + cookieJar?: PromiseCookieJar | ToughCookieJar; + /** + Ignore invalid cookies instead of throwing an error. + Only useful when the `cookieJar` option has been set. Not recommended. + + @default false + */ + ignoreInvalidCookies?: boolean; + /** + Query string that will be added to the request URL. + This will override the query string in `url`. + + If you need to pass in an array, you can do it using a `URLSearchParams` instance. + + @example + ``` + const got = require('got'); + + const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]); + + got('https://example.com', {searchParams}); + + console.log(searchParams.toString()); + //=> 'key=a&key=b' + ``` + */ + searchParams?: string | Record | URLSearchParams; + /** + An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups. + Useful when making lots of requests to different *public* hostnames. + + `CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay. + + __Note__: This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc. + + @default false + */ + dnsCache?: CacheableLookup | boolean; + /** + User data. In contrast to other options, `context` is not enumerable. + + __Note__: The object is never merged, it's just passed through. + Got will not modify the object in any way. + + @example + ``` + const got = require('got'); + + const instance = got.extend({ + hooks: { + beforeRequest: [ + options => { + if (!options.context || !options.context.token) { + throw new Error('Token required'); + } + + options.headers.token = options.context.token; + } + ] + } + }); + + (async () => { + const context = { + token: 'secret' + }; + + const response = await instance('https://httpbin.org/headers', {context}); + + // Let's see the headers + console.log(response.body); + })(); + ``` + */ + context?: Record; + /** + Hooks allow modifications during the request lifecycle. + Hook functions may be async and are run serially. + */ + hooks?: Hooks; + /** + Defines if redirect responses should be followed automatically. + + Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. + This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). + + @default true + */ + followRedirect?: boolean; + /** + If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. + + @default 10 + */ + maxRedirects?: number; + /** + A cache adapter instance for storing cached response data. + + @default false + */ + cache?: string | CacheableRequest.StorageAdapter | false; + /** + Determines if a `got.HTTPError` is thrown for unsuccessful responses. + + If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. + This may be useful if you are checking for resource availability and are expecting error responses. + + @default true + */ + throwHttpErrors?: boolean; + username?: string; + password?: string; + /** + If set to `true`, Got will additionally accept HTTP2 requests. + + It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol. + + __Note__: Overriding `options.request` will disable HTTP2 support. + + __Note__: This option will default to `true` in the next upcoming major release. + + @default false + + @example + ``` + const got = require('got'); + + (async () => { + const {headers} = await got('https://nghttp2.org/httpbin/anything', {http2: true}); + console.log(headers.via); + //=> '2 nghttpx' + })(); + ``` + */ + http2?: boolean; + /** + Set this to `true` to allow sending body for the `GET` method. + However, the [HTTP/2 specification](https://tools.ietf.org/html/rfc7540#section-8.1.3) says that `An HTTP GET request includes request header fields and no payload body`, therefore when using the HTTP/2 protocol this option will have no effect. + This option is only meant to interact with non-compliant servers when you have no other choice. + + __Note__: The [RFC 7321](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore __it's considered an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern)__. + + @default false + */ + allowGetBody?: boolean; + lookup?: CacheableLookup['lookup']; + /** + Request headers. + + Existing headers will be overwritten. Headers set to `undefined` will be omitted. + + @default {} + */ + headers?: Headers; + /** + By default, redirects will use [method rewriting](https://tools.ietf.org/html/rfc7231#section-6.4). + For example, when sending a POST request and receiving a `302`, it will resend the body to the new location using the same HTTP method (`POST` in this case). + + @default true + */ + methodRewriting?: boolean; + /** + Indicates which DNS record family to use. + + Values: + - `auto`: IPv4 (if present) or IPv6 + - `ipv4`: Only IPv4 + - `ipv6`: Only IPv6 + + __Note__: If you are using the undocumented option `family`, `dnsLookupIpVersion` will override it. + + @default 'auto' + */ + dnsLookupIpVersion?: DnsLookupIpVersion; + /** + A function used to parse JSON responses. + + @example + ``` + const got = require('got'); + const Bourne = require('@hapi/bourne'); + + (async () => { + const parsed = await got('https://example.com', { + parseJson: text => Bourne.parse(text) + }).json(); + + console.log(parsed); + })(); + ``` + */ + parseJson?: ParseJsonFunction; + /** + A function used to stringify the body of JSON requests. + + @example + ``` + const got = require('got'); + + (async () => { + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (key.startsWith('_')) { + return; + } + + return value; + }), + json: { + some: 'payload', + _ignoreMe: 1234 + } + }); + })(); + ``` + + @example + ``` + const got = require('got'); + + (async () => { + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (typeof value === 'number') { + return value.toString(); + } + + return value; + }), + json: { + some: 'payload', + number: 1 + } + }); + })(); + ``` + */ + stringifyJson?: StringifyJsonFunction; + /** + An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes. + + Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1). + + The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. + The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry). + + By default, it retries *only* on the specified methods, status codes, and on these network errors: + + - `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached. + - `ECONNRESET`: Connection was forcibly closed by a peer. + - `EADDRINUSE`: Could not bind to any free port. + - `ECONNREFUSED`: Connection was refused by the server. + - `EPIPE`: The remote side of the stream being written has been closed. + - `ENOTFOUND`: Couldn't resolve the hostname to an IP address. + - `ENETUNREACH`: No internet connection. + - `EAI_AGAIN`: DNS lookup timed out. + + __Note__: If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. + __Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. + */ + retry?: Partial | number; + /** + The IP address used to send the request from. + */ + localAddress?: string; + socketPath?: string; + /** + The HTTP method used to make the request. + + @default 'GET' + */ + method?: Method; + createConnection?: (options: http.RequestOptions, oncreate: (error: Error, socket: Socket) => void) => Socket; + cacheOptions?: CacheOptions; + /** + If set to `false`, all invalid SSL certificates will be ignored and no error will be thrown. + + If set to `true`, it will throw an error whenever an invalid SSL certificate is detected. + + We strongly recommend to have this set to `true` for security reasons. + + @default true + + @example + ``` + const got = require('got'); + + (async () => { + // Correct: + await got('https://example.com', {rejectUnauthorized: true}); + + // You can disable it when developing an HTTPS app: + await got('https://localhost', {rejectUnauthorized: false}); + + // Never do this: + await got('https://example.com', {rejectUnauthorized: false}); + })(); + ``` + */ + rejectUnauthorized?: boolean; + /** + Options for the advanced HTTPS API. + */ + https?: HTTPSOptions; +} +export interface Options extends PromiseOnly.Options, PlainOptions { +} +export interface HTTPSOptions { + rejectUnauthorized?: https.RequestOptions['rejectUnauthorized']; + checkServerIdentity?: CheckServerIdentityFunction; + /** + Override the default Certificate Authorities ([from Mozilla](https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport)). + + @example + ``` + // Single Certificate Authority + got('https://example.com', { + https: { + certificateAuthority: fs.readFileSync('./my_ca.pem') + } + }); + ``` + */ + certificateAuthority?: SecureContextOptions['ca']; + /** + Private keys in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format. + + [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) allows the option of private keys being encrypted. + Encrypted keys will be decrypted with `options.https.passphrase`. + + Multiple keys with different passphrases can be provided as an array of `{pem: , passphrase: }` + */ + key?: SecureContextOptions['key']; + /** + [Certificate chains](https://en.wikipedia.org/wiki/X.509#Certificate_chains_and_cross-certification) in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format. + + One cert chain should be provided per private key (`options.https.key`). + + When providing multiple cert chains, they do not have to be in the same order as their private keys in `options.https.key`. + + If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail. + */ + certificate?: SecureContextOptions['cert']; + /** + The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation). + */ + passphrase?: SecureContextOptions['passphrase']; + pfx?: SecureContextOptions['pfx']; +} +interface NormalizedPlainOptions extends PlainOptions { + method: Method; + url: URL; + timeout: Delays; + prefixUrl: string; + ignoreInvalidCookies: boolean; + decompress: boolean; + searchParams?: URLSearchParams; + cookieJar?: PromiseCookieJar; + headers: Headers; + context: Record; + hooks: Required; + followRedirect: boolean; + maxRedirects: number; + cache?: string | CacheableRequest.StorageAdapter; + throwHttpErrors: boolean; + dnsCache?: CacheableLookup; + http2: boolean; + allowGetBody: boolean; + rejectUnauthorized: boolean; + lookup?: CacheableLookup['lookup']; + methodRewriting: boolean; + username: string; + password: string; + parseJson: ParseJsonFunction; + stringifyJson: StringifyJsonFunction; + retry: RequiredRetryOptions; + cacheOptions: CacheOptions; + [kRequest]: HttpRequestFunction; + [kIsNormalizedAlready]?: boolean; +} +export interface NormalizedOptions extends PromiseOnly.NormalizedOptions, NormalizedPlainOptions { +} +interface PlainDefaults { + timeout: Delays; + prefixUrl: string; + method: Method; + ignoreInvalidCookies: boolean; + decompress: boolean; + context: Record; + cookieJar?: PromiseCookieJar | ToughCookieJar; + dnsCache?: CacheableLookup; + headers: Headers; + hooks: Required; + followRedirect: boolean; + maxRedirects: number; + cache?: string | CacheableRequest.StorageAdapter; + throwHttpErrors: boolean; + http2: boolean; + allowGetBody: boolean; + https?: HTTPSOptions; + methodRewriting: boolean; + parseJson: ParseJsonFunction; + stringifyJson: StringifyJsonFunction; + retry: RequiredRetryOptions; + agent?: Agents | false; + request?: RequestFunction; + searchParams?: URLSearchParams; + lookup?: CacheableLookup['lookup']; + localAddress?: string; + createConnection?: Options['createConnection']; + cacheOptions: CacheOptions; +} +export interface Defaults extends PromiseOnly.Defaults, PlainDefaults { +} +export interface Progress { + percent: number; + transferred: number; + total?: number; +} +export interface PlainResponse extends IncomingMessageWithTimings { + /** + The original request URL. + */ + requestUrl: string; + /** + The redirect URLs. + */ + redirectUrls: string[]; + /** + - `options` - The Got options that were set on this request. + + __Note__: This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest). + */ + request: Request; + /** + The remote IP address. + + This is hopefully a temporary limitation, see [lukechilds/cacheable-request#86](https://github.com/lukechilds/cacheable-request/issues/86). + + __Note__: Not available when the response is cached. + */ + ip?: string; + /** + Whether the response was retrieved from the cache. + */ + isFromCache: boolean; + /** + The status code of the response. + */ + statusCode: number; + /** + The request URL or the final URL after redirects. + */ + url: string; + /** + The object contains the following properties: + + - `start` - Time when the request started. + - `socket` - Time when a socket was assigned to the request. + - `lookup` - Time when the DNS lookup finished. + - `connect` - Time when the socket successfully connected. + - `secureConnect` - Time when the socket securely connected. + - `upload` - Time when the request finished uploading. + - `response` - Time when the request fired `response` event. + - `end` - Time when the response fired `end` event. + - `error` - Time when the request fired `error` event. + - `abort` - Time when the request fired `abort` event. + - `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + + If something has not been measured yet, it will be `undefined`. + + __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + */ + timings: Timings; + /** + The number of times the request was retried. + */ + retryCount: number; + /** + The raw result of the request. + */ + rawBody?: Buffer; + /** + The result of the request. + */ + body?: unknown; +} +export interface Response extends PlainResponse { + /** + The result of the request. + */ + body: T; + /** + The raw result of the request. + */ + rawBody: Buffer; +} +export interface RequestEvents { + /** + `request` event to get the request object of the request. + + __Tip__: You can use `request` event to abort requests. + + @example + ``` + got.stream('https://github.com') + .on('request', request => setTimeout(() => request.destroy(), 50)); + ``` + */ + on: ((name: 'request', listener: (request: http.ClientRequest) => void) => T) + /** + The `response` event to get the response object of the final request. + */ + & ((name: 'response', listener: (response: R) => void) => T) + /** + The `redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location. + */ + & ((name: 'redirect', listener: (response: R, nextOptions: N) => void) => T) + /** + Progress events for uploading (sending a request) and downloading (receiving a response). + The `progress` argument is an object like: + + ```js + { + percent: 0.1, + transferred: 1024, + total: 10240 + } + ``` + + If the `content-length` header is missing, `total` will be `undefined`. + + @example + ```js + (async () => { + const response = await got('https://sindresorhus.com') + .on('downloadProgress', progress => { + // Report download progress + }) + .on('uploadProgress', progress => { + // Report upload progress + }); + + console.log(response); + })(); + ``` + */ + & ((name: 'uploadProgress' | 'downloadProgress', listener: (progress: Progress) => void) => T) + /** + To enable retrying on a Got stream, it is required to have a `retry` handler attached. + + When this event is emitted, you should reset the stream you were writing to and prepare the body again. + + See `got.options.retry` for more information. + */ + & ((name: 'retry', listener: (retryCount: number, error: RequestError) => void) => T); +} +export declare const setNonEnumerableProperties: (sources: Array, to: Options) => void; +/** +An error to be thrown when a request fails. +Contains a `code` property with error class code, like `ECONNREFUSED`. +*/ +export declare class RequestError extends Error { + code?: string; + stack: string; + readonly options: NormalizedOptions; + readonly response?: Response; + readonly request?: Request; + readonly timings?: Timings; + constructor(message: string, error: Partial, self: Request | NormalizedOptions); +} +/** +An error to be thrown when the server redirects you more than ten times. +Includes a `response` property. +*/ +export declare class MaxRedirectsError extends RequestError { + readonly response: Response; + readonly request: Request; + readonly timings: Timings; + constructor(request: Request); +} +/** +An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. +Includes a `response` property. +*/ +export declare class HTTPError extends RequestError { + readonly response: Response; + readonly request: Request; + readonly timings: Timings; + constructor(response: Response); +} +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +export declare class CacheError extends RequestError { + readonly request: Request; + constructor(error: Error, request: Request); +} +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +export declare class UploadError extends RequestError { + readonly request: Request; + constructor(error: Error, request: Request); +} +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +export declare class TimeoutError extends RequestError { + readonly request: Request; + readonly timings: Timings; + readonly event: string; + constructor(error: TimedOutTimeoutError, timings: Timings, request: Request); +} +/** +An error to be thrown when reading from response stream fails. +*/ +export declare class ReadError extends RequestError { + readonly request: Request; + readonly response: Response; + readonly timings: Timings; + constructor(error: Error, request: Request); +} +/** +An error to be thrown when given an unsupported protocol. +*/ +export declare class UnsupportedProtocolError extends RequestError { + constructor(options: NormalizedOptions); +} +export default class Request extends Duplex implements RequestEvents { + ['constructor']: typeof Request; + [kUnproxyEvents]: () => void; + _cannotHaveBody: boolean; + [kDownloadedSize]: number; + [kUploadedSize]: number; + [kStopReading]: boolean; + [kTriggerRead]: boolean; + [kBody]: Options['body']; + [kJobs]: Array<() => void>; + [kRetryTimeout]?: NodeJS.Timeout; + [kBodySize]?: number; + [kServerResponsesPiped]: Set; + [kIsFromCache]?: boolean; + [kStartedReading]?: boolean; + [kCancelTimeouts]?: () => void; + [kResponseSize]?: number; + [kResponse]?: IncomingMessageWithTimings; + [kOriginalResponse]?: IncomingMessageWithTimings; + [kRequest]?: ClientRequest; + _noPipe?: boolean; + _progressCallbacks: Array<() => void>; + options: NormalizedOptions; + requestUrl: string; + requestInitialized: boolean; + redirects: string[]; + retryCount: number; + constructor(url: string | URL | undefined, options?: Options, defaults?: Defaults); + static normalizeArguments(url?: string | URL, options?: Options, defaults?: Defaults): NormalizedOptions; + _lockWrite(): void; + _unlockWrite(): void; + _finalizeBody(): Promise; + _onResponseBase(response: IncomingMessageWithTimings): Promise; + _onResponse(response: IncomingMessageWithTimings): Promise; + _onRequest(request: ClientRequest): void; + _createCacheableRequest(url: URL, options: RequestOptions): Promise; + _makeRequest(): Promise; + _error(error: RequestError): Promise; + _beforeError(error: Error): void; + _read(): void; + _write(chunk: any, encoding: string | undefined, callback: (error?: Error | null) => void): void; + _writeRequest(chunk: any, encoding: BufferEncoding | undefined, callback: (error?: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error: Error | null) => void): void; + get _isAboutToError(): boolean; + /** + The remote IP address. + */ + get ip(): string | undefined; + /** + Indicates whether the request has been aborted or not. + */ + get aborted(): boolean; + get socket(): Socket | undefined; + /** + Progress event for downloading (receiving a response). + */ + get downloadProgress(): Progress; + /** + Progress event for uploading (sending a request). + */ + get uploadProgress(): Progress; + /** + The object contains the following properties: + + - `start` - Time when the request started. + - `socket` - Time when a socket was assigned to the request. + - `lookup` - Time when the DNS lookup finished. + - `connect` - Time when the socket successfully connected. + - `secureConnect` - Time when the socket securely connected. + - `upload` - Time when the request finished uploading. + - `response` - Time when the request fired `response` event. + - `end` - Time when the response fired `end` event. + - `error` - Time when the request fired `error` event. + - `abort` - Time when the request fired `abort` event. + - `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + + If something has not been measured yet, it will be `undefined`. + + __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + */ + get timings(): Timings | undefined; + /** + Whether the response was retrieved from the cache. + */ + get isFromCache(): boolean | undefined; + pipe(destination: T, options?: { + end?: boolean; + }): T; + unpipe(destination: T): this; +} +export {}; diff --git a/node_modules/got/dist/source/core/index.js b/node_modules/got/dist/source/core/index.js new file mode 100644 index 0000000..541b06f --- /dev/null +++ b/node_modules/got/dist/source/core/index.js @@ -0,0 +1,1491 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UnsupportedProtocolError = exports.ReadError = exports.TimeoutError = exports.UploadError = exports.CacheError = exports.HTTPError = exports.MaxRedirectsError = exports.RequestError = exports.setNonEnumerableProperties = exports.knownHookEvents = exports.withoutBody = exports.kIsNormalizedAlready = void 0; +const util_1 = require("util"); +const stream_1 = require("stream"); +const fs_1 = require("fs"); +const url_1 = require("url"); +const http = require("http"); +const http_1 = require("http"); +const https = require("https"); +const http_timer_1 = require("@szmarczak/http-timer"); +const cacheable_lookup_1 = require("cacheable-lookup"); +const CacheableRequest = require("cacheable-request"); +const decompressResponse = require("decompress-response"); +// @ts-expect-error Missing types +const http2wrapper = require("http2-wrapper"); +const lowercaseKeys = require("lowercase-keys"); +const is_1 = require("@sindresorhus/is"); +const get_body_size_1 = require("./utils/get-body-size"); +const is_form_data_1 = require("./utils/is-form-data"); +const proxy_events_1 = require("./utils/proxy-events"); +const timed_out_1 = require("./utils/timed-out"); +const url_to_options_1 = require("./utils/url-to-options"); +const options_to_url_1 = require("./utils/options-to-url"); +const weakable_map_1 = require("./utils/weakable-map"); +const get_buffer_1 = require("./utils/get-buffer"); +const dns_ip_version_1 = require("./utils/dns-ip-version"); +const is_response_ok_1 = require("./utils/is-response-ok"); +const deprecation_warning_1 = require("../utils/deprecation-warning"); +const normalize_arguments_1 = require("../as-promise/normalize-arguments"); +const calculate_retry_delay_1 = require("./calculate-retry-delay"); +let globalDnsCache; +const kRequest = Symbol('request'); +const kResponse = Symbol('response'); +const kResponseSize = Symbol('responseSize'); +const kDownloadedSize = Symbol('downloadedSize'); +const kBodySize = Symbol('bodySize'); +const kUploadedSize = Symbol('uploadedSize'); +const kServerResponsesPiped = Symbol('serverResponsesPiped'); +const kUnproxyEvents = Symbol('unproxyEvents'); +const kIsFromCache = Symbol('isFromCache'); +const kCancelTimeouts = Symbol('cancelTimeouts'); +const kStartedReading = Symbol('startedReading'); +const kStopReading = Symbol('stopReading'); +const kTriggerRead = Symbol('triggerRead'); +const kBody = Symbol('body'); +const kJobs = Symbol('jobs'); +const kOriginalResponse = Symbol('originalResponse'); +const kRetryTimeout = Symbol('retryTimeout'); +exports.kIsNormalizedAlready = Symbol('isNormalizedAlready'); +const supportsBrotli = is_1.default.string(process.versions.brotli); +exports.withoutBody = new Set(['GET', 'HEAD']); +exports.knownHookEvents = [ + 'init', + 'beforeRequest', + 'beforeRedirect', + 'beforeError', + 'beforeRetry', + // Promise-Only + 'afterResponse' +]; +function validateSearchParameters(searchParameters) { + // eslint-disable-next-line guard-for-in + for (const key in searchParameters) { + const value = searchParameters[key]; + if (!is_1.default.string(value) && !is_1.default.number(value) && !is_1.default.boolean(value) && !is_1.default.null_(value) && !is_1.default.undefined(value)) { + throw new TypeError(`The \`searchParams\` value '${String(value)}' must be a string, number, boolean or null`); + } + } +} +function isClientRequest(clientRequest) { + return is_1.default.object(clientRequest) && !('statusCode' in clientRequest); +} +const cacheableStore = new weakable_map_1.default(); +const waitForOpenFile = async (file) => new Promise((resolve, reject) => { + const onError = (error) => { + reject(error); + }; + // Node.js 12 has incomplete types + if (!file.pending) { + resolve(); + } + file.once('error', onError); + file.once('ready', () => { + file.off('error', onError); + resolve(); + }); +}); +const redirectCodes = new Set([300, 301, 302, 303, 304, 307, 308]); +const nonEnumerableProperties = [ + 'context', + 'body', + 'json', + 'form' +]; +exports.setNonEnumerableProperties = (sources, to) => { + // Non enumerable properties shall not be merged + const properties = {}; + for (const source of sources) { + if (!source) { + continue; + } + for (const name of nonEnumerableProperties) { + if (!(name in source)) { + continue; + } + properties[name] = { + writable: true, + configurable: true, + enumerable: false, + // @ts-expect-error TS doesn't see the check above + value: source[name] + }; + } + } + Object.defineProperties(to, properties); +}; +/** +An error to be thrown when a request fails. +Contains a `code` property with error class code, like `ECONNREFUSED`. +*/ +class RequestError extends Error { + constructor(message, error, self) { + var _a; + super(message); + Error.captureStackTrace(this, this.constructor); + this.name = 'RequestError'; + this.code = error.code; + if (self instanceof Request) { + Object.defineProperty(this, 'request', { + enumerable: false, + value: self + }); + Object.defineProperty(this, 'response', { + enumerable: false, + value: self[kResponse] + }); + Object.defineProperty(this, 'options', { + // This fails because of TS 3.7.2 useDefineForClassFields + // Ref: https://github.com/microsoft/TypeScript/issues/34972 + enumerable: false, + value: self.options + }); + } + else { + Object.defineProperty(this, 'options', { + // This fails because of TS 3.7.2 useDefineForClassFields + // Ref: https://github.com/microsoft/TypeScript/issues/34972 + enumerable: false, + value: self + }); + } + this.timings = (_a = this.request) === null || _a === void 0 ? void 0 : _a.timings; + // Recover the original stacktrace + if (is_1.default.string(error.stack) && is_1.default.string(this.stack)) { + const indexOfMessage = this.stack.indexOf(this.message) + this.message.length; + const thisStackTrace = this.stack.slice(indexOfMessage).split('\n').reverse(); + const errorStackTrace = error.stack.slice(error.stack.indexOf(error.message) + error.message.length).split('\n').reverse(); + // Remove duplicated traces + while (errorStackTrace.length !== 0 && errorStackTrace[0] === thisStackTrace[0]) { + thisStackTrace.shift(); + } + this.stack = `${this.stack.slice(0, indexOfMessage)}${thisStackTrace.reverse().join('\n')}${errorStackTrace.reverse().join('\n')}`; + } + } +} +exports.RequestError = RequestError; +/** +An error to be thrown when the server redirects you more than ten times. +Includes a `response` property. +*/ +class MaxRedirectsError extends RequestError { + constructor(request) { + super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request); + this.name = 'MaxRedirectsError'; + } +} +exports.MaxRedirectsError = MaxRedirectsError; +/** +An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. +Includes a `response` property. +*/ +class HTTPError extends RequestError { + constructor(response) { + super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request); + this.name = 'HTTPError'; + } +} +exports.HTTPError = HTTPError; +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +class CacheError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'CacheError'; + } +} +exports.CacheError = CacheError; +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +class UploadError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'UploadError'; + } +} +exports.UploadError = UploadError; +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +class TimeoutError extends RequestError { + constructor(error, timings, request) { + super(error.message, error, request); + this.name = 'TimeoutError'; + this.event = error.event; + this.timings = timings; + } +} +exports.TimeoutError = TimeoutError; +/** +An error to be thrown when reading from response stream fails. +*/ +class ReadError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'ReadError'; + } +} +exports.ReadError = ReadError; +/** +An error to be thrown when given an unsupported protocol. +*/ +class UnsupportedProtocolError extends RequestError { + constructor(options) { + super(`Unsupported protocol "${options.url.protocol}"`, {}, options); + this.name = 'UnsupportedProtocolError'; + } +} +exports.UnsupportedProtocolError = UnsupportedProtocolError; +const proxiedRequestEvents = [ + 'socket', + 'connect', + 'continue', + 'information', + 'upgrade', + 'timeout' +]; +class Request extends stream_1.Duplex { + constructor(url, options = {}, defaults) { + super({ + // This must be false, to enable throwing after destroy + // It is used for retry logic in Promise API + autoDestroy: false, + // It needs to be zero because we're just proxying the data to another stream + highWaterMark: 0 + }); + this[kDownloadedSize] = 0; + this[kUploadedSize] = 0; + this.requestInitialized = false; + this[kServerResponsesPiped] = new Set(); + this.redirects = []; + this[kStopReading] = false; + this[kTriggerRead] = false; + this[kJobs] = []; + this.retryCount = 0; + // TODO: Remove this when targeting Node.js >= 12 + this._progressCallbacks = []; + const unlockWrite = () => this._unlockWrite(); + const lockWrite = () => this._lockWrite(); + this.on('pipe', (source) => { + source.prependListener('data', unlockWrite); + source.on('data', lockWrite); + source.prependListener('end', unlockWrite); + source.on('end', lockWrite); + }); + this.on('unpipe', (source) => { + source.off('data', unlockWrite); + source.off('data', lockWrite); + source.off('end', unlockWrite); + source.off('end', lockWrite); + }); + this.on('pipe', source => { + if (source instanceof http_1.IncomingMessage) { + this.options.headers = { + ...source.headers, + ...this.options.headers + }; + } + }); + const { json, body, form } = options; + if (json || body || form) { + this._lockWrite(); + } + if (exports.kIsNormalizedAlready in options) { + this.options = options; + } + else { + try { + // @ts-expect-error Common TypeScript bug saying that `this.constructor` is not accessible + this.options = this.constructor.normalizeArguments(url, options, defaults); + } + catch (error) { + // TODO: Move this to `_destroy()` + if (is_1.default.nodeStream(options.body)) { + options.body.destroy(); + } + this.destroy(error); + return; + } + } + (async () => { + var _a; + try { + if (this.options.body instanceof fs_1.ReadStream) { + await waitForOpenFile(this.options.body); + } + const { url: normalizedURL } = this.options; + if (!normalizedURL) { + throw new TypeError('Missing `url` property'); + } + this.requestUrl = normalizedURL.toString(); + decodeURI(this.requestUrl); + await this._finalizeBody(); + await this._makeRequest(); + if (this.destroyed) { + (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroy(); + return; + } + // Queued writes etc. + for (const job of this[kJobs]) { + job(); + } + // Prevent memory leak + this[kJobs].length = 0; + this.requestInitialized = true; + } + catch (error) { + if (error instanceof RequestError) { + this._beforeError(error); + return; + } + // This is a workaround for https://github.com/nodejs/node/issues/33335 + if (!this.destroyed) { + this.destroy(error); + } + } + })(); + } + static normalizeArguments(url, options, defaults) { + var _a, _b, _c, _d, _e; + const rawOptions = options; + if (is_1.default.object(url) && !is_1.default.urlInstance(url)) { + options = { ...defaults, ...url, ...options }; + } + else { + if (url && options && options.url !== undefined) { + throw new TypeError('The `url` option is mutually exclusive with the `input` argument'); + } + options = { ...defaults, ...options }; + if (url !== undefined) { + options.url = url; + } + if (is_1.default.urlInstance(options.url)) { + options.url = new url_1.URL(options.url.toString()); + } + } + // TODO: Deprecate URL options in Got 12. + // Support extend-specific options + if (options.cache === false) { + options.cache = undefined; + } + if (options.dnsCache === false) { + options.dnsCache = undefined; + } + // Nice type assertions + is_1.assert.any([is_1.default.string, is_1.default.undefined], options.method); + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.headers); + is_1.assert.any([is_1.default.string, is_1.default.urlInstance, is_1.default.undefined], options.prefixUrl); + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.cookieJar); + is_1.assert.any([is_1.default.object, is_1.default.string, is_1.default.undefined], options.searchParams); + is_1.assert.any([is_1.default.object, is_1.default.string, is_1.default.undefined], options.cache); + is_1.assert.any([is_1.default.object, is_1.default.number, is_1.default.undefined], options.timeout); + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.context); + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.hooks); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.decompress); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.ignoreInvalidCookies); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.followRedirect); + is_1.assert.any([is_1.default.number, is_1.default.undefined], options.maxRedirects); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.throwHttpErrors); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.http2); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.allowGetBody); + is_1.assert.any([is_1.default.string, is_1.default.undefined], options.localAddress); + is_1.assert.any([dns_ip_version_1.isDnsLookupIpVersion, is_1.default.undefined], options.dnsLookupIpVersion); + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.https); + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.rejectUnauthorized); + if (options.https) { + is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.https.rejectUnauthorized); + is_1.assert.any([is_1.default.function_, is_1.default.undefined], options.https.checkServerIdentity); + is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.certificateAuthority); + is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.key); + is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.certificate); + is_1.assert.any([is_1.default.string, is_1.default.undefined], options.https.passphrase); + is_1.assert.any([is_1.default.string, is_1.default.buffer, is_1.default.array, is_1.default.undefined], options.https.pfx); + } + is_1.assert.any([is_1.default.object, is_1.default.undefined], options.cacheOptions); + // `options.method` + if (is_1.default.string(options.method)) { + options.method = options.method.toUpperCase(); + } + else { + options.method = 'GET'; + } + // `options.headers` + if (options.headers === (defaults === null || defaults === void 0 ? void 0 : defaults.headers)) { + options.headers = { ...options.headers }; + } + else { + options.headers = lowercaseKeys({ ...(defaults === null || defaults === void 0 ? void 0 : defaults.headers), ...options.headers }); + } + // Disallow legacy `url.Url` + if ('slashes' in options) { + throw new TypeError('The legacy `url.Url` has been deprecated. Use `URL` instead.'); + } + // `options.auth` + if ('auth' in options) { + throw new TypeError('Parameter `auth` is deprecated. Use `username` / `password` instead.'); + } + // `options.searchParams` + if ('searchParams' in options) { + if (options.searchParams && options.searchParams !== (defaults === null || defaults === void 0 ? void 0 : defaults.searchParams)) { + let searchParameters; + if (is_1.default.string(options.searchParams) || (options.searchParams instanceof url_1.URLSearchParams)) { + searchParameters = new url_1.URLSearchParams(options.searchParams); + } + else { + validateSearchParameters(options.searchParams); + searchParameters = new url_1.URLSearchParams(); + // eslint-disable-next-line guard-for-in + for (const key in options.searchParams) { + const value = options.searchParams[key]; + if (value === null) { + searchParameters.append(key, ''); + } + else if (value !== undefined) { + searchParameters.append(key, value); + } + } + } + // `normalizeArguments()` is also used to merge options + (_a = defaults === null || defaults === void 0 ? void 0 : defaults.searchParams) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => { + // Only use default if one isn't already defined + if (!searchParameters.has(key)) { + searchParameters.append(key, value); + } + }); + options.searchParams = searchParameters; + } + } + // `options.username` & `options.password` + options.username = (_b = options.username) !== null && _b !== void 0 ? _b : ''; + options.password = (_c = options.password) !== null && _c !== void 0 ? _c : ''; + // `options.prefixUrl` & `options.url` + if (is_1.default.undefined(options.prefixUrl)) { + options.prefixUrl = (_d = defaults === null || defaults === void 0 ? void 0 : defaults.prefixUrl) !== null && _d !== void 0 ? _d : ''; + } + else { + options.prefixUrl = options.prefixUrl.toString(); + if (options.prefixUrl !== '' && !options.prefixUrl.endsWith('/')) { + options.prefixUrl += '/'; + } + } + if (is_1.default.string(options.url)) { + if (options.url.startsWith('/')) { + throw new Error('`input` must not start with a slash when using `prefixUrl`'); + } + options.url = options_to_url_1.default(options.prefixUrl + options.url, options); + } + else if ((is_1.default.undefined(options.url) && options.prefixUrl !== '') || options.protocol) { + options.url = options_to_url_1.default(options.prefixUrl, options); + } + if (options.url) { + if ('port' in options) { + delete options.port; + } + // Make it possible to change `options.prefixUrl` + let { prefixUrl } = options; + Object.defineProperty(options, 'prefixUrl', { + set: (value) => { + const url = options.url; + if (!url.href.startsWith(value)) { + throw new Error(`Cannot change \`prefixUrl\` from ${prefixUrl} to ${value}: ${url.href}`); + } + options.url = new url_1.URL(value + url.href.slice(prefixUrl.length)); + prefixUrl = value; + }, + get: () => prefixUrl + }); + // Support UNIX sockets + let { protocol } = options.url; + if (protocol === 'unix:') { + protocol = 'http:'; + options.url = new url_1.URL(`http://unix${options.url.pathname}${options.url.search}`); + } + // Set search params + if (options.searchParams) { + // eslint-disable-next-line @typescript-eslint/no-base-to-string + options.url.search = options.searchParams.toString(); + } + // Protocol check + if (protocol !== 'http:' && protocol !== 'https:') { + throw new UnsupportedProtocolError(options); + } + // Update `username` + if (options.username === '') { + options.username = options.url.username; + } + else { + options.url.username = options.username; + } + // Update `password` + if (options.password === '') { + options.password = options.url.password; + } + else { + options.url.password = options.password; + } + } + // `options.cookieJar` + const { cookieJar } = options; + if (cookieJar) { + let { setCookie, getCookieString } = cookieJar; + is_1.assert.function_(setCookie); + is_1.assert.function_(getCookieString); + /* istanbul ignore next: Horrible `tough-cookie` v3 check */ + if (setCookie.length === 4 && getCookieString.length === 0) { + setCookie = util_1.promisify(setCookie.bind(options.cookieJar)); + getCookieString = util_1.promisify(getCookieString.bind(options.cookieJar)); + options.cookieJar = { + setCookie, + getCookieString: getCookieString + }; + } + } + // `options.cache` + const { cache } = options; + if (cache) { + if (!cacheableStore.has(cache)) { + cacheableStore.set(cache, new CacheableRequest(((requestOptions, handler) => { + const result = requestOptions[kRequest](requestOptions, handler); + // TODO: remove this when `cacheable-request` supports async request functions. + if (is_1.default.promise(result)) { + // @ts-expect-error + // We only need to implement the error handler in order to support HTTP2 caching. + // The result will be a promise anyway. + result.once = (event, handler) => { + if (event === 'error') { + result.catch(handler); + } + else if (event === 'abort') { + // The empty catch is needed here in case when + // it rejects before it's `await`ed in `_makeRequest`. + (async () => { + try { + const request = (await result); + request.once('abort', handler); + } + catch (_a) { } + })(); + } + else { + /* istanbul ignore next: safety check */ + throw new Error(`Unknown HTTP2 promise event: ${event}`); + } + return result; + }; + } + return result; + }), cache)); + } + } + // `options.cacheOptions` + options.cacheOptions = { ...options.cacheOptions }; + // `options.dnsCache` + if (options.dnsCache === true) { + if (!globalDnsCache) { + globalDnsCache = new cacheable_lookup_1.default(); + } + options.dnsCache = globalDnsCache; + } + else if (!is_1.default.undefined(options.dnsCache) && !options.dnsCache.lookup) { + throw new TypeError(`Parameter \`dnsCache\` must be a CacheableLookup instance or a boolean, got ${is_1.default(options.dnsCache)}`); + } + // `options.timeout` + if (is_1.default.number(options.timeout)) { + options.timeout = { request: options.timeout }; + } + else if (defaults && options.timeout !== defaults.timeout) { + options.timeout = { + ...defaults.timeout, + ...options.timeout + }; + } + else { + options.timeout = { ...options.timeout }; + } + // `options.context` + if (!options.context) { + options.context = {}; + } + // `options.hooks` + const areHooksDefault = options.hooks === (defaults === null || defaults === void 0 ? void 0 : defaults.hooks); + options.hooks = { ...options.hooks }; + for (const event of exports.knownHookEvents) { + if (event in options.hooks) { + if (is_1.default.array(options.hooks[event])) { + // See https://github.com/microsoft/TypeScript/issues/31445#issuecomment-576929044 + options.hooks[event] = [...options.hooks[event]]; + } + else { + throw new TypeError(`Parameter \`${event}\` must be an Array, got ${is_1.default(options.hooks[event])}`); + } + } + else { + options.hooks[event] = []; + } + } + if (defaults && !areHooksDefault) { + for (const event of exports.knownHookEvents) { + const defaultHooks = defaults.hooks[event]; + if (defaultHooks.length > 0) { + // See https://github.com/microsoft/TypeScript/issues/31445#issuecomment-576929044 + options.hooks[event] = [ + ...defaults.hooks[event], + ...options.hooks[event] + ]; + } + } + } + // DNS options + if ('family' in options) { + deprecation_warning_1.default('"options.family" was never documented, please use "options.dnsLookupIpVersion"'); + } + // HTTPS options + if (defaults === null || defaults === void 0 ? void 0 : defaults.https) { + options.https = { ...defaults.https, ...options.https }; + } + if ('rejectUnauthorized' in options) { + deprecation_warning_1.default('"options.rejectUnauthorized" is now deprecated, please use "options.https.rejectUnauthorized"'); + } + if ('checkServerIdentity' in options) { + deprecation_warning_1.default('"options.checkServerIdentity" was never documented, please use "options.https.checkServerIdentity"'); + } + if ('ca' in options) { + deprecation_warning_1.default('"options.ca" was never documented, please use "options.https.certificateAuthority"'); + } + if ('key' in options) { + deprecation_warning_1.default('"options.key" was never documented, please use "options.https.key"'); + } + if ('cert' in options) { + deprecation_warning_1.default('"options.cert" was never documented, please use "options.https.certificate"'); + } + if ('passphrase' in options) { + deprecation_warning_1.default('"options.passphrase" was never documented, please use "options.https.passphrase"'); + } + if ('pfx' in options) { + deprecation_warning_1.default('"options.pfx" was never documented, please use "options.https.pfx"'); + } + // Other options + if ('followRedirects' in options) { + throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.'); + } + if (options.agent) { + for (const key in options.agent) { + if (key !== 'http' && key !== 'https' && key !== 'http2') { + throw new TypeError(`Expected the \`options.agent\` properties to be \`http\`, \`https\` or \`http2\`, got \`${key}\``); + } + } + } + options.maxRedirects = (_e = options.maxRedirects) !== null && _e !== void 0 ? _e : 0; + // Set non-enumerable properties + exports.setNonEnumerableProperties([defaults, rawOptions], options); + return normalize_arguments_1.default(options, defaults); + } + _lockWrite() { + const onLockedWrite = () => { + throw new TypeError('The payload has been already provided'); + }; + this.write = onLockedWrite; + this.end = onLockedWrite; + } + _unlockWrite() { + this.write = super.write; + this.end = super.end; + } + async _finalizeBody() { + const { options } = this; + const { headers } = options; + const isForm = !is_1.default.undefined(options.form); + const isJSON = !is_1.default.undefined(options.json); + const isBody = !is_1.default.undefined(options.body); + const hasPayload = isForm || isJSON || isBody; + const cannotHaveBody = exports.withoutBody.has(options.method) && !(options.method === 'GET' && options.allowGetBody); + this._cannotHaveBody = cannotHaveBody; + if (hasPayload) { + if (cannotHaveBody) { + throw new TypeError(`The \`${options.method}\` method cannot be used with a body`); + } + if ([isBody, isForm, isJSON].filter(isTrue => isTrue).length > 1) { + throw new TypeError('The `body`, `json` and `form` options are mutually exclusive'); + } + if (isBody && + !(options.body instanceof stream_1.Readable) && + !is_1.default.string(options.body) && + !is_1.default.buffer(options.body) && + !is_form_data_1.default(options.body)) { + throw new TypeError('The `body` option must be a stream.Readable, string or Buffer'); + } + if (isForm && !is_1.default.object(options.form)) { + throw new TypeError('The `form` option must be an Object'); + } + { + // Serialize body + const noContentType = !is_1.default.string(headers['content-type']); + if (isBody) { + // Special case for https://github.com/form-data/form-data + if (is_form_data_1.default(options.body) && noContentType) { + headers['content-type'] = `multipart/form-data; boundary=${options.body.getBoundary()}`; + } + this[kBody] = options.body; + } + else if (isForm) { + if (noContentType) { + headers['content-type'] = 'application/x-www-form-urlencoded'; + } + this[kBody] = (new url_1.URLSearchParams(options.form)).toString(); + } + else { + if (noContentType) { + headers['content-type'] = 'application/json'; + } + this[kBody] = options.stringifyJson(options.json); + } + const uploadBodySize = await get_body_size_1.default(this[kBody], options.headers); + // See https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. For example, a Content-Length header + // field is normally sent in a POST request even when the value is 0 + // (indicating an empty payload body). A user agent SHOULD NOT send a + // Content-Length header field when the request message does not contain + // a payload body and the method semantics do not anticipate such a + // body. + if (is_1.default.undefined(headers['content-length']) && is_1.default.undefined(headers['transfer-encoding'])) { + if (!cannotHaveBody && !is_1.default.undefined(uploadBodySize)) { + headers['content-length'] = String(uploadBodySize); + } + } + } + } + else if (cannotHaveBody) { + this._lockWrite(); + } + else { + this._unlockWrite(); + } + this[kBodySize] = Number(headers['content-length']) || undefined; + } + async _onResponseBase(response) { + const { options } = this; + const { url } = options; + this[kOriginalResponse] = response; + if (options.decompress) { + response = decompressResponse(response); + } + const statusCode = response.statusCode; + const typedResponse = response; + typedResponse.statusMessage = typedResponse.statusMessage ? typedResponse.statusMessage : http.STATUS_CODES[statusCode]; + typedResponse.url = options.url.toString(); + typedResponse.requestUrl = this.requestUrl; + typedResponse.redirectUrls = this.redirects; + typedResponse.request = this; + typedResponse.isFromCache = response.fromCache || false; + typedResponse.ip = this.ip; + typedResponse.retryCount = this.retryCount; + this[kIsFromCache] = typedResponse.isFromCache; + this[kResponseSize] = Number(response.headers['content-length']) || undefined; + this[kResponse] = response; + response.once('end', () => { + this[kResponseSize] = this[kDownloadedSize]; + this.emit('downloadProgress', this.downloadProgress); + }); + response.once('error', (error) => { + // Force clean-up, because some packages don't do this. + // TODO: Fix decompress-response + response.destroy(); + this._beforeError(new ReadError(error, this)); + }); + response.once('aborted', () => { + this._beforeError(new ReadError({ + name: 'Error', + message: 'The server aborted pending request', + code: 'ECONNRESET' + }, this)); + }); + this.emit('downloadProgress', this.downloadProgress); + const rawCookies = response.headers['set-cookie']; + if (is_1.default.object(options.cookieJar) && rawCookies) { + let promises = rawCookies.map(async (rawCookie) => options.cookieJar.setCookie(rawCookie, url.toString())); + if (options.ignoreInvalidCookies) { + promises = promises.map(async (p) => p.catch(() => { })); + } + try { + await Promise.all(promises); + } + catch (error) { + this._beforeError(error); + return; + } + } + if (options.followRedirect && response.headers.location && redirectCodes.has(statusCode)) { + // We're being redirected, we don't care about the response. + // It'd be best to abort the request, but we can't because + // we would have to sacrifice the TCP connection. We don't want that. + response.resume(); + if (this[kRequest]) { + this[kCancelTimeouts](); + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete this[kRequest]; + this[kUnproxyEvents](); + } + const shouldBeGet = statusCode === 303 && options.method !== 'GET' && options.method !== 'HEAD'; + if (shouldBeGet || !options.methodRewriting) { + // Server responded with "see other", indicating that the resource exists at another location, + // and the client should request it from that location via GET or HEAD. + options.method = 'GET'; + if ('body' in options) { + delete options.body; + } + if ('json' in options) { + delete options.json; + } + if ('form' in options) { + delete options.form; + } + this[kBody] = undefined; + delete options.headers['content-length']; + } + if (this.redirects.length >= options.maxRedirects) { + this._beforeError(new MaxRedirectsError(this)); + return; + } + try { + // Do not remove. See https://github.com/sindresorhus/got/pull/214 + const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString(); + // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604 + const redirectUrl = new url_1.URL(redirectBuffer, url); + const redirectString = redirectUrl.toString(); + decodeURI(redirectString); + // Redirecting to a different site, clear sensitive data. + if (redirectUrl.hostname !== url.hostname || redirectUrl.port !== url.port) { + if ('host' in options.headers) { + delete options.headers.host; + } + if ('cookie' in options.headers) { + delete options.headers.cookie; + } + if ('authorization' in options.headers) { + delete options.headers.authorization; + } + if (options.username || options.password) { + options.username = ''; + options.password = ''; + } + } + else { + redirectUrl.username = options.username; + redirectUrl.password = options.password; + } + this.redirects.push(redirectString); + options.url = redirectUrl; + for (const hook of options.hooks.beforeRedirect) { + // eslint-disable-next-line no-await-in-loop + await hook(options, typedResponse); + } + this.emit('redirect', typedResponse, options); + await this._makeRequest(); + } + catch (error) { + this._beforeError(error); + return; + } + return; + } + if (options.isStream && options.throwHttpErrors && !is_response_ok_1.isResponseOk(typedResponse)) { + this._beforeError(new HTTPError(typedResponse)); + return; + } + response.on('readable', () => { + if (this[kTriggerRead]) { + this._read(); + } + }); + this.on('resume', () => { + response.resume(); + }); + this.on('pause', () => { + response.pause(); + }); + response.once('end', () => { + this.push(null); + }); + this.emit('response', response); + for (const destination of this[kServerResponsesPiped]) { + if (destination.headersSent) { + continue; + } + // eslint-disable-next-line guard-for-in + for (const key in response.headers) { + const isAllowed = options.decompress ? key !== 'content-encoding' : true; + const value = response.headers[key]; + if (isAllowed) { + destination.setHeader(key, value); + } + } + destination.statusCode = statusCode; + } + } + async _onResponse(response) { + try { + await this._onResponseBase(response); + } + catch (error) { + /* istanbul ignore next: better safe than sorry */ + this._beforeError(error); + } + } + _onRequest(request) { + const { options } = this; + const { timeout, url } = options; + http_timer_1.default(request); + this[kCancelTimeouts] = timed_out_1.default(request, timeout, url); + const responseEventName = options.cache ? 'cacheableResponse' : 'response'; + request.once(responseEventName, (response) => { + void this._onResponse(response); + }); + request.once('error', (error) => { + var _a; + // Force clean-up, because some packages (e.g. nock) don't do this. + request.destroy(); + // Node.js <= 12.18.2 mistakenly emits the response `end` first. + (_a = request.res) === null || _a === void 0 ? void 0 : _a.removeAllListeners('end'); + error = error instanceof timed_out_1.TimeoutError ? new TimeoutError(error, this.timings, this) : new RequestError(error.message, error, this); + this._beforeError(error); + }); + this[kUnproxyEvents] = proxy_events_1.default(request, this, proxiedRequestEvents); + this[kRequest] = request; + this.emit('uploadProgress', this.uploadProgress); + // Send body + const body = this[kBody]; + const currentRequest = this.redirects.length === 0 ? this : request; + if (is_1.default.nodeStream(body)) { + body.pipe(currentRequest); + body.once('error', (error) => { + this._beforeError(new UploadError(error, this)); + }); + } + else { + this._unlockWrite(); + if (!is_1.default.undefined(body)) { + this._writeRequest(body, undefined, () => { }); + currentRequest.end(); + this._lockWrite(); + } + else if (this._cannotHaveBody || this._noPipe) { + currentRequest.end(); + this._lockWrite(); + } + } + this.emit('request', request); + } + async _createCacheableRequest(url, options) { + return new Promise((resolve, reject) => { + // TODO: Remove `utils/url-to-options.ts` when `cacheable-request` is fixed + Object.assign(options, url_to_options_1.default(url)); + // `http-cache-semantics` checks this + // TODO: Fix this ignore. + // @ts-expect-error + delete options.url; + let request; + // This is ugly + const cacheRequest = cacheableStore.get(options.cache)(options, async (response) => { + // TODO: Fix `cacheable-response` + response._readableState.autoDestroy = false; + if (request) { + (await request).emit('cacheableResponse', response); + } + resolve(response); + }); + // Restore options + options.url = url; + cacheRequest.once('error', reject); + cacheRequest.once('request', async (requestOrPromise) => { + request = requestOrPromise; + resolve(request); + }); + }); + } + async _makeRequest() { + var _a, _b, _c, _d, _e; + const { options } = this; + const { headers } = options; + for (const key in headers) { + if (is_1.default.undefined(headers[key])) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete headers[key]; + } + else if (is_1.default.null_(headers[key])) { + throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${key}\` header`); + } + } + if (options.decompress && is_1.default.undefined(headers['accept-encoding'])) { + headers['accept-encoding'] = supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate'; + } + // Set cookies + if (options.cookieJar) { + const cookieString = await options.cookieJar.getCookieString(options.url.toString()); + if (is_1.default.nonEmptyString(cookieString)) { + options.headers.cookie = cookieString; + } + } + for (const hook of options.hooks.beforeRequest) { + // eslint-disable-next-line no-await-in-loop + const result = await hook(options); + if (!is_1.default.undefined(result)) { + // @ts-expect-error Skip the type mismatch to support abstract responses + options.request = () => result; + break; + } + } + if (options.body && this[kBody] !== options.body) { + this[kBody] = options.body; + } + const { agent, request, timeout, url } = options; + if (options.dnsCache && !('lookup' in options)) { + options.lookup = options.dnsCache.lookup; + } + // UNIX sockets + if (url.hostname === 'unix') { + const matches = /(?.+?):(?.+)/.exec(`${url.pathname}${url.search}`); + if (matches === null || matches === void 0 ? void 0 : matches.groups) { + const { socketPath, path } = matches.groups; + Object.assign(options, { + socketPath, + path, + host: '' + }); + } + } + const isHttps = url.protocol === 'https:'; + // Fallback function + let fallbackFn; + if (options.http2) { + fallbackFn = http2wrapper.auto; + } + else { + fallbackFn = isHttps ? https.request : http.request; + } + const realFn = (_a = options.request) !== null && _a !== void 0 ? _a : fallbackFn; + // Cache support + const fn = options.cache ? this._createCacheableRequest : realFn; + // Pass an agent directly when HTTP2 is disabled + if (agent && !options.http2) { + options.agent = agent[isHttps ? 'https' : 'http']; + } + // Prepare plain HTTP request options + options[kRequest] = realFn; + delete options.request; + // TODO: Fix this ignore. + // @ts-expect-error + delete options.timeout; + const requestOptions = options; + requestOptions.shared = (_b = options.cacheOptions) === null || _b === void 0 ? void 0 : _b.shared; + requestOptions.cacheHeuristic = (_c = options.cacheOptions) === null || _c === void 0 ? void 0 : _c.cacheHeuristic; + requestOptions.immutableMinTimeToLive = (_d = options.cacheOptions) === null || _d === void 0 ? void 0 : _d.immutableMinTimeToLive; + requestOptions.ignoreCargoCult = (_e = options.cacheOptions) === null || _e === void 0 ? void 0 : _e.ignoreCargoCult; + // If `dnsLookupIpVersion` is not present do not override `family` + if (options.dnsLookupIpVersion !== undefined) { + try { + requestOptions.family = dns_ip_version_1.dnsLookupIpVersionToFamily(options.dnsLookupIpVersion); + } + catch (_f) { + throw new Error('Invalid `dnsLookupIpVersion` option value'); + } + } + // HTTPS options remapping + if (options.https) { + if ('rejectUnauthorized' in options.https) { + requestOptions.rejectUnauthorized = options.https.rejectUnauthorized; + } + if (options.https.checkServerIdentity) { + requestOptions.checkServerIdentity = options.https.checkServerIdentity; + } + if (options.https.certificateAuthority) { + requestOptions.ca = options.https.certificateAuthority; + } + if (options.https.certificate) { + requestOptions.cert = options.https.certificate; + } + if (options.https.key) { + requestOptions.key = options.https.key; + } + if (options.https.passphrase) { + requestOptions.passphrase = options.https.passphrase; + } + if (options.https.pfx) { + requestOptions.pfx = options.https.pfx; + } + } + try { + let requestOrResponse = await fn(url, requestOptions); + if (is_1.default.undefined(requestOrResponse)) { + requestOrResponse = fallbackFn(url, requestOptions); + } + // Restore options + options.request = request; + options.timeout = timeout; + options.agent = agent; + // HTTPS options restore + if (options.https) { + if ('rejectUnauthorized' in options.https) { + delete requestOptions.rejectUnauthorized; + } + if (options.https.checkServerIdentity) { + // @ts-expect-error - This one will be removed when we remove the alias. + delete requestOptions.checkServerIdentity; + } + if (options.https.certificateAuthority) { + delete requestOptions.ca; + } + if (options.https.certificate) { + delete requestOptions.cert; + } + if (options.https.key) { + delete requestOptions.key; + } + if (options.https.passphrase) { + delete requestOptions.passphrase; + } + if (options.https.pfx) { + delete requestOptions.pfx; + } + } + if (isClientRequest(requestOrResponse)) { + this._onRequest(requestOrResponse); + // Emit the response after the stream has been ended + } + else if (this.writable) { + this.once('finish', () => { + void this._onResponse(requestOrResponse); + }); + this._unlockWrite(); + this.end(); + this._lockWrite(); + } + else { + void this._onResponse(requestOrResponse); + } + } + catch (error) { + if (error instanceof CacheableRequest.CacheError) { + throw new CacheError(error, this); + } + throw new RequestError(error.message, error, this); + } + } + async _error(error) { + try { + for (const hook of this.options.hooks.beforeError) { + // eslint-disable-next-line no-await-in-loop + error = await hook(error); + } + } + catch (error_) { + error = new RequestError(error_.message, error_, this); + } + this.destroy(error); + } + _beforeError(error) { + if (this[kStopReading]) { + return; + } + const { options } = this; + const retryCount = this.retryCount + 1; + this[kStopReading] = true; + if (!(error instanceof RequestError)) { + error = new RequestError(error.message, error, this); + } + const typedError = error; + const { response } = typedError; + void (async () => { + if (response && !response.body) { + response.setEncoding(this._readableState.encoding); + try { + response.rawBody = await get_buffer_1.default(response); + response.body = response.rawBody.toString(); + } + catch (_a) { } + } + if (this.listenerCount('retry') !== 0) { + let backoff; + try { + let retryAfter; + if (response && 'retry-after' in response.headers) { + retryAfter = Number(response.headers['retry-after']); + if (Number.isNaN(retryAfter)) { + retryAfter = Date.parse(response.headers['retry-after']) - Date.now(); + if (retryAfter <= 0) { + retryAfter = 1; + } + } + else { + retryAfter *= 1000; + } + } + backoff = await options.retry.calculateDelay({ + attemptCount: retryCount, + retryOptions: options.retry, + error: typedError, + retryAfter, + computedValue: calculate_retry_delay_1.default({ + attemptCount: retryCount, + retryOptions: options.retry, + error: typedError, + retryAfter, + computedValue: 0 + }) + }); + } + catch (error_) { + void this._error(new RequestError(error_.message, error_, this)); + return; + } + if (backoff) { + const retry = async () => { + try { + for (const hook of this.options.hooks.beforeRetry) { + // eslint-disable-next-line no-await-in-loop + await hook(this.options, typedError, retryCount); + } + } + catch (error_) { + void this._error(new RequestError(error_.message, error, this)); + return; + } + // Something forced us to abort the retry + if (this.destroyed) { + return; + } + this.destroy(); + this.emit('retry', retryCount, error); + }; + this[kRetryTimeout] = setTimeout(retry, backoff); + return; + } + } + void this._error(typedError); + })(); + } + _read() { + this[kTriggerRead] = true; + const response = this[kResponse]; + if (response && !this[kStopReading]) { + // We cannot put this in the `if` above + // because `.read()` also triggers the `end` event + if (response.readableLength) { + this[kTriggerRead] = false; + } + let data; + while ((data = response.read()) !== null) { + this[kDownloadedSize] += data.length; + this[kStartedReading] = true; + const progress = this.downloadProgress; + if (progress.percent < 1) { + this.emit('downloadProgress', progress); + } + this.push(data); + } + } + } + // Node.js 12 has incorrect types, so the encoding must be a string + _write(chunk, encoding, callback) { + const write = () => { + this._writeRequest(chunk, encoding, callback); + }; + if (this.requestInitialized) { + write(); + } + else { + this[kJobs].push(write); + } + } + _writeRequest(chunk, encoding, callback) { + if (this[kRequest].destroyed) { + // Probably the `ClientRequest` instance will throw + return; + } + this._progressCallbacks.push(() => { + this[kUploadedSize] += Buffer.byteLength(chunk, encoding); + const progress = this.uploadProgress; + if (progress.percent < 1) { + this.emit('uploadProgress', progress); + } + }); + // TODO: What happens if it's from cache? Then this[kRequest] won't be defined. + this[kRequest].write(chunk, encoding, (error) => { + if (!error && this._progressCallbacks.length > 0) { + this._progressCallbacks.shift()(); + } + callback(error); + }); + } + _final(callback) { + const endRequest = () => { + // FIX: Node.js 10 calls the write callback AFTER the end callback! + while (this._progressCallbacks.length !== 0) { + this._progressCallbacks.shift()(); + } + // We need to check if `this[kRequest]` is present, + // because it isn't when we use cache. + if (!(kRequest in this)) { + callback(); + return; + } + if (this[kRequest].destroyed) { + callback(); + return; + } + this[kRequest].end((error) => { + if (!error) { + this[kBodySize] = this[kUploadedSize]; + this.emit('uploadProgress', this.uploadProgress); + this[kRequest].emit('upload-complete'); + } + callback(error); + }); + }; + if (this.requestInitialized) { + endRequest(); + } + else { + this[kJobs].push(endRequest); + } + } + _destroy(error, callback) { + var _a; + this[kStopReading] = true; + // Prevent further retries + clearTimeout(this[kRetryTimeout]); + if (kRequest in this) { + this[kCancelTimeouts](); + // TODO: Remove the next `if` when these get fixed: + // - https://github.com/nodejs/node/issues/32851 + if (!((_a = this[kResponse]) === null || _a === void 0 ? void 0 : _a.complete)) { + this[kRequest].destroy(); + } + } + if (error !== null && !is_1.default.undefined(error) && !(error instanceof RequestError)) { + error = new RequestError(error.message, error, this); + } + callback(error); + } + get _isAboutToError() { + return this[kStopReading]; + } + /** + The remote IP address. + */ + get ip() { + var _a; + return (_a = this.socket) === null || _a === void 0 ? void 0 : _a.remoteAddress; + } + /** + Indicates whether the request has been aborted or not. + */ + get aborted() { + var _a, _b, _c; + return ((_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroyed) !== null && _b !== void 0 ? _b : this.destroyed) && !((_c = this[kOriginalResponse]) === null || _c === void 0 ? void 0 : _c.complete); + } + get socket() { + var _a, _b; + return (_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket) !== null && _b !== void 0 ? _b : undefined; + } + /** + Progress event for downloading (receiving a response). + */ + get downloadProgress() { + let percent; + if (this[kResponseSize]) { + percent = this[kDownloadedSize] / this[kResponseSize]; + } + else if (this[kResponseSize] === this[kDownloadedSize]) { + percent = 1; + } + else { + percent = 0; + } + return { + percent, + transferred: this[kDownloadedSize], + total: this[kResponseSize] + }; + } + /** + Progress event for uploading (sending a request). + */ + get uploadProgress() { + let percent; + if (this[kBodySize]) { + percent = this[kUploadedSize] / this[kBodySize]; + } + else if (this[kBodySize] === this[kUploadedSize]) { + percent = 1; + } + else { + percent = 0; + } + return { + percent, + transferred: this[kUploadedSize], + total: this[kBodySize] + }; + } + /** + The object contains the following properties: + + - `start` - Time when the request started. + - `socket` - Time when a socket was assigned to the request. + - `lookup` - Time when the DNS lookup finished. + - `connect` - Time when the socket successfully connected. + - `secureConnect` - Time when the socket securely connected. + - `upload` - Time when the request finished uploading. + - `response` - Time when the request fired `response` event. + - `end` - Time when the response fired `end` event. + - `error` - Time when the request fired `error` event. + - `abort` - Time when the request fired `abort` event. + - `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + + If something has not been measured yet, it will be `undefined`. + + __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + */ + get timings() { + var _a; + return (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.timings; + } + /** + Whether the response was retrieved from the cache. + */ + get isFromCache() { + return this[kIsFromCache]; + } + pipe(destination, options) { + if (this[kStartedReading]) { + throw new Error('Failed to pipe. The response has been emitted already.'); + } + if (destination instanceof http_1.ServerResponse) { + this[kServerResponsesPiped].add(destination); + } + return super.pipe(destination, options); + } + unpipe(destination) { + if (destination instanceof http_1.ServerResponse) { + this[kServerResponsesPiped].delete(destination); + } + super.unpipe(destination); + return this; + } +} +exports.default = Request; diff --git a/node_modules/got/dist/source/core/utils/dns-ip-version.d.ts b/node_modules/got/dist/source/core/utils/dns-ip-version.d.ts new file mode 100644 index 0000000..ea547cd --- /dev/null +++ b/node_modules/got/dist/source/core/utils/dns-ip-version.d.ts @@ -0,0 +1,5 @@ +export declare type DnsLookupIpVersion = 'auto' | 'ipv4' | 'ipv6'; +declare type DnsIpFamily = 0 | 4 | 6; +export declare const isDnsLookupIpVersion: (value: any) => boolean; +export declare const dnsLookupIpVersionToFamily: (dnsLookupIpVersion: DnsLookupIpVersion) => DnsIpFamily; +export {}; diff --git a/node_modules/got/dist/source/core/utils/dns-ip-version.js b/node_modules/got/dist/source/core/utils/dns-ip-version.js new file mode 100644 index 0000000..6f599c2 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/dns-ip-version.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dnsLookupIpVersionToFamily = exports.isDnsLookupIpVersion = void 0; +const conversionTable = { + auto: 0, + ipv4: 4, + ipv6: 6 +}; +exports.isDnsLookupIpVersion = (value) => { + return value in conversionTable; +}; +exports.dnsLookupIpVersionToFamily = (dnsLookupIpVersion) => { + if (exports.isDnsLookupIpVersion(dnsLookupIpVersion)) { + return conversionTable[dnsLookupIpVersion]; + } + throw new Error('Invalid DNS lookup IP version'); +}; diff --git a/node_modules/got/dist/source/core/utils/get-body-size.d.ts b/node_modules/got/dist/source/core/utils/get-body-size.d.ts new file mode 100644 index 0000000..9745f69 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/get-body-size.d.ts @@ -0,0 +1,3 @@ +import { ClientRequestArgs } from 'http'; +declare const _default: (body: unknown, headers: ClientRequestArgs['headers']) => Promise; +export default _default; diff --git a/node_modules/got/dist/source/core/utils/get-body-size.js b/node_modules/got/dist/source/core/utils/get-body-size.js new file mode 100644 index 0000000..0202342 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/get-body-size.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = require("fs"); +const util_1 = require("util"); +const is_1 = require("@sindresorhus/is"); +const is_form_data_1 = require("./is-form-data"); +const statAsync = util_1.promisify(fs_1.stat); +exports.default = async (body, headers) => { + if (headers && 'content-length' in headers) { + return Number(headers['content-length']); + } + if (!body) { + return 0; + } + if (is_1.default.string(body)) { + return Buffer.byteLength(body); + } + if (is_1.default.buffer(body)) { + return body.length; + } + if (is_form_data_1.default(body)) { + return util_1.promisify(body.getLength.bind(body))(); + } + if (body instanceof fs_1.ReadStream) { + const { size } = await statAsync(body.path); + if (size === 0) { + return undefined; + } + return size; + } + return undefined; +}; diff --git a/node_modules/got/dist/source/core/utils/get-buffer.d.ts b/node_modules/got/dist/source/core/utils/get-buffer.d.ts new file mode 100644 index 0000000..66eaada --- /dev/null +++ b/node_modules/got/dist/source/core/utils/get-buffer.d.ts @@ -0,0 +1,4 @@ +/// +import { Readable } from 'stream'; +declare const getBuffer: (stream: Readable) => Promise; +export default getBuffer; diff --git a/node_modules/got/dist/source/core/utils/get-buffer.js b/node_modules/got/dist/source/core/utils/get-buffer.js new file mode 100644 index 0000000..0155f08 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/get-buffer.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// TODO: Update https://github.com/sindresorhus/get-stream +const getBuffer = async (stream) => { + const chunks = []; + let length = 0; + for await (const chunk of stream) { + chunks.push(chunk); + length += Buffer.byteLength(chunk); + } + if (Buffer.isBuffer(chunks[0])) { + return Buffer.concat(chunks, length); + } + return Buffer.from(chunks.join('')); +}; +exports.default = getBuffer; diff --git a/node_modules/got/dist/source/core/utils/is-form-data.d.ts b/node_modules/got/dist/source/core/utils/is-form-data.d.ts new file mode 100644 index 0000000..02087b5 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/is-form-data.d.ts @@ -0,0 +1,8 @@ +/// +import { Readable } from 'stream'; +interface FormData extends Readable { + getBoundary: () => string; + getLength: (callback: (error: Error | null, length: number) => void) => void; +} +declare const _default: (body: unknown) => body is FormData; +export default _default; diff --git a/node_modules/got/dist/source/core/utils/is-form-data.js b/node_modules/got/dist/source/core/utils/is-form-data.js new file mode 100644 index 0000000..32c16cc --- /dev/null +++ b/node_modules/got/dist/source/core/utils/is-form-data.js @@ -0,0 +1,4 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const is_1 = require("@sindresorhus/is"); +exports.default = (body) => is_1.default.nodeStream(body) && is_1.default.function_(body.getBoundary); diff --git a/node_modules/got/dist/source/core/utils/is-response-ok.d.ts b/node_modules/got/dist/source/core/utils/is-response-ok.d.ts new file mode 100644 index 0000000..7e1d49a --- /dev/null +++ b/node_modules/got/dist/source/core/utils/is-response-ok.d.ts @@ -0,0 +1,2 @@ +import { Response } from '..'; +export declare const isResponseOk: (response: Response) => boolean; diff --git a/node_modules/got/dist/source/core/utils/is-response-ok.js b/node_modules/got/dist/source/core/utils/is-response-ok.js new file mode 100644 index 0000000..84c9331 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/is-response-ok.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isResponseOk = void 0; +exports.isResponseOk = (response) => { + const { statusCode } = response; + const limitStatusCode = response.request.options.followRedirect ? 299 : 399; + return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304; +}; diff --git a/node_modules/got/dist/source/core/utils/options-to-url.d.ts b/node_modules/got/dist/source/core/utils/options-to-url.d.ts new file mode 100644 index 0000000..c696a83 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/options-to-url.d.ts @@ -0,0 +1,14 @@ +import { URL } from 'url'; +export interface URLOptions { + href?: string; + protocol?: string; + host?: string; + hostname?: string; + port?: string | number; + pathname?: string; + search?: string; + searchParams?: unknown; + path?: string; +} +declare const _default: (origin: string, options: URLOptions) => URL; +export default _default; diff --git a/node_modules/got/dist/source/core/utils/options-to-url.js b/node_modules/got/dist/source/core/utils/options-to-url.js new file mode 100644 index 0000000..65be02f --- /dev/null +++ b/node_modules/got/dist/source/core/utils/options-to-url.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* istanbul ignore file: deprecated */ +const url_1 = require("url"); +const keys = [ + 'protocol', + 'host', + 'hostname', + 'port', + 'pathname', + 'search' +]; +exports.default = (origin, options) => { + var _a, _b; + if (options.path) { + if (options.pathname) { + throw new TypeError('Parameters `path` and `pathname` are mutually exclusive.'); + } + if (options.search) { + throw new TypeError('Parameters `path` and `search` are mutually exclusive.'); + } + if (options.searchParams) { + throw new TypeError('Parameters `path` and `searchParams` are mutually exclusive.'); + } + } + if (options.search && options.searchParams) { + throw new TypeError('Parameters `search` and `searchParams` are mutually exclusive.'); + } + if (!origin) { + if (!options.protocol) { + throw new TypeError('No URL protocol specified'); + } + origin = `${options.protocol}//${(_b = (_a = options.hostname) !== null && _a !== void 0 ? _a : options.host) !== null && _b !== void 0 ? _b : ''}`; + } + const url = new url_1.URL(origin); + if (options.path) { + const searchIndex = options.path.indexOf('?'); + if (searchIndex === -1) { + options.pathname = options.path; + } + else { + options.pathname = options.path.slice(0, searchIndex); + options.search = options.path.slice(searchIndex + 1); + } + delete options.path; + } + for (const key of keys) { + if (options[key]) { + url[key] = options[key].toString(); + } + } + return url; +}; diff --git a/node_modules/got/dist/source/core/utils/proxy-events.d.ts b/node_modules/got/dist/source/core/utils/proxy-events.d.ts new file mode 100644 index 0000000..b244d82 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/proxy-events.d.ts @@ -0,0 +1,3 @@ +/// +import { EventEmitter } from 'events'; +export default function (from: EventEmitter, to: EventEmitter, events: string[]): () => void; diff --git a/node_modules/got/dist/source/core/utils/proxy-events.js b/node_modules/got/dist/source/core/utils/proxy-events.js new file mode 100644 index 0000000..4d47c53 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/proxy-events.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function default_1(from, to, events) { + const fns = {}; + for (const event of events) { + fns[event] = (...args) => { + to.emit(event, ...args); + }; + from.on(event, fns[event]); + } + return () => { + for (const event of events) { + from.off(event, fns[event]); + } + }; +} +exports.default = default_1; diff --git a/node_modules/got/dist/source/core/utils/timed-out.d.ts b/node_modules/got/dist/source/core/utils/timed-out.d.ts new file mode 100644 index 0000000..5b495d4 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/timed-out.d.ts @@ -0,0 +1,29 @@ +import { ClientRequest } from 'http'; +declare const reentry: unique symbol; +interface TimedOutOptions { + host?: string; + hostname?: string; + protocol?: string; +} +export interface Delays { + lookup?: number; + connect?: number; + secureConnect?: number; + socket?: number; + response?: number; + send?: number; + request?: number; +} +export declare type ErrorCode = 'ETIMEDOUT' | 'ECONNRESET' | 'EADDRINUSE' | 'ECONNREFUSED' | 'EPIPE' | 'ENOTFOUND' | 'ENETUNREACH' | 'EAI_AGAIN'; +export declare class TimeoutError extends Error { + event: string; + code: ErrorCode; + constructor(threshold: number, event: string); +} +declare const _default: (request: ClientRequest, delays: Delays, options: TimedOutOptions) => () => void; +export default _default; +declare module 'http' { + interface ClientRequest { + [reentry]: boolean; + } +} diff --git a/node_modules/got/dist/source/core/utils/timed-out.js b/node_modules/got/dist/source/core/utils/timed-out.js new file mode 100644 index 0000000..8877016 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/timed-out.js @@ -0,0 +1,121 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TimeoutError = void 0; +const net = require("net"); +const unhandle_1 = require("./unhandle"); +const reentry = Symbol('reentry'); +const noop = () => { }; +class TimeoutError extends Error { + constructor(threshold, event) { + super(`Timeout awaiting '${event}' for ${threshold}ms`); + this.event = event; + this.name = 'TimeoutError'; + this.code = 'ETIMEDOUT'; + } +} +exports.TimeoutError = TimeoutError; +exports.default = (request, delays, options) => { + if (reentry in request) { + return noop; + } + request[reentry] = true; + const cancelers = []; + const { once, unhandleAll } = unhandle_1.default(); + const addTimeout = (delay, callback, event) => { + var _a; + const timeout = setTimeout(callback, delay, delay, event); + (_a = timeout.unref) === null || _a === void 0 ? void 0 : _a.call(timeout); + const cancel = () => { + clearTimeout(timeout); + }; + cancelers.push(cancel); + return cancel; + }; + const { host, hostname } = options; + const timeoutHandler = (delay, event) => { + request.destroy(new TimeoutError(delay, event)); + }; + const cancelTimeouts = () => { + for (const cancel of cancelers) { + cancel(); + } + unhandleAll(); + }; + request.once('error', error => { + cancelTimeouts(); + // Save original behavior + /* istanbul ignore next */ + if (request.listenerCount('error') === 0) { + throw error; + } + }); + request.once('close', cancelTimeouts); + once(request, 'response', (response) => { + once(response, 'end', cancelTimeouts); + }); + if (typeof delays.request !== 'undefined') { + addTimeout(delays.request, timeoutHandler, 'request'); + } + if (typeof delays.socket !== 'undefined') { + const socketTimeoutHandler = () => { + timeoutHandler(delays.socket, 'socket'); + }; + request.setTimeout(delays.socket, socketTimeoutHandler); + // `request.setTimeout(0)` causes a memory leak. + // We can just remove the listener and forget about the timer - it's unreffed. + // See https://github.com/sindresorhus/got/issues/690 + cancelers.push(() => { + request.removeListener('timeout', socketTimeoutHandler); + }); + } + once(request, 'socket', (socket) => { + var _a; + const { socketPath } = request; + /* istanbul ignore next: hard to test */ + if (socket.connecting) { + const hasPath = Boolean(socketPath !== null && socketPath !== void 0 ? socketPath : net.isIP((_a = hostname !== null && hostname !== void 0 ? hostname : host) !== null && _a !== void 0 ? _a : '') !== 0); + if (typeof delays.lookup !== 'undefined' && !hasPath && typeof socket.address().address === 'undefined') { + const cancelTimeout = addTimeout(delays.lookup, timeoutHandler, 'lookup'); + once(socket, 'lookup', cancelTimeout); + } + if (typeof delays.connect !== 'undefined') { + const timeConnect = () => addTimeout(delays.connect, timeoutHandler, 'connect'); + if (hasPath) { + once(socket, 'connect', timeConnect()); + } + else { + once(socket, 'lookup', (error) => { + if (error === null) { + once(socket, 'connect', timeConnect()); + } + }); + } + } + if (typeof delays.secureConnect !== 'undefined' && options.protocol === 'https:') { + once(socket, 'connect', () => { + const cancelTimeout = addTimeout(delays.secureConnect, timeoutHandler, 'secureConnect'); + once(socket, 'secureConnect', cancelTimeout); + }); + } + } + if (typeof delays.send !== 'undefined') { + const timeRequest = () => addTimeout(delays.send, timeoutHandler, 'send'); + /* istanbul ignore next: hard to test */ + if (socket.connecting) { + once(socket, 'connect', () => { + once(request, 'upload-complete', timeRequest()); + }); + } + else { + once(request, 'upload-complete', timeRequest()); + } + } + }); + if (typeof delays.response !== 'undefined') { + once(request, 'upload-complete', () => { + const cancelTimeout = addTimeout(delays.response, timeoutHandler, 'response'); + once(request, 'response', cancelTimeout); + }); + } + return cancelTimeouts; +}; diff --git a/node_modules/got/dist/source/core/utils/unhandle.d.ts b/node_modules/got/dist/source/core/utils/unhandle.d.ts new file mode 100644 index 0000000..f49b792 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/unhandle.d.ts @@ -0,0 +1,11 @@ +/// +import { EventEmitter } from 'events'; +declare type Origin = EventEmitter; +declare type Event = string | symbol; +declare type Fn = (...args: any[]) => void; +interface Unhandler { + once: (origin: Origin, event: Event, fn: Fn) => void; + unhandleAll: () => void; +} +declare const _default: () => Unhandler; +export default _default; diff --git a/node_modules/got/dist/source/core/utils/unhandle.js b/node_modules/got/dist/source/core/utils/unhandle.js new file mode 100644 index 0000000..e749697 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/unhandle.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// When attaching listeners, it's very easy to forget about them. +// Especially if you do error handling and set timeouts. +// So instead of checking if it's proper to throw an error on every timeout ever, +// use this simple tool which will remove all listeners you have attached. +exports.default = () => { + const handlers = []; + return { + once(origin, event, fn) { + origin.once(event, fn); + handlers.push({ origin, event, fn }); + }, + unhandleAll() { + for (const handler of handlers) { + const { origin, event, fn } = handler; + origin.removeListener(event, fn); + } + handlers.length = 0; + } + }; +}; diff --git a/node_modules/got/dist/source/core/utils/url-to-options.d.ts b/node_modules/got/dist/source/core/utils/url-to-options.d.ts new file mode 100644 index 0000000..c977a0f --- /dev/null +++ b/node_modules/got/dist/source/core/utils/url-to-options.d.ts @@ -0,0 +1,15 @@ +import { URL, UrlWithStringQuery } from 'url'; +export interface LegacyUrlOptions { + protocol: string; + hostname: string; + host: string; + hash: string | null; + search: string | null; + pathname: string; + href: string; + path: string; + port?: number; + auth?: string; +} +declare const _default: (url: URL | UrlWithStringQuery) => LegacyUrlOptions; +export default _default; diff --git a/node_modules/got/dist/source/core/utils/url-to-options.js b/node_modules/got/dist/source/core/utils/url-to-options.js new file mode 100644 index 0000000..19cc487 --- /dev/null +++ b/node_modules/got/dist/source/core/utils/url-to-options.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const is_1 = require("@sindresorhus/is"); +exports.default = (url) => { + // Cast to URL + url = url; + const options = { + protocol: url.protocol, + hostname: is_1.default.string(url.hostname) && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, + host: url.host, + hash: url.hash, + search: url.search, + pathname: url.pathname, + href: url.href, + path: `${url.pathname || ''}${url.search || ''}` + }; + if (is_1.default.string(url.port) && url.port.length > 0) { + options.port = Number(url.port); + } + if (url.username || url.password) { + options.auth = `${url.username || ''}:${url.password || ''}`; + } + return options; +}; diff --git a/node_modules/got/dist/source/core/utils/weakable-map.d.ts b/node_modules/got/dist/source/core/utils/weakable-map.d.ts new file mode 100644 index 0000000..9e3466c --- /dev/null +++ b/node_modules/got/dist/source/core/utils/weakable-map.d.ts @@ -0,0 +1,8 @@ +export default class WeakableMap { + weakMap: WeakMap, V>; + map: Map; + constructor(); + set(key: K, value: V): void; + get(key: K): V | undefined; + has(key: K): boolean; +} diff --git a/node_modules/got/dist/source/core/utils/weakable-map.js b/node_modules/got/dist/source/core/utils/weakable-map.js new file mode 100644 index 0000000..5c5da7f --- /dev/null +++ b/node_modules/got/dist/source/core/utils/weakable-map.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class WeakableMap { + constructor() { + this.weakMap = new WeakMap(); + this.map = new Map(); + } + set(key, value) { + if (typeof key === 'object') { + this.weakMap.set(key, value); + } + else { + this.map.set(key, value); + } + } + get(key) { + if (typeof key === 'object') { + return this.weakMap.get(key); + } + return this.map.get(key); + } + has(key) { + if (typeof key === 'object') { + return this.weakMap.has(key); + } + return this.map.has(key); + } +} +exports.default = WeakableMap; diff --git a/node_modules/got/dist/source/create.d.ts b/node_modules/got/dist/source/create.d.ts new file mode 100644 index 0000000..c8fd7ae --- /dev/null +++ b/node_modules/got/dist/source/create.d.ts @@ -0,0 +1,5 @@ +import { Got, HandlerFunction, InstanceDefaults } from './types'; +export declare const defaultHandler: HandlerFunction; +declare const create: (defaults: InstanceDefaults) => Got; +export default create; +export * from './types'; diff --git a/node_modules/got/dist/source/create.js b/node_modules/got/dist/source/create.js new file mode 100644 index 0000000..bf56db4 --- /dev/null +++ b/node_modules/got/dist/source/create.js @@ -0,0 +1,240 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.defaultHandler = void 0; +const is_1 = require("@sindresorhus/is"); +const as_promise_1 = require("./as-promise"); +const create_rejection_1 = require("./as-promise/create-rejection"); +const core_1 = require("./core"); +const deep_freeze_1 = require("./utils/deep-freeze"); +const errors = { + RequestError: as_promise_1.RequestError, + CacheError: as_promise_1.CacheError, + ReadError: as_promise_1.ReadError, + HTTPError: as_promise_1.HTTPError, + MaxRedirectsError: as_promise_1.MaxRedirectsError, + TimeoutError: as_promise_1.TimeoutError, + ParseError: as_promise_1.ParseError, + CancelError: as_promise_1.CancelError, + UnsupportedProtocolError: as_promise_1.UnsupportedProtocolError, + UploadError: as_promise_1.UploadError +}; +// The `delay` package weighs 10KB (!) +const delay = async (ms) => new Promise(resolve => { + setTimeout(resolve, ms); +}); +const { normalizeArguments } = core_1.default; +const mergeOptions = (...sources) => { + let mergedOptions; + for (const source of sources) { + mergedOptions = normalizeArguments(undefined, source, mergedOptions); + } + return mergedOptions; +}; +const getPromiseOrStream = (options) => options.isStream ? new core_1.default(undefined, options) : as_promise_1.default(options); +const isGotInstance = (value) => ('defaults' in value && 'options' in value.defaults); +const aliases = [ + 'get', + 'post', + 'put', + 'patch', + 'head', + 'delete' +]; +exports.defaultHandler = (options, next) => next(options); +const callInitHooks = (hooks, options) => { + if (hooks) { + for (const hook of hooks) { + hook(options); + } + } +}; +const create = (defaults) => { + // Proxy properties from next handlers + defaults._rawHandlers = defaults.handlers; + defaults.handlers = defaults.handlers.map(fn => ((options, next) => { + // This will be assigned by assigning result + let root; + const result = fn(options, newOptions => { + root = next(newOptions); + return root; + }); + if (result !== root && !options.isStream && root) { + const typedResult = result; + const { then: promiseThen, catch: promiseCatch, finally: promiseFianlly } = typedResult; + Object.setPrototypeOf(typedResult, Object.getPrototypeOf(root)); + Object.defineProperties(typedResult, Object.getOwnPropertyDescriptors(root)); + // These should point to the new promise + // eslint-disable-next-line promise/prefer-await-to-then + typedResult.then = promiseThen; + typedResult.catch = promiseCatch; + typedResult.finally = promiseFianlly; + } + return result; + })); + // Got interface + const got = ((url, options = {}, _defaults) => { + var _a, _b; + let iteration = 0; + const iterateHandlers = (newOptions) => { + return defaults.handlers[iteration++](newOptions, iteration === defaults.handlers.length ? getPromiseOrStream : iterateHandlers); + }; + // TODO: Remove this in Got 12. + if (is_1.default.plainObject(url)) { + const mergedOptions = { + ...url, + ...options + }; + core_1.setNonEnumerableProperties([url, options], mergedOptions); + options = mergedOptions; + url = undefined; + } + try { + // Call `init` hooks + let initHookError; + try { + callInitHooks(defaults.options.hooks.init, options); + callInitHooks((_a = options.hooks) === null || _a === void 0 ? void 0 : _a.init, options); + } + catch (error) { + initHookError = error; + } + // Normalize options & call handlers + const normalizedOptions = normalizeArguments(url, options, _defaults !== null && _defaults !== void 0 ? _defaults : defaults.options); + normalizedOptions[core_1.kIsNormalizedAlready] = true; + if (initHookError) { + throw new as_promise_1.RequestError(initHookError.message, initHookError, normalizedOptions); + } + return iterateHandlers(normalizedOptions); + } + catch (error) { + if (options.isStream) { + throw error; + } + else { + return create_rejection_1.default(error, defaults.options.hooks.beforeError, (_b = options.hooks) === null || _b === void 0 ? void 0 : _b.beforeError); + } + } + }); + got.extend = (...instancesOrOptions) => { + const optionsArray = [defaults.options]; + let handlers = [...defaults._rawHandlers]; + let isMutableDefaults; + for (const value of instancesOrOptions) { + if (isGotInstance(value)) { + optionsArray.push(value.defaults.options); + handlers.push(...value.defaults._rawHandlers); + isMutableDefaults = value.defaults.mutableDefaults; + } + else { + optionsArray.push(value); + if ('handlers' in value) { + handlers.push(...value.handlers); + } + isMutableDefaults = value.mutableDefaults; + } + } + handlers = handlers.filter(handler => handler !== exports.defaultHandler); + if (handlers.length === 0) { + handlers.push(exports.defaultHandler); + } + return create({ + options: mergeOptions(...optionsArray), + handlers, + mutableDefaults: Boolean(isMutableDefaults) + }); + }; + // Pagination + const paginateEach = (async function* (url, options) { + // TODO: Remove this `@ts-expect-error` when upgrading to TypeScript 4. + // Error: Argument of type 'Merge> | undefined' is not assignable to parameter of type 'Options | undefined'. + // @ts-expect-error + let normalizedOptions = normalizeArguments(url, options, defaults.options); + normalizedOptions.resolveBodyOnly = false; + const pagination = normalizedOptions.pagination; + if (!is_1.default.object(pagination)) { + throw new TypeError('`options.pagination` must be implemented'); + } + const all = []; + let { countLimit } = pagination; + let numberOfRequests = 0; + while (numberOfRequests < pagination.requestLimit) { + if (numberOfRequests !== 0) { + // eslint-disable-next-line no-await-in-loop + await delay(pagination.backoff); + } + // @ts-expect-error FIXME! + // TODO: Throw when result is not an instance of Response + // eslint-disable-next-line no-await-in-loop + const result = (await got(undefined, undefined, normalizedOptions)); + // eslint-disable-next-line no-await-in-loop + const parsed = await pagination.transform(result); + const current = []; + for (const item of parsed) { + if (pagination.filter(item, all, current)) { + if (!pagination.shouldContinue(item, all, current)) { + return; + } + yield item; + if (pagination.stackAllItems) { + all.push(item); + } + current.push(item); + if (--countLimit <= 0) { + return; + } + } + } + const optionsToMerge = pagination.paginate(result, all, current); + if (optionsToMerge === false) { + return; + } + if (optionsToMerge === result.request.options) { + normalizedOptions = result.request.options; + } + else if (optionsToMerge !== undefined) { + normalizedOptions = normalizeArguments(undefined, optionsToMerge, normalizedOptions); + } + numberOfRequests++; + } + }); + got.paginate = paginateEach; + got.paginate.all = (async (url, options) => { + const results = []; + for await (const item of paginateEach(url, options)) { + results.push(item); + } + return results; + }); + // For those who like very descriptive names + got.paginate.each = paginateEach; + // Stream API + got.stream = ((url, options) => got(url, { ...options, isStream: true })); + // Shortcuts + for (const method of aliases) { + got[method] = ((url, options) => got(url, { ...options, method })); + got.stream[method] = ((url, options) => { + return got(url, { ...options, method, isStream: true }); + }); + } + Object.assign(got, errors); + Object.defineProperty(got, 'defaults', { + value: defaults.mutableDefaults ? defaults : deep_freeze_1.default(defaults), + writable: defaults.mutableDefaults, + configurable: defaults.mutableDefaults, + enumerable: true + }); + got.mergeOptions = mergeOptions; + return got; +}; +exports.default = create; +__exportStar(require("./types"), exports); diff --git a/node_modules/got/dist/source/index.d.ts b/node_modules/got/dist/source/index.d.ts new file mode 100644 index 0000000..e653895 --- /dev/null +++ b/node_modules/got/dist/source/index.d.ts @@ -0,0 +1,4 @@ +declare const got: import("./types").Got; +export default got; +export * from './create'; +export * from './as-promise'; diff --git a/node_modules/got/dist/source/index.js b/node_modules/got/dist/source/index.js new file mode 100644 index 0000000..106b1f2 --- /dev/null +++ b/node_modules/got/dist/source/index.js @@ -0,0 +1,132 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const url_1 = require("url"); +const create_1 = require("./create"); +const defaults = { + options: { + method: 'GET', + retry: { + limit: 2, + methods: [ + 'GET', + 'PUT', + 'HEAD', + 'DELETE', + 'OPTIONS', + 'TRACE' + ], + statusCodes: [ + 408, + 413, + 429, + 500, + 502, + 503, + 504, + 521, + 522, + 524 + ], + errorCodes: [ + 'ETIMEDOUT', + 'ECONNRESET', + 'EADDRINUSE', + 'ECONNREFUSED', + 'EPIPE', + 'ENOTFOUND', + 'ENETUNREACH', + 'EAI_AGAIN' + ], + maxRetryAfter: undefined, + calculateDelay: ({ computedValue }) => computedValue + }, + timeout: {}, + headers: { + 'user-agent': 'got (https://github.com/sindresorhus/got)' + }, + hooks: { + init: [], + beforeRequest: [], + beforeRedirect: [], + beforeRetry: [], + beforeError: [], + afterResponse: [] + }, + cache: undefined, + dnsCache: undefined, + decompress: true, + throwHttpErrors: true, + followRedirect: true, + isStream: false, + responseType: 'text', + resolveBodyOnly: false, + maxRedirects: 10, + prefixUrl: '', + methodRewriting: true, + ignoreInvalidCookies: false, + context: {}, + // TODO: Set this to `true` when Got 12 gets released + http2: false, + allowGetBody: false, + https: undefined, + pagination: { + transform: (response) => { + if (response.request.options.responseType === 'json') { + return response.body; + } + return JSON.parse(response.body); + }, + paginate: response => { + if (!Reflect.has(response.headers, 'link')) { + return false; + } + const items = response.headers.link.split(','); + let next; + for (const item of items) { + const parsed = item.split(';'); + if (parsed[1].includes('next')) { + next = parsed[0].trimStart().trim(); + next = next.slice(1, -1); + break; + } + } + if (next) { + const options = { + url: new url_1.URL(next) + }; + return options; + } + return false; + }, + filter: () => true, + shouldContinue: () => true, + countLimit: Infinity, + backoff: 0, + requestLimit: 10000, + stackAllItems: true + }, + parseJson: (text) => JSON.parse(text), + stringifyJson: (object) => JSON.stringify(object), + cacheOptions: {} + }, + handlers: [create_1.defaultHandler], + mutableDefaults: false +}; +const got = create_1.default(defaults); +exports.default = got; +// For CommonJS default export support +module.exports = got; +module.exports.default = got; +module.exports.__esModule = true; // Workaround for TS issue: https://github.com/sindresorhus/got/pull/1267 +__exportStar(require("./create"), exports); +__exportStar(require("./as-promise"), exports); diff --git a/node_modules/got/dist/source/types.d.ts b/node_modules/got/dist/source/types.d.ts new file mode 100644 index 0000000..b148c92 --- /dev/null +++ b/node_modules/got/dist/source/types.d.ts @@ -0,0 +1,342 @@ +/// +import { URL } from 'url'; +import { CancelError } from 'p-cancelable'; +import { CancelableRequest, Response, Options, NormalizedOptions, Defaults as DefaultOptions, PaginationOptions, ParseError, RequestError, CacheError, ReadError, HTTPError, MaxRedirectsError, TimeoutError, UnsupportedProtocolError, UploadError } from './as-promise'; +import Request from './core'; +declare type Except = Pick>; +declare type Merge = Except> & SecondType; +/** +Defaults for each Got instance. +*/ +export interface InstanceDefaults { + /** + An object containing the default options of Got. + */ + options: DefaultOptions; + /** + An array of functions. You execute them directly by calling `got()`. + They are some sort of "global hooks" - these functions are called first. + The last handler (*it's hidden*) is either `asPromise` or `asStream`, depending on the `options.isStream` property. + + @default [] + */ + handlers: HandlerFunction[]; + /** + A read-only boolean describing whether the defaults are mutable or not. + If set to `true`, you can update headers over time, for example, update an access token when it expires. + + @default false + */ + mutableDefaults: boolean; + _rawHandlers?: HandlerFunction[]; +} +/** +A Request object returned by calling Got, or any of the Got HTTP alias request functions. +*/ +export declare type GotReturn = Request | CancelableRequest; +/** +A function to handle options and returns a Request object. +It acts sort of like a "global hook", and will be called before any actual request is made. +*/ +export declare type HandlerFunction = (options: NormalizedOptions, next: (options: NormalizedOptions) => T) => T | Promise; +/** +The options available for `got.extend()`. +*/ +export interface ExtendOptions extends Options { + /** + An array of functions. You execute them directly by calling `got()`. + They are some sort of "global hooks" - these functions are called first. + The last handler (*it's hidden*) is either `asPromise` or `asStream`, depending on the `options.isStream` property. + + @default [] + */ + handlers?: HandlerFunction[]; + /** + A read-only boolean describing whether the defaults are mutable or not. + If set to `true`, you can update headers over time, for example, update an access token when it expires. + + @default false + */ + mutableDefaults?: boolean; +} +export declare type OptionsOfTextResponseBody = Merge; +export declare type OptionsOfJSONResponseBody = Merge; +export declare type OptionsOfBufferResponseBody = Merge; +export declare type OptionsOfUnknownResponseBody = Merge; +export declare type StrictOptions = Except; +export declare type StreamOptions = Merge; +declare type ResponseBodyOnly = { + resolveBodyOnly: true; +}; +export declare type OptionsWithPagination = Merge>; +/** +An instance of `got.paginate`. +*/ +export interface GotPaginate { + /** + Returns an async iterator. + + See pagination.options for more pagination options. + + @example + ``` + (async () => { + const countLimit = 10; + + const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + + for await (const commitData of pagination) { + console.log(commitData.commit.message); + } + })(); + ``` + */ + each: ((url: string | URL, options?: OptionsWithPagination) => AsyncIterableIterator) & ((options?: OptionsWithPagination) => AsyncIterableIterator); + /** + Returns a Promise for an array of all results. + + See pagination.options for more pagination options. + + @example + ``` + (async () => { + const countLimit = 10; + + const results = await got.paginate.all('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + console.log(results); + })(); + ``` + */ + all: ((url: string | URL, options?: OptionsWithPagination) => Promise) & ((options?: OptionsWithPagination) => Promise); + /** + Same as `GotPaginate.each`. + */ + (url: string | URL, options?: OptionsWithPagination): AsyncIterableIterator; + /** + Same as `GotPaginate.each`. + */ + (options?: OptionsWithPagination): AsyncIterableIterator; +} +export interface GotRequestFunction { + (url: string | URL, options?: OptionsOfTextResponseBody): CancelableRequest>; + (url: string | URL, options?: OptionsOfJSONResponseBody): CancelableRequest>; + (url: string | URL, options?: OptionsOfBufferResponseBody): CancelableRequest>; + (url: string | URL, options?: OptionsOfUnknownResponseBody): CancelableRequest; + (options: OptionsOfTextResponseBody): CancelableRequest>; + (options: OptionsOfJSONResponseBody): CancelableRequest>; + (options: OptionsOfBufferResponseBody): CancelableRequest>; + (options: OptionsOfUnknownResponseBody): CancelableRequest; + (url: string | URL, options?: (Merge)): CancelableRequest; + (url: string | URL, options?: (Merge)): CancelableRequest; + (url: string | URL, options?: (Merge)): CancelableRequest; + (options: (Merge)): CancelableRequest; + (options: (Merge)): CancelableRequest; + (options: (Merge)): CancelableRequest; + (url: string | URL, options?: Merge): Request; + (options: Merge): Request; + (url: string | URL, options?: Options): CancelableRequest | Request; + (options: Options): CancelableRequest | Request; +} +/** +All available HTTP request methods provided by Got. +*/ +export declare type HTTPAlias = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'; +interface GotStreamFunction { + (url: string | URL, options?: Merge): Request; + (options?: Merge): Request; +} +/** +An instance of `got.stream()`. +*/ +export declare type GotStream = GotStreamFunction & Record; +/** +An instance of `got`. +*/ +export interface Got extends Record, GotRequestFunction { + /** + Sets `options.isStream` to `true`. + + Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex) with additional events: + - request + - response + - redirect + - uploadProgress + - downloadProgress + - error + */ + stream: GotStream; + /** + Returns an async iterator. + + See pagination.options for more pagination options. + + @example + ``` + (async () => { + const countLimit = 10; + + const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + + for await (const commitData of pagination) { + console.log(commitData.commit.message); + } + })(); + ``` + */ + paginate: GotPaginate; + /** + The Got defaults used in that instance. + */ + defaults: InstanceDefaults; + /** + An error to be thrown when a cache method fails. + For example, if the database goes down or there's a filesystem error. + */ + CacheError: typeof CacheError; + /** + An error to be thrown when a request fails. + Contains a `code` property with error class code, like `ECONNREFUSED`. + */ + RequestError: typeof RequestError; + /** + An error to be thrown when reading from response stream fails. + */ + ReadError: typeof ReadError; + /** + An error to be thrown when server response code is 2xx, and parsing body fails. + Includes a `response` property. + */ + ParseError: typeof ParseError; + /** + An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. + Includes a `response` property. + */ + HTTPError: typeof HTTPError; + /** + An error to be thrown when the server redirects you more than ten times. + Includes a `response` property. + */ + MaxRedirectsError: typeof MaxRedirectsError; + /** + An error to be thrown when given an unsupported protocol. + */ + UnsupportedProtocolError: typeof UnsupportedProtocolError; + /** + An error to be thrown when the request is aborted due to a timeout. + Includes an `event` and `timings` property. + */ + TimeoutError: typeof TimeoutError; + /** + An error to be thrown when the request body is a stream and an error occurs while reading from that stream. + */ + UploadError: typeof UploadError; + /** + An error to be thrown when the request is aborted with `.cancel()`. + */ + CancelError: typeof CancelError; + /** + Configure a new `got` instance with default `options`. + The `options` are merged with the parent instance's `defaults.options` using `got.mergeOptions`. + You can access the resolved options with the `.defaults` property on the instance. + + Additionally, `got.extend()` accepts two properties from the `defaults` object: `mutableDefaults` and `handlers`. + + It is also possible to merges many instances into a single one: + - options are merged using `got.mergeOptions()` (including hooks), + - handlers are stored in an array (you can access them through `instance.defaults.handlers`). + + @example + ```js + const client = got.extend({ + prefixUrl: 'https://example.com', + headers: { + 'x-unicorn': 'rainbow' + } + }); + + client.get('demo'); + + // HTTP Request => + // GET /demo HTTP/1.1 + // Host: example.com + // x-unicorn: rainbow + ``` + */ + extend: (...instancesOrOptions: Array) => Got; + /** + Merges multiple `got` instances into the parent. + */ + mergeInstances: (parent: Got, ...instances: Got[]) => Got; + /** + Extends parent options. + Avoid using [object spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) as it doesn't work recursively. + + Options are deeply merged to a new object. The value of each key is determined as follows: + + - If the new property is not defined, the old value is used. + - If the new property is explicitly set to `undefined`: + - If the parent property is a plain `object`, the parent value is deeply cloned. + - Otherwise, `undefined` is used. + - If the parent value is an instance of `URLSearchParams`: + - If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. + The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append). + The keys defined in the new value override the keys defined in the parent value. + - Otherwise, the only available value is `undefined`. + - If the new property is a plain `object`: + - If the parent property is a plain `object` too, both values are merged recursively into a new `object`. + - Otherwise, only the new value is deeply cloned. + - If the new property is an `Array`, it overwrites the old one with a deep clone of the new property. + - Properties that are not enumerable, such as `context`, `body`, `json`, and `form`, will not be merged. + - Otherwise, the new value is assigned to the key. + + **Note:** Only Got options are merged! Custom user options should be defined via [`options.context`](#context). + + @example + ``` + const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}}; + const b = {headers: {cow: 'moo', wolf: ['auuu']}}; + + {...a, ...b} // => {headers: {cow: 'moo', wolf: ['auuu']}} + got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}} + ``` + */ + mergeOptions: (...sources: Options[]) => NormalizedOptions; +} +export {}; diff --git a/node_modules/got/dist/source/types.js b/node_modules/got/dist/source/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/node_modules/got/dist/source/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/got/dist/source/utils/deep-freeze.d.ts b/node_modules/got/dist/source/utils/deep-freeze.d.ts new file mode 100644 index 0000000..7c33e5c --- /dev/null +++ b/node_modules/got/dist/source/utils/deep-freeze.d.ts @@ -0,0 +1 @@ +export default function deepFreeze>(object: T): Readonly; diff --git a/node_modules/got/dist/source/utils/deep-freeze.js b/node_modules/got/dist/source/utils/deep-freeze.js new file mode 100644 index 0000000..a696d4e --- /dev/null +++ b/node_modules/got/dist/source/utils/deep-freeze.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const is_1 = require("@sindresorhus/is"); +function deepFreeze(object) { + for (const value of Object.values(object)) { + if (is_1.default.plainObject(value) || is_1.default.array(value)) { + deepFreeze(value); + } + } + return Object.freeze(object); +} +exports.default = deepFreeze; diff --git a/node_modules/got/dist/source/utils/deprecation-warning.d.ts b/node_modules/got/dist/source/utils/deprecation-warning.d.ts new file mode 100644 index 0000000..1a08f96 --- /dev/null +++ b/node_modules/got/dist/source/utils/deprecation-warning.d.ts @@ -0,0 +1,2 @@ +declare const _default: (message: string) => void; +export default _default; diff --git a/node_modules/got/dist/source/utils/deprecation-warning.js b/node_modules/got/dist/source/utils/deprecation-warning.js new file mode 100644 index 0000000..3cfb7b2 --- /dev/null +++ b/node_modules/got/dist/source/utils/deprecation-warning.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const alreadyWarned = new Set(); +exports.default = (message) => { + if (alreadyWarned.has(message)) { + return; + } + alreadyWarned.add(message); + // @ts-expect-error Missing types. + process.emitWarning(`Got: ${message}`, { + type: 'DeprecationWarning' + }); +}; diff --git a/node_modules/got/license b/node_modules/got/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/got/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/got/package.json b/node_modules/got/package.json new file mode 100644 index 0000000..0ab89c3 --- /dev/null +++ b/node_modules/got/package.json @@ -0,0 +1,130 @@ +{ + "name": "got", + "version": "11.8.2", + "description": "Human-friendly and powerful HTTP request library for Node.js", + "license": "MIT", + "repository": "sindresorhus/got", + "funding": "https://github.com/sindresorhus/got?sponsor=1", + "main": "dist/source", + "engines": { + "node": ">=10.19.0" + }, + "scripts": { + "test": "xo && npm run build && nyc --reporter=html --reporter=text ava", + "release": "np", + "build": "del-cli dist && tsc", + "prepare": "npm run build" + }, + "files": [ + "dist/source" + ], + "keywords": [ + "http", + "https", + "http2", + "get", + "got", + "url", + "uri", + "request", + "simple", + "curl", + "wget", + "fetch", + "net", + "network", + "gzip", + "brotli", + "requests", + "human-friendly", + "axios", + "superagent", + "node-fetch", + "ky" + ], + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "devDependencies": { + "@ava/typescript": "^1.1.1", + "@sindresorhus/tsconfig": "^0.7.0", + "@sinonjs/fake-timers": "^6.0.1", + "@types/benchmark": "^1.0.33", + "@types/express": "^4.17.7", + "@types/node": "^14.14.0", + "@types/node-fetch": "^2.5.7", + "@types/pem": "^1.9.5", + "@types/pify": "^3.0.2", + "@types/request": "^2.48.5", + "@types/sinon": "^9.0.5", + "@types/tough-cookie": "^4.0.0", + "ava": "^3.11.1", + "axios": "^0.20.0", + "benchmark": "^2.1.4", + "coveralls": "^3.1.0", + "create-test-server": "^3.0.1", + "del-cli": "^3.0.1", + "delay": "^4.4.0", + "express": "^4.17.1", + "form-data": "^3.0.0", + "get-stream": "^6.0.0", + "nock": "^13.0.4", + "node-fetch": "^2.6.0", + "np": "^6.4.0", + "nyc": "^15.1.0", + "p-event": "^4.2.0", + "pem": "^1.14.4", + "pify": "^5.0.0", + "sinon": "^9.0.3", + "slow-stream": "0.0.4", + "tempy": "^1.0.0", + "to-readable-stream": "^2.1.0", + "tough-cookie": "^4.0.0", + "typescript": "4.0.3", + "xo": "^0.34.1" + }, + "types": "dist/source", + "sideEffects": false, + "ava": { + "files": [ + "test/*" + ], + "timeout": "1m", + "typescript": { + "rewritePaths": { + "test/": "dist/test/" + } + } + }, + "nyc": { + "extension": [ + ".ts" + ], + "exclude": [ + "**/test/**" + ] + }, + "xo": { + "ignores": [ + "documentation/examples/*" + ], + "rules": { + "@typescript-eslint/no-empty-function": "off", + "node/prefer-global/url": "off", + "node/prefer-global/url-search-params": "off", + "import/no-anonymous-default-export": "off", + "@typescript-eslint/no-implicit-any-catch": "off" + } + }, + "runkitExampleFilename": "./documentation/examples/runkit-example.js" +} diff --git a/node_modules/got/readme.md b/node_modules/got/readme.md new file mode 100644 index 0000000..82a89c1 --- /dev/null +++ b/node_modules/got/readme.md @@ -0,0 +1,2476 @@ +
+
+
+ Got +
+
+
+

Huge thanks to for sponsoring Sindre Sorhus! +

+

(they love Got too!)

+
+
+
+ +> Human-friendly and powerful HTTP request library for Node.js + +[![Build Status: Linux](https://travis-ci.com/sindresorhus/got.svg?branch=master)](https://travis-ci.com/github/sindresorhus/got) +[![Coverage Status](https://coveralls.io/repos/github/sindresorhus/got/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/got?branch=master) +[![Downloads](https://img.shields.io/npm/dm/got.svg)](https://npmjs.com/got) +[![Install size](https://packagephobia.now.sh/badge?p=got)](https://packagephobia.now.sh/result?p=got) + +[Moving from Request?](documentation/migration-guides.md) [*(Note that Request is unmaintained)*](https://github.com/request/request/issues/3142) + +[See how Got compares to other HTTP libraries](#comparison) + +For browser usage, we recommend [Ky](https://github.com/sindresorhus/ky) by the same people. + +## Highlights + +- [Promise API](#api) +- [Stream API](#streams) +- [Pagination API](#pagination) +- [HTTP2 support](#http2) +- [Request cancelation](#aborting-the-request) +- [RFC compliant caching](#cache-adapters) +- [Follows redirects](#followredirect) +- [Retries on failure](#retry) +- [Progress events](#onuploadprogress-progress) +- [Handles gzip/deflate/brotli](#decompress) +- [Timeout handling](#timeout) +- [Errors with metadata](#errors) +- [JSON mode](#json-mode) +- [WHATWG URL support](#url) +- [HTTPS API](#advanced-https-api) +- [Hooks](#hooks) +- [Instances with custom defaults](#instances) +- [Types](#types) +- [Composable](documentation/advanced-creation.md#merging-instances) +- [Plugins](documentation/lets-make-a-plugin.md) +- [Used by 4K+ packages and 1.8M+ repos](https://github.com/sindresorhus/got/network/dependents) +- [Actively maintained](https://github.com/sindresorhus/got/graphs/contributors) +- [Trusted by many companies](#widely-used) + +## Install + +``` +$ npm install got +``` + +## Usage + +###### Promise + +```js +const got = require('got'); + +(async () => { + try { + const response = await got('https://sindresorhus.com'); + console.log(response.body); + //=> ' ...' + } catch (error) { + console.log(error.response.body); + //=> 'Internal server error ...' + } +})(); +``` + +###### JSON + +```js +const got = require('got'); + +(async () => { + const {body} = await got.post('https://httpbin.org/anything', { + json: { + hello: 'world' + }, + responseType: 'json' + }); + + console.log(body.data); + //=> {hello: 'world'} +})(); +``` + +See [JSON mode](#json-mode) for more details. + +###### Streams + +```js +const stream = require('stream'); +const {promisify} = require('util'); +const fs = require('fs'); +const got = require('got'); + +const pipeline = promisify(stream.pipeline); + +(async () => { + await pipeline( + got.stream('https://sindresorhus.com'), + fs.createWriteStream('index.html') + ); + + // For POST, PUT, PATCH, and DELETE methods, `got.stream` returns a `stream.Writable`. + await pipeline( + fs.createReadStream('index.html'), + got.stream.post('https://sindresorhus.com') + ); +})(); +``` + +**Tip:** `from.pipe(to)` doesn't forward errors. Instead, use [`stream.pipeline(from, ..., to, callback)`](https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback). + +**Note:** While `got.post('https://example.com')` resolves, `got.stream.post('https://example.com')` will hang indefinitely until a body is provided. If there's no body on purpose, remember to `.end()` the stream or set the [`body`](#body) option to an empty string. + +### API + +It's a `GET` request by default, but can be changed by using different methods or via [`options.method`](#method). + +**By default, Got will retry on failure. To disable this option, set [`options.retry`](#retry) to `0`.** + +#### got(url?, options?) + +Returns a Promise giving a [Response object](#response) or a [Got Stream](#streams-1) if `options.isStream` is set to true. + +##### url + +Type: `string | object` + +The URL to request, as a string, a [`https.request` options object](https://nodejs.org/api/https.html#https_https_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url). + +Properties from `options` will override properties in the parsed `url`. + +If no protocol is specified, it will throw a `TypeError`. + +**Note:** The query string is **not** parsed as search params. Example: + +```js +got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b +got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b + +// The query string is overridden by `searchParams` +got('https://example.com/?query=a b', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b +``` + +##### options + +Type: `object` + +Any of the [`https.request`](https://nodejs.org/api/https.html#https_https_request_options_callback) options. + +**Note:** Legacy URL support is disabled. `options.path` is supported only for backwards compatibility. Use `options.pathname` and `options.searchParams` instead. `options.auth` has been replaced with `options.username` & `options.password`. + +###### method + +Type: `string`\ +Default: `GET` + +The HTTP method used to make the request. + +###### prefixUrl + +Type: `string | URL` + +When specified, `prefixUrl` will be prepended to `url`. The prefix can be any valid URL, either relative or absolute.\ +A trailing slash `/` is optional - one will be added automatically. + +**Note:** `prefixUrl` will be ignored if the `url` argument is a URL instance. + +**Note:** Leading slashes in `input` are disallowed when using this option to enforce consistency and avoid confusion. For example, when the prefix URL is `https://example.com/foo` and the input is `/bar`, there's ambiguity whether the resulting URL would become `https://example.com/foo/bar` or `https://example.com/bar`. The latter is used by browsers. + +**Tip:** Useful when used with [`got.extend()`](#custom-endpoints) to create niche-specific Got instances. + +**Tip:** You can change `prefixUrl` using hooks as long as the URL still includes the `prefixUrl`. If the URL doesn't include it anymore, it will throw. + +```js +const got = require('got'); + +(async () => { + await got('unicorn', {prefixUrl: 'https://cats.com'}); + //=> 'https://cats.com/unicorn' + + const instance = got.extend({ + prefixUrl: 'https://google.com' + }); + + await instance('unicorn', { + hooks: { + beforeRequest: [ + options => { + options.prefixUrl = 'https://cats.com'; + } + ] + } + }); + //=> 'https://cats.com/unicorn' +})(); +``` + +###### headers + +Type: `object`\ +Default: `{}` + +Request headers. + +Existing headers will be overwritten. Headers set to `undefined` will be omitted. + +###### isStream + +Type: `boolean`\ +Default: `false` + +Returns a `Stream` instead of a `Promise`. This is equivalent to calling `got.stream(url, options?)`. + +###### body + +Type: `string | Buffer | stream.Readable` or [`form-data` instance](https://github.com/form-data/form-data) + +**Note #1:** The `body` option cannot be used with the `json` or `form` option. + +**Note #2:** If you provide this option, `got.stream()` will be read-only. + +**Note #3:** If you provide a payload with the `GET` or `HEAD` method, it will throw a `TypeError` unless the method is `GET` and the `allowGetBody` option is set to `true`. + +**Note #4:** This option is not enumerable and will not be merged with the instance defaults. + +The `content-length` header will be automatically set if `body` is a `string` / `Buffer` / `fs.createReadStream` instance / [`form-data` instance](https://github.com/form-data/form-data), and `content-length` and `transfer-encoding` are not manually set in `options.headers`. + +###### json + +Type: `object | Array | number | string | boolean | null` *(JSON-serializable values)* + +**Note #1:** If you provide this option, `got.stream()` will be read-only.\ +**Note #2:** This option is not enumerable and will not be merged with the instance defaults. + +JSON body. If the `Content-Type` header is not set, it will be set to `application/json`. + +###### context + +Type: `object` + +User data. In contrast to other options, `context` is not enumerable. + +**Note:** The object is never merged, it's just passed through. Got will not modify the object in any way. + +It's very useful for storing auth tokens: + +```js +const got = require('got'); + +const instance = got.extend({ + hooks: { + beforeRequest: [ + options => { + if (!options.context || !options.context.token) { + throw new Error('Token required'); + } + + options.headers.token = options.context.token; + } + ] + } +}); + +(async () => { + const context = { + token: 'secret' + }; + + const response = await instance('https://httpbin.org/headers', {context}); + + // Let's see the headers + console.log(response.body); +})(); +``` + +###### responseType + +Type: `string`\ +Default: `'text'` + +**Note:** When using streams, this option is ignored. + +The parsing method. Can be `'text'`, `'json'` or `'buffer'`. + +The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body.\ +It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise. + +Example: + +```js +(async () => { + const responsePromise = got(url); + const bufferPromise = responsePromise.buffer(); + const jsonPromise = responsePromise.json(); + + const [response, buffer, json] = await Promise.all([responsePromise, bufferPromise, jsonPromise]); + // `response` is an instance of Got Response + // `buffer` is an instance of Buffer + // `json` is an object +})(); +``` + +```js +// This +const body = await got(url).json(); + +// is semantically the same as this +const body = await got(url, {responseType: 'json', resolveBodyOnly: true}); +``` + +**Note:** `buffer` will return the raw body buffer. Modifying it will also alter the result of `promise.text()` and `promise.json()`. Before overwritting the buffer, please copy it first via `Buffer.from(buffer)`. See https://github.com/nodejs/node/issues/27080 + +###### parseJson + +Type: `(text: string) => unknown`\ +Default: `(text: string) => JSON.parse(text)` + +A function used to parse JSON responses. + +
+Example + +Using [`bourne`](https://github.com/hapijs/bourne) to prevent prototype pollution: + +```js +const got = require('got'); +const Bourne = require('@hapi/bourne'); + +(async () => { + const parsed = await got('https://example.com', { + parseJson: text => Bourne.parse(text) + }).json(); + + console.log(parsed); +})(); +``` +
+ +###### stringifyJson + +Type: `(object: unknown) => string`\ +Default: `(object: unknown) => JSON.stringify(object)` + +A function used to stringify the body of JSON requests. + +
+Examples + +Ignore properties starting with `_`: + +```js +const got = require('got'); + +(async () => { + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (key.startsWith('_')) { + return; + } + + return value; + }), + json: { + some: 'payload', + _ignoreMe: 1234 + } + }); +})(); +``` + +All numbers as strings: + +```js +const got = require('got'); + +(async () => { + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (typeof value === 'number') { + return value.toString(); + } + + return value; + }), + json: { + some: 'payload', + number: 1 + } + }); +})(); +``` +
+ +###### resolveBodyOnly + +Type: `boolean`\ +Default: `false` + +When set to `true` the promise will return the [Response body](#body-1) instead of the [Response](#response) object. + +###### cookieJar + +Type: `object` | [`tough.CookieJar` instance](https://github.com/salesforce/tough-cookie#cookiejar) + +**Note:** If you provide this option, `options.headers.cookie` will be overridden. + +Cookie support. You don't have to care about parsing or how to store them. [Example](#cookies). + +###### cookieJar.setCookie + +Type: `Function` + +The function takes two arguments: `rawCookie` (`string`) and `url` (`string`). + +###### cookieJar.getCookieString + +Type: `Function` + +The function takes one argument: `url` (`string`). + +###### ignoreInvalidCookies + +Type: `boolean`\ +Default: `false` + +Ignore invalid cookies instead of throwing an error. Only useful when the `cookieJar` option has been set. Not recommended. + +###### encoding + +Type: `string`\ +Default: `'utf8'` + +[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. + +To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set [`responseType`](#responseType) to `buffer` instead. Don't set this option to `null`. + +**Note:** This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`. + +###### form + +Type: `object` + +**Note #1:** If you provide this option, `got.stream()` will be read-only.\ +**Note #2:** This option is not enumerable and will not be merged with the instance defaults. + +The form body is converted to a query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj). + +If the `Content-Type` header is not present, it will be set to `application/x-www-form-urlencoded`. + +###### searchParams + +Type: `string | object | URLSearchParams` + +Query string that will be added to the request URL. This will override the query string in `url`. + +If you need to pass in an array, you can do it using a `URLSearchParams` instance: + +```js +const got = require('got'); + +const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]); + +got('https://example.com', {searchParams}); + +console.log(searchParams.toString()); +//=> 'key=a&key=b' +``` + +There are some exceptions in regards to `URLSearchParams` behavior: + +**Note #1:** `null` values are not stringified, an empty string is used instead. + +**Note #2:** `undefined` values are not stringified, the entry is skipped instead. + +###### timeout + +Type: `number | object` + +Milliseconds to wait for the server to end the response before aborting the request with [`got.TimeoutError`](#gottimeouterror) error (a.k.a. `request` property). By default, there's no timeout. + +This also accepts an `object` with the following fields to constrain the duration of each phase of the request lifecycle: + +- `lookup` starts when a socket is assigned and ends when the hostname has been resolved. Does not apply when using a Unix domain socket. +- `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected. +- `secureConnect` starts when `connect` completes and ends when the handshaking process completes (HTTPS only). +- `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback). +- `response` starts when the request has been written to the socket and ends when the response headers are received. +- `send` starts when the socket is connected and ends with the request has been written to the socket. +- `request` starts when the request is initiated and ends when the response's end event fires. + +###### retry + +Type: `number | object`\ +Default: +- limit: `2` +- calculateDelay: `({attemptCount, retryOptions, error, computedValue}) => computedValue | Promise` +- methods: `GET` `PUT` `HEAD` `DELETE` `OPTIONS` `TRACE` +- statusCodes: [`408`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413) [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) [`500`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) [`502`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) [`504`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504) [`521`](https://support.cloudflare.com/hc/en-us/articles/115003011431#521error) [`522`](https://support.cloudflare.com/hc/en-us/articles/115003011431#522error) [`524`](https://support.cloudflare.com/hc/en-us/articles/115003011431#524error) +- maxRetryAfter: `undefined` +- errorCodes: `ETIMEDOUT` `ECONNRESET` `EADDRINUSE` `ECONNREFUSED` `EPIPE` `ENOTFOUND` `ENETUNREACH` `EAI_AGAIN` + +An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes. + +If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`.\ +If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. + +Delays between retries counts with function `1000 * Math.pow(2, retry - 1) + Math.random() * 100`, where `retry` is attempt number (starts from 1). + +The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry). + +**Note:** The `calculateDelay` function is responsible for the entire cache mechanism, including the `limit` property. To support it, you need to check whether `computedValue` is different than `0`. + +By default, it retries *only* on the specified methods, status codes, and on these network errors: +- `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached. +- `ECONNRESET`: Connection was forcibly closed by a peer. +- `EADDRINUSE`: Could not bind to any free port. +- `ECONNREFUSED`: Connection was refused by the server. +- `EPIPE`: The remote side of the stream being written has been closed. +- `ENOTFOUND`: Couldn't resolve the hostname to an IP address. +- `ENETUNREACH`: No internet connection. +- `EAI_AGAIN`: DNS lookup timed out. + + + +You can retry Got streams too. The implementation looks like this: + +```js +const got = require('got'); +const fs = require('fs'); + +let writeStream; + +const fn = (retryCount = 0) => { + const stream = got.stream('https://example.com'); + stream.retryCount = retryCount; + + if (writeStream) { + writeStream.destroy(); + } + + writeStream = fs.createWriteStream('example.com'); + + stream.pipe(writeStream); + + // If you don't attach the listener, it will NOT make a retry. + // It automatically checks the listener count so it knows whether to retry or not :) + stream.once('retry', fn); +}; + +fn(); +``` + +###### followRedirect + +Type: `boolean`\ +Default: `true` + +Defines if redirect responses should be followed automatically. + +Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). + +###### methodRewriting + +Type: `boolean`\ +Default: `true` + +By default, redirects will use [method rewriting](https://tools.ietf.org/html/rfc7231#section-6.4). For example, when sending a POST request and receiving a `302`, it will resend the body to the new location using the same HTTP method (`POST` in this case). + +###### allowGetBody + +Type: `boolean`\ +Default: `false` + +**Note:** The [RFC 7321](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore **it's considered an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern)**. + +Set this to `true` to allow sending body for the `GET` method. However, the [HTTP/2 specification](https://tools.ietf.org/html/rfc7540#section-8.1.3) says that `An HTTP GET request includes request header fields and no payload body`, therefore when using the HTTP/2 protocol this option will have no effect. This option is only meant to interact with non-compliant servers when you have no other choice. + +###### maxRedirects + +Type: `number`\ +Default: `10` + +If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. + +###### decompress + +Type: `boolean`\ +Default: `true` + +Decompress the response automatically. This will set the `accept-encoding` header to `gzip, deflate, br` on Node.js 11.7.0+ or `gzip, deflate` for older Node.js versions, unless you set it yourself. + +Brotli (`br`) support requires Node.js 11.7.0 or later. + +If this is disabled, a compressed response is returned as a `Buffer`. This may be useful if you want to handle decompression yourself or stream the raw compressed data. + +###### cache + +Type: `object | false`\ +Default: `false` + +[Cache adapter instance](#cache-adapters) for storing cached response data. + +###### cacheOptions + +Type: `object | undefined`\ +Default: `{}` + +[Cache options](https://github.com/kornelski/http-cache-semantics#constructor-options) used for the specified request. + +###### dnsCache + +Type: `CacheableLookup | false`\ +Default: `false` + +An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups. Useful when making lots of requests to different *public* hostnames. + +**Note:** This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc.\ +`CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay. + +###### dnsLookupIpVersion + +Type: `'auto' | 'ipv4' | 'ipv6'`\ +Default: `'auto'` + +Indicates which DNS record family to use.\ +Values: + - `auto`: IPv4 (if present) or IPv6 + - `ipv4`: Only IPv4 + - `ipv6`: Only IPv6 + +Note: If you are using the undocumented option `family`, `dnsLookupIpVersion` will override it. + +```js +// `api6.ipify.org` will be resolved as IPv4 and the request will be over IPv4 (the website will respond with your public IPv4) +await got('https://api6.ipify.org', { + dnsLookupIpVersion: 'ipv4' +}); + +// `api6.ipify.org` will be resolved as IPv6 and the request will be over IPv6 (the website will respond with your public IPv6) +await got('https://api6.ipify.org', { + dnsLookupIpVersion: 'ipv6' +}); +``` + +###### lookup + +Type: `Function`\ +Default: [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) + +Custom DNS resolution logic. + +The function signature is the same as [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback). + +###### request + +Type: `Function`\ +Default: `http.request | https.request` *(Depending on the protocol)* + +Custom request function. The main purpose of this is to [support HTTP2 using a wrapper](https://github.com/szmarczak/http2-wrapper). + +###### http2 + +Type: `boolean`\ +Default: `false` + +If set to `true`, Got will additionally accept HTTP2 requests.\ +It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol. + +**Note:** Overriding `options.request` will disable HTTP2 support. + +**Note:** This option will default to `true` in the next upcoming major release. + +```js +const got = require('got'); + +(async () => { + const {headers} = await got('https://nghttp2.org/httpbin/anything', {http2: true}); + console.log(headers.via); + //=> '2 nghttpx' +})(); +``` + +###### throwHttpErrors + +Type: `boolean`\ +Default: `true` + +Determines if a [`got.HTTPError`](#gothttperror) is thrown for unsuccessful responses. + +If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. This may be useful if you are checking for resource availability and are expecting error responses. + +###### agent + +Type: `object` + +An object representing `http`, `https` and `http2` keys for [`http.Agent`](https://nodejs.org/api/http.html#http_class_http_agent), [`https.Agent`](https://nodejs.org/api/https.html#https_class_https_agent) and [`http2wrapper.Agent`](https://github.com/szmarczak/http2-wrapper#new-http2agentoptions) instance. This is necessary because a request to one protocol might redirect to another. In such a scenario, Got will switch over to the right protocol agent for you. + +If a key is not present, it will default to a global agent. + +```js +const got = require('got'); +const HttpAgent = require('agentkeepalive'); +const {HttpsAgent} = HttpAgent; + +got('https://sindresorhus.com', { + agent: { + http: new HttpAgent(), + https: new HttpsAgent() + } +}); +``` + +###### hooks + +Type: `object` + +Hooks allow modifications during the request lifecycle. Hook functions may be async and are run serially. + +###### hooks.init + +Type: `Function[]`\ +Default: `[]` + +Called with plain [request options](#options), right before their normalization. This is especially useful in conjunction with [`got.extend()`](#instances) when the input needs custom handling. + +See the [Request migration guide](documentation/migration-guides.md#breaking-changes) for an example. + +**Note #1:** This hook must be synchronous!\ +**Note #2:** Errors in this hook will be converted into an instances of [`RequestError`](#gotrequesterror).\ +**Note #3:** The options object may not have a `url` property. To modify it, use a `beforeRequest` hook instead. + +###### hooks.beforeRequest + +Type: `Function[]`\ +Default: `[]` + +Called with [normalized](source/core/index.ts) [request options](#options). Got will make no further changes to the request before it is sent. This is especially useful in conjunction with [`got.extend()`](#instances) when you want to create an API client that, for example, uses HMAC-signing. + +**Note:** Changing `options.json` or `options.form` has no effect on the request, you should change `options.body` instead. If needed, update the `options.headers` accordingly. Example: + +```js +const got = require('got'); + +got.post({ + json: {payload: 'old'}, + hooks: { + beforeRequest: [ + options => { + options.body = JSON.stringify({payload: 'new'}); + options.headers['content-length'] = options.body.length.toString(); + } + ] + } +}); +``` + +**Tip:** You can override the `request` function by returning a [`ClientRequest`-like](https://nodejs.org/api/http.html#http_class_http_clientrequest) instance or a [`IncomingMessage`-like](https://nodejs.org/api/http.html#http_class_http_incomingmessage) instance. This is very useful when creating a custom cache mechanism. + +###### hooks.beforeRedirect + +Type: `Function[]`\ +Default: `[]` + +Called with [normalized](source/core/index.ts) [request options](#options) and the redirect [response](#response). Got will make no further changes to the request. This is especially useful when you want to avoid dead sites. Example: + +```js +const got = require('got'); + +got('https://example.com', { + hooks: { + beforeRedirect: [ + (options, response) => { + if (options.hostname === 'deadSite') { + options.hostname = 'fallbackSite'; + } + } + ] + } +}); +``` + +###### hooks.beforeRetry + +Type: `Function[]`\ +Default: `[]` + +**Note:** When using streams, this hook is ignored. + +Called with [normalized](source/normalize-arguments.ts) [request options](#options), the error and the retry count. Got will make no further changes to the request. This is especially useful when some extra work is required before the next try. Example: + +```js +const got = require('got'); + +got.post('https://example.com', { + hooks: { + beforeRetry: [ + (options, error, retryCount) => { + if (error.response.statusCode === 413) { // Payload too large + options.body = getNewBody(); + } + } + ] + } +}); +``` + +**Note:** When retrying in a `afterResponse` hook, all remaining `beforeRetry` hooks will be called without the `error` and `retryCount` arguments. + +###### hooks.afterResponse + +Type: `Function[]`\ +Default: `[]` + +**Note:** When using streams, this hook is ignored. + +Called with [response object](#response) and a retry function. Calling the retry function will trigger `beforeRetry` hooks. + +Each function should return the response. This is especially useful when you want to refresh an access token. Example: + +```js +const got = require('got'); + +const instance = got.extend({ + hooks: { + afterResponse: [ + (response, retryWithMergedOptions) => { + if (response.statusCode === 401) { // Unauthorized + const updatedOptions = { + headers: { + token: getNewToken() // Refresh the access token + } + }; + + // Save for further requests + instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions); + + // Make a new retry + return retryWithMergedOptions(updatedOptions); + } + + // No changes otherwise + return response; + } + ], + beforeRetry: [ + (options, error, retryCount) => { + // This will be called on `retryWithMergedOptions(...)` + } + ] + }, + mutableDefaults: true +}); +``` + +###### hooks.beforeError + +Type: `Function[]`\ +Default: `[]` + +Called with an `Error` instance. The error is passed to the hook right before it's thrown. This is especially useful when you want to have more detailed errors. + +**Note:** Errors thrown while normalizing input options are thrown directly and not part of this hook. + +```js +const got = require('got'); + +got('https://api.github.com/some-endpoint', { + hooks: { + beforeError: [ + error => { + const {response} = error; + if (response && response.body) { + error.name = 'GitHubError'; + error.message = `${response.body.message} (${response.statusCode})`; + } + + return error; + } + ] + } +}); +``` + +##### pagination + +Type: `object` + +**Note:** We're [looking for feedback](https://github.com/sindresorhus/got/issues/1052), any ideas on how to improve the API are welcome. + +###### pagination.transform + +Type: `Function`\ +Default: `response => JSON.parse(response.body)` + +A function that transform [`Response`](#response) into an array of items. This is where you should do the parsing. + +###### pagination.paginate + +Type: `Function`\ +Default: [`Link` header logic](source/index.ts) + +The function takes three arguments: +- `response` - The current response object. +- `allItems` - An array of the emitted items. +- `currentItems` - Items from the current response. + +It should return an object representing Got options pointing to the next page. The options are merged automatically with the previous request, therefore the options returned `pagination.paginate(...)` must reflect changes only. If there are no more pages, `false` should be returned. + +For example, if you want to stop when the response contains less items than expected, you can use something like this: + +```js +const got = require('got'); + +(async () => { + const limit = 10; + + const items = got.paginate('https://example.com/items', { + searchParams: { + limit, + offset: 0 + }, + pagination: { + paginate: (response, allItems, currentItems) => { + const previousSearchParams = response.request.options.searchParams; + const previousOffset = previousSearchParams.get('offset'); + + if (currentItems.length < limit) { + return false; + } + + return { + searchParams: { + ...previousSearchParams, + offset: Number(previousOffset) + limit, + } + }; + } + } + }); + + console.log('Items from all pages:', items); +})(); +``` + +###### pagination.filter + +Type: `Function`\ +Default: `(item, allItems, currentItems) => true` + +Checks whether the item should be emitted or not. + +###### pagination.shouldContinue + +Type: `Function`\ +Default: `(item, allItems, currentItems) => true` + +Checks whether the pagination should continue. + +For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems, currentItems) => !item.flag`. If you want to stop **after** emitting the entry, you should use `(item, allItems, currentItems) => allItems.some(entry => entry.flag)` instead. + +###### pagination.countLimit + +Type: `number`\ +Default: `Infinity` + +The maximum amount of items that should be emitted. + +###### pagination.backoff + +Type: `number`\ +Default: `0` + +Milliseconds to wait before the next request is triggered. + +###### pagination.requestLimit + +Type: `number`\ +Default: `10000` + +The maximum amount of request that should be triggered. [Retries on failure](#retry) are not counted towards this limit. + +For example, it can be helpful during development to avoid an infinite number of requests. + +###### pagination.stackAllItems + +Type: `boolean`\ +Default: `true` + +Defines how the parameter `allItems` in [pagination.paginate](#pagination.paginate), [pagination.filter](#pagination.filter) and [pagination.shouldContinue](#pagination.shouldContinue) is managed. When set to `false`, the parameter `allItems` is always an empty array. + +This option can be helpful to save on memory usage when working with a large dataset. + +##### localAddress + +Type: `string` + +The IP address used to send the request from. + +### Advanced HTTPS API + +Note: If the request is not HTTPS, these options will be ignored. + +##### https.certificateAuthority + +Type: `string | Buffer | Array` + +Override the default Certificate Authorities ([from Mozilla](https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport)) + +```js +// Single Certificate Authority +got('https://example.com', { + https: { + certificateAuthority: fs.readFileSync('./my_ca.pem') + } +}); +``` + +##### https.key + +Type: `string | Buffer | Array | object[]` + +Private keys in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format.\ +[PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) allows the option of private keys being encrypted. Encrypted keys will be decrypted with `options.https.passphrase`.\ +Multiple keys with different passphrases can be provided as an array of `{pem: , passphrase: }` + +##### https.certificate + +Type: `string | Buffer | (string | Buffer)[]` + +[Certificate chains](https://en.wikipedia.org/wiki/X.509#Certificate_chains_and_cross-certification) in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format.\ +One cert chain should be provided per private key (`options.https.key`).\ +When providing multiple cert chains, they do not have to be in the same order as their private keys in `options.https.key`.\ +If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail. + +##### https.passphrase + +Type: `string` + +The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation). + +##### https.pfx + +Type: `string | Buffer | Array` + +[PFX or PKCS12](https://en.wikipedia.org/wiki/PKCS_12) encoded private key and certificate chain. Using `options.https.pfx` is an alternative to providing `options.https.key` and `options.https.certificate` individually. A PFX is usually encrypted, and if it is, `options.https.passphrase` will be used to decrypt it. + +Multiple PFX's can be be provided as an array of unencrypted buffers or an array of objects like: + +```ts +{ + buffer: string | Buffer, + passphrase?: string +} +``` + +This object form can only occur in an array. If the provided buffers are encrypted, `object.passphrase` can be used to decrypt them. If `object.passphrase` is not provided, `options.https.passphrase` will be used for decryption. + +##### Examples for `https.key`, `https.certificate`, `https.passphrase`, and `https.pfx` + +```js +// Single key with certificate +got('https://example.com', { + https: { + key: fs.readFileSync('./client_key.pem'), + certificate: fs.readFileSync('./client_cert.pem') + } +}); + +// Multiple keys with certificates (out of order) +got('https://example.com', { + https: { + key: [ + fs.readFileSync('./client_key1.pem'), + fs.readFileSync('./client_key2.pem') + ], + certificate: [ + fs.readFileSync('./client_cert2.pem'), + fs.readFileSync('./client_cert1.pem') + ] + } +}); + +// Single key with passphrase +got('https://example.com', { + https: { + key: fs.readFileSync('./client_key.pem'), + certificate: fs.readFileSync('./client_cert.pem'), + passphrase: 'client_key_passphrase' + } +}); + +// Multiple keys with different passphrases +got('https://example.com', { + https: { + key: [ + {pem: fs.readFileSync('./client_key1.pem'), passphrase: 'passphrase1'}, + {pem: fs.readFileSync('./client_key2.pem'), passphrase: 'passphrase2'}, + ], + certificate: [ + fs.readFileSync('./client_cert1.pem'), + fs.readFileSync('./client_cert2.pem') + ] + } +}); + +// Single encrypted PFX with passphrase +got('https://example.com', { + https: { + pfx: fs.readFileSync('./fake.pfx'), + passphrase: 'passphrase' + } +}); + +// Multiple encrypted PFX's with different passphrases +got('https://example.com', { + https: { + pfx: [ + { + buffer: fs.readFileSync('./key1.pfx'), + passphrase: 'passphrase1' + }, + { + buffer: fs.readFileSync('./key2.pfx'), + passphrase: 'passphrase2' + } + ] + } +}); + +// Multiple encrypted PFX's with single passphrase +got('https://example.com', { + https: { + passphrase: 'passphrase', + pfx: [ + { + buffer: fs.readFileSync('./key1.pfx') + }, + { + buffer: fs.readFileSync('./key2.pfx') + } + ] + } +}); +``` + +##### https.rejectUnauthorized + +Type: `boolean`\ +Default: `true` + +If set to `false`, all invalid SSL certificates will be ignored and no error will be thrown.\ +If set to `true`, it will throw an error whenever an invalid SSL certificate is detected. + +We strongly recommend to have this set to `true` for security reasons. + +```js +const got = require('got'); + +(async () => { + // Correct: + await got('https://example.com', { + https: { + rejectUnauthorized: true + } + }); + + // You can disable it when developing an HTTPS app: + await got('https://localhost', { + https: { + rejectUnauthorized: false + } + }); + + // Never do this: + await got('https://example.com', { + https: { + rejectUnauthorized: false + } + }); +``` + +##### https.checkServerIdentity + +Type: `Function`\ +Signature: `(hostname: string, certificate: DetailedPeerCertificate) => Error | undefined`\ +Default: `tls.checkServerIdentity` (from the `tls` module) + +This function enable a custom check of the certificate.\ +Note: In order to have the function called the certificate must not be `expired`, `self-signed` or with an `untrusted-root`.\ +The function parameters are: +- `hostname`: The server hostname (used when connecting) +- `certificate`: The server certificate + +The function must return `undefined` if the check succeeded or an `Error` if it failed. + +```js +await got('https://example.com', { + https: { + checkServerIdentity: (hostname, certificate) => { + if (hostname === 'example.com') { + return; // Certificate OK + } + + return new Error('Invalid Hostname'); // Certificate NOT OK + } + } +}); +``` + +#### Response + +The response object will typically be a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage), however, if returned from the cache it will be a [response-like object](https://github.com/lukechilds/responselike) which behaves in the same way. + +##### request + +Type: `object` + +**Note:** This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest). + +- `options` - The Got options that were set on this request. + +##### body + +Type: `string | object | Buffer` *(Depending on `options.responseType`)* + +The result of the request. + +##### rawBody + +Type: `Buffer` + +The raw result of the request. + +##### url + +Type: `string` + +The request URL or the final URL after redirects. + +##### ip + +Type: `string` + +The remote IP address. + +**Note:** Not available when the response is cached. This is hopefully a temporary limitation, see [lukechilds/cacheable-request#86](https://github.com/lukechilds/cacheable-request/issues/86). + +##### requestUrl + +Type: `string` + +The original request URL. + +##### timings + +Type: `object` + +The object contains the following properties: + +- `start` - Time when the request started. +- `socket` - Time when a socket was assigned to the request. +- `lookup` - Time when the DNS lookup finished. +- `connect` - Time when the socket successfully connected. +- `secureConnect` - Time when the socket securely connected. +- `upload` - Time when the request finished uploading. +- `response` - Time when the request fired `response` event. +- `end` - Time when the response fired `end` event. +- `error` - Time when the request fired `error` event. +- `abort` - Time when the request fired `abort` event. +- `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + +If something has not been measured yet, it will be `undefined`. + +**Note:** The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + +##### isFromCache + +Type: `boolean` + +Whether the response was retrieved from the cache. + +##### redirectUrls + +Type: `string[]` + +The redirect URLs. + +##### retryCount + +Type: `number` + +The number of times the request was retried. + +#### Streams + +**Note:** Progress events, redirect events and request/response events can also be used with promises. + +**Note:** To access `response.isFromCache` you need to use `got.stream(url, options).isFromCache`. The value will be undefined until the `response` event. + +#### got.stream(url, options?) + +Sets `options.isStream` to `true`. + +Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex) with additional events: + +##### .on('request', request) + +`request` event to get the request object of the request. + +**Tip:** You can use `request` event to abort request: + +```js +got.stream('https://github.com') + .on('request', request => setTimeout(() => request.destroy(), 50)); +``` + +##### .on('response', response) + +The `response` event to get the response object of the final request. + +##### .on('redirect', response, nextOptions) + +The `redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location. + +##### .on('uploadProgress', progress) +##### .uploadProgress +##### .on('downloadProgress', progress) +##### .downloadProgress + +Progress events for uploading (sending a request) and downloading (receiving a response). The `progress` argument is an object like: + +```js +{ + percent: 0.1, + transferred: 1024, + total: 10240 +} +``` + +If the `content-length` header is missing, `total` will be `undefined`. + +```js +(async () => { + const response = await got('https://sindresorhus.com') + .on('downloadProgress', progress => { + // Report download progress + }) + .on('uploadProgress', progress => { + // Report upload progress + }); + + console.log(response); +})(); +``` + +##### .once('retry', retryCount, error) + +To enable retrying on a Got stream, it is required to have a `retry` handler attached.\ +When this event is emitted, you should reset the stream you were writing to and prepare the body again. + +See the [`retry`](#retry-stream) option for an example implementation. + +##### .ip + +Type: `string` + +The remote IP address. + +##### .aborted + +Type: `boolean` + +Indicates whether the request has been aborted or not. + +##### .timings + +The same as `response.timings`. + +##### .isFromCache + +The same as `response.isFromCache`. + +##### .socket + +The same as `response.socket`. + +##### .on('error', error) + +The emitted `error` is an instance of [`RequestError`](#gotrequesterror). + +#### Pagination + +#### got.paginate(url, options?) +#### got.paginate.each(url, options?) + +Returns an async iterator: + +```js +(async () => { + const countLimit = 10; + + const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + + for await (const commitData of pagination) { + console.log(commitData.commit.message); + } +})(); +``` + +See [`options.pagination`](#pagination) for more pagination options. + +#### got.paginate.all(url, options?) + +Returns a Promise for an array of all results: + +```js +(async () => { + const countLimit = 10; + + const results = await got.paginate.all('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + console.log(results); +})(); +``` + +See [`options.pagination`](#pagination) for more pagination options. + +#### got.get(url, options?) +#### got.post(url, options?) +#### got.put(url, options?) +#### got.patch(url, options?) +#### got.head(url, options?) +#### got.delete(url, options?) + +Sets [`options.method`](#method) to the method name and makes a request. + +### Instances + +#### got.extend(...options) + +Configure a new `got` instance with default `options`. The `options` are merged with the parent instance's `defaults.options` using [`got.mergeOptions`](#gotmergeoptionsparentoptions-newoptions). You can access the resolved options with the `.defaults` property on the instance. + +```js +const client = got.extend({ + prefixUrl: 'https://example.com', + headers: { + 'x-unicorn': 'rainbow' + } +}); + +client.get('demo'); + +/* HTTP Request => + * GET /demo HTTP/1.1 + * Host: example.com + * x-unicorn: rainbow + */ +``` + +```js +(async () => { + const client = got.extend({ + prefixUrl: 'httpbin.org', + headers: { + 'x-foo': 'bar' + } + }); + const {headers} = await client.get('headers').json(); + //=> headers['x-foo'] === 'bar' + + const jsonClient = client.extend({ + responseType: 'json', + resolveBodyOnly: true, + headers: { + 'x-baz': 'qux' + } + }); + const {headers: headers2} = await jsonClient.get('headers'); + //=> headers2['x-foo'] === 'bar' + //=> headers2['x-baz'] === 'qux' +})(); +``` + +Additionally, `got.extend()` accepts two properties from the `defaults` object: `mutableDefaults` and `handlers`. Example: + +```js +// You can now modify `mutableGot.defaults.options`. +const mutableGot = got.extend({mutableDefaults: true}); + +const mergedHandlers = got.extend({ + handlers: [ + (options, next) => { + delete options.headers.referer; + + return next(options); + } + ] +}); +``` + +**Note:** Handlers can be asynchronous. The recommended approach is: + +```js +const handler = (options, next) => { + if (options.isStream) { + // It's a Stream + return next(options); + } + + // It's a Promise + return (async () => { + try { + const response = await next(options); + response.yourOwnProperty = true; + return response; + } catch (error) { + // Every error will be replaced by this one. + // Before you receive any error here, + // it will be passed to the `beforeError` hooks first. + // Note: this one won't be passed to `beforeError` hook. It's final. + throw new Error('Your very own error.'); + } + })(); +}; + +const instance = got.extend({handlers: [handler]}); +``` + +#### got.extend(...options, ...instances, ...) + +Merges many instances into a single one: +- options are merged using [`got.mergeOptions()`](#gotmergeoptionsparentoptions-newoptions) (including hooks), +- handlers are stored in an array (you can access them through `instance.defaults.handlers`). + +```js +const a = {headers: {cat: 'meow'}}; +const b = got.extend({ + options: { + headers: { + cow: 'moo' + } + } +}); + +// The same as `got.extend(a).extend(b)`. +// Note `a` is options and `b` is an instance. +got.extend(a, b); +//=> {headers: {cat: 'meow', cow: 'moo'}} +``` + +#### got.mergeOptions(parent, ...sources) + +Extends parent options. Avoid using [object spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) as it doesn't work recursively: + +```js +const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}}; +const b = {headers: {cow: 'moo', wolf: ['auuu']}}; + +{...a, ...b} // => {headers: {cow: 'moo', wolf: ['auuu']}} +got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}} +``` + +**Note:** Only Got options are merged! Custom user options should be defined via [`options.context`](#context). + +Options are deeply merged to a new object. The value of each key is determined as follows: + +- If the new property is not defined, the old value is used. +- If the new property is explicitly set to `undefined`: + - If the parent property is a plain `object`, the parent value is deeply cloned. + - Otherwise, `undefined` is used. +- If the parent value is an instance of `URLSearchParams`: + - If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append). The keys defined in the new value override the keys defined in the parent value. Please note that `null` values point to an empty string and `undefined` values will exclude the entry. + - Otherwise, the only available value is `undefined`. +- If the new property is a plain `object`: + - If the parent property is a plain `object` too, both values are merged recursively into a new `object`. + - Otherwise, only the new value is deeply cloned. +- If the new property is an `Array`, it overwrites the old one with a deep clone of the new property. +- Properties that are not enumerable, such as `context`, `body`, `json`, and `form`, will not be merged. +- Otherwise, the new value is assigned to the key. + +```js +const a = {json: {cat: 'meow'}}; +const b = {json: {cow: 'moo'}}; + +got.mergeOptions(a, b); +//=> {json: {cow: 'moo'}} +``` + +#### got.defaults + +Type: `object` + +The Got defaults used in that instance. + +##### [options](#options) + +##### handlers + +Type: `Function[]`\ +Default: `[]` + +An array of functions. You execute them directly by calling `got()`. They are some sort of "global hooks" - these functions are called first. The last handler (*it's hidden*) is either [`asPromise`](source/core/as-promise/index.ts) or [`asStream`](source/core/index.ts), depending on the `options.isStream` property. + +Each handler takes two arguments: + +###### [options](#options) + +###### next() + +Returns a `Promise` or a `Stream` depending on [`options.isStream`](#isstream). + +```js +const settings = { + handlers: [ + (options, next) => { + if (options.isStream) { + // It's a Stream, so we can perform stream-specific actions on it + return next(options) + .on('request', request => { + setTimeout(() => { + request.abort(); + }, 50); + }); + } + + // It's a Promise + return next(options); + } + ], + options: got.mergeOptions(got.defaults.options, { + responseType: 'json' + }) +}; + +const jsonGot = got.extend(settings); +``` + +##### mutableDefaults + +Type: `boolean`\ +Default: `false` + +A read-only boolean describing whether the defaults are mutable or not. If set to `true`, you can [update headers over time](#hooksafterresponse), for example, update an access token when it expires. + +## Types + +Got exports some handy TypeScript types and interfaces. See the type definition for all the exported types. + +### Got + +TypeScript will automatically infer types for Got instances, but in case you want to define something like dependencies, you can import the available types directly from Got. + +```ts +import {GotRequestFunction} from 'got'; + +interface Dependencies { + readonly post: GotRequestFunction +} +``` + +### Hooks + +When writing hooks, you can refer to their types to keep your interfaces consistent. + +```ts +import {BeforeRequestHook} from 'got'; + +const addAccessToken = (accessToken: string): BeforeRequestHook => options => { + options.path = `${options.path}?access_token=${accessToken}`; +} +``` + +## Errors + +Each error contains an `options` property which are the options Got used to create a request - just to make debugging easier.\ +Additionaly, the errors may have `request` (Got Stream) and `response` (Got Response) properties depending on which phase of the request failed. + +#### got.RequestError + +When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`. All the errors below inherit this one. + +#### got.CacheError + +When a cache method fails, for example, if the database goes down or there's a filesystem error. + +#### got.ReadError + +When reading from response stream fails. + +#### got.ParseError + +When server response code is 2xx, and parsing body fails. Includes a `response` property. + +#### got.UploadError + +When the request body is a stream and an error occurs while reading from that stream. + +#### got.HTTPError + +When the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. Includes a `response` property. + +#### got.MaxRedirectsError + +When the server redirects you more than ten times. Includes a `response` property. + +#### got.UnsupportedProtocolError + +When given an unsupported protocol. + +#### got.TimeoutError + +When the request is aborted due to a [timeout](#timeout). Includes an `event` and `timings` property. + +#### got.CancelError + +When the request is aborted with `.cancel()`. + +## Aborting the request + +The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/p-cancelable) method which when called, aborts the request. + +```js +(async () => { + const request = got(url, options); + + // … + + // In another part of the code + if (something) { + request.cancel(); + } + + // … + + try { + await request; + } catch (error) { + if (request.isCanceled) { // Or `error instanceof got.CancelError` + // Handle cancelation + } + + // Handle other errors + } +})(); +``` + +When using hooks, simply throw an error to abort the request. + +```js +const got = require('got'); + +(async () => { + const request = got(url, { + hooks: { + beforeRequest: [ + () => { + throw new Error('Oops. Request canceled.'); + } + ] + } + }); + + try { + await request; + } catch (error) { + // … + } +})(); +``` + +To abort the Got Stream request, just call `stream.destroy()`. + +```js +const got = require('got'); + +const stream = got.stream(url); +stream.destroy(); +``` + + +## Cache + +Got implements [RFC 7234](https://httpwg.org/specs/rfc7234.html) compliant HTTP caching which works out of the box in-memory and is easily pluggable with a wide range of storage adapters. Fresh cache entries are served directly from the cache, and stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers. You can read more about the underlying cache behavior in the [`cacheable-request` documentation](https://github.com/lukechilds/cacheable-request). For DNS cache, Got uses [`cacheable-lookup`](https://github.com/szmarczak/cacheable-lookup). + +You can use the JavaScript `Map` type as an in-memory cache: + +```js +const got = require('got'); + +const map = new Map(); + +(async () => { + let response = await got('https://sindresorhus.com', {cache: map}); + console.log(response.isFromCache); + //=> false + + response = await got('https://sindresorhus.com', {cache: map}); + console.log(response.isFromCache); + //=> true +})(); +``` + +Got uses [Keyv](https://github.com/lukechilds/keyv) internally to support a wide range of storage adapters. For something more scalable you could use an [official Keyv storage adapter](https://github.com/lukechilds/keyv#official-storage-adapters): + +``` +$ npm install @keyv/redis +``` + +```js +const got = require('got'); +const KeyvRedis = require('@keyv/redis'); + +const redis = new KeyvRedis('redis://user:pass@localhost:6379'); + +got('https://sindresorhus.com', {cache: redis}); +``` + +Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution. + +For example, the following are all valid storage adapters: + +```js +const storageAdapter = new Map(); +// Or +const storageAdapter = require('./my-storage-adapter'); +// Or +const QuickLRU = require('quick-lru'); +const storageAdapter = new QuickLRU({maxSize: 1000}); + +got('https://sindresorhus.com', {cache: storageAdapter}); +``` + +View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters. + +## Proxies + +You can use the [`tunnel`](https://github.com/koichik/node-tunnel) package with the `agent` option to work with proxies: + +```js +const got = require('got'); +const tunnel = require('tunnel'); + +got('https://sindresorhus.com', { + agent: { + https: tunnel.httpsOverHttp({ + proxy: { + host: 'localhost' + } + }) + } +}); +``` + +Otherwise, you can use the [`hpagent`](https://github.com/delvedor/hpagent) package, which keeps the internal sockets alive to be reused. + +```js +const got = require('got'); +const {HttpsProxyAgent} = require('hpagent'); + +got('https://sindresorhus.com', { + agent: { + https: new HttpsProxyAgent({ + keepAlive: true, + keepAliveMsecs: 1000, + maxSockets: 256, + maxFreeSockets: 256, + scheduling: 'lifo', + proxy: 'https://localhost:8080' + }) + } +}); +``` + +Alternatively, use [`global-agent`](https://github.com/gajus/global-agent) to configure a global proxy for all HTTP/HTTPS traffic in your program. + +Read the [`http2-wrapper`](https://github.com/szmarczak/http2-wrapper/#proxy-support) docs to learn about proxying for HTTP/2. + +## Cookies + +You can use the [`tough-cookie`](https://github.com/salesforce/tough-cookie) package: + +```js +const {promisify} = require('util'); +const got = require('got'); +const {CookieJar} = require('tough-cookie'); + +(async () => { + const cookieJar = new CookieJar(); + const setCookie = promisify(cookieJar.setCookie.bind(cookieJar)); + + await setCookie('foo=bar', 'https://example.com'); + await got('https://example.com', {cookieJar}); +})(); +``` + +## Form data + +You can use the [`form-data`](https://github.com/form-data/form-data) package to create POST request with form data: + +```js +const fs = require('fs'); +const got = require('got'); +const FormData = require('form-data'); + +const form = new FormData(); + +form.append('my_file', fs.createReadStream('/foo/bar.jpg')); + +got.post('https://example.com', { + body: form +}); +``` + +## OAuth + +You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) package to create a signed OAuth request: + +```js +const got = require('got'); +const crypto = require('crypto'); +const OAuth = require('oauth-1.0a'); + +const oauth = OAuth({ + consumer: { + key: process.env.CONSUMER_KEY, + secret: process.env.CONSUMER_SECRET + }, + signature_method: 'HMAC-SHA1', + hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64') +}); + +const token = { + key: process.env.ACCESS_TOKEN, + secret: process.env.ACCESS_TOKEN_SECRET +}; + +const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'; + +got(url, { + headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)), + responseType: 'json' +}); +``` + +## Unix Domain Sockets + +Requests can also be sent via [unix domain sockets](http://serverfault.com/questions/124517/whats-the-difference-between-unix-socket-and-tcp-ip-socket). Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH`. + +- `PROTOCOL` - `http` or `https` *(optional)* +- `SOCKET` - Absolute path to a unix domain socket, for example: `/var/run/docker.sock` +- `PATH` - Request path, for example: `/v2/keys` + +```js +const got = require('got'); + +got('http://unix:/var/run/docker.sock:/containers/json'); + +// Or without protocol (HTTP by default) +got('unix:/var/run/docker.sock:/containers/json'); +``` + +## AWS + +Requests to AWS services need to have their headers signed. This can be accomplished by using the [`got4aws`](https://www.npmjs.com/package/got4aws) package. This is an example for querying an ["API Gateway"](https://docs.aws.amazon.com/apigateway/api-reference/signing-requests/) with a signed request. + +```js +const got4aws = require('got4aws');; + +const awsClient = got4aws(); + +const response = await awsClient('https://.execute-api..amazonaws.com//endpoint/path', { + // Request-specific options +}); +``` + +## Testing + +You can test your requests by using the [`nock`](https://github.com/node-nock/nock) package to mock an endpoint: + +```js +const got = require('got'); +const nock = require('nock'); + +nock('https://sindresorhus.com') + .get('/') + .reply(200, 'Hello world!'); + +(async () => { + const response = await got('https://sindresorhus.com'); + console.log(response.body); + //=> 'Hello world!' +})(); +``` + +Bear in mind, that by default `nock` mocks only one request. Got will [retry](#retry) on failed requests by default, causing a `No match for request ...` error. The solution is to either disable retrying (set `options.retry` to `0`) or call `.persist()` on the mocked request. + +```js +const got = require('got'); +const nock = require('nock'); + +const scope = nock('https://sindresorhus.com') + .get('/') + .reply(500, 'Internal server error') + .persist(); + +(async () => { + try { + await got('https://sindresorhus.com') + } catch (error) { + console.log(error.response.body); + //=> 'Internal server error' + + console.log(error.response.retryCount); + //=> 2 + } + + scope.persist(false); +})(); +``` + +For real integration testing we recommend using [`ava`](https://github.com/avajs/ava) with [`create-test-server`](https://github.com/lukechilds/create-test-server). We're using a macro so we don't have to `server.listen()` and `server.close()` every test. Take a look at one of our tests: + +```js +test('retry function gets iteration count', withServer, async (t, server, got) => { + let knocks = 0; + server.get('/', (request, response) => { + if (knocks++ === 1) { + response.end('who`s there?'); + } + }); + + await got({ + retry: { + calculateDelay: ({attemptCount}) => { + t.true(is.number(attemptCount)); + return attemptCount < 2 ? 1 : 0; + } + } + }); +}); +``` + +## Tips + +### JSON mode + +To pass an object as the body, you need to use the `json` option. It will be stringified using `JSON.stringify`. Example: + +```js +const got = require('got'); + +(async () => { + const {body} = await got.post('https://httpbin.org/anything', { + json: { + hello: 'world' + }, + responseType: 'json' + }); + + console.log(body.data); + //=> '{"hello":"world"}' +})(); +``` + +To receive a JSON body you can either set `responseType` option to `json` or use `promise.json()`. Example: + +```js +const got = require('got'); + +(async () => { + const body = await got.post('https://httpbin.org/anything', { + json: { + hello: 'world' + } + }).json(); + + console.log(body); + //=> {…} +})(); +``` + +### User Agent + +It's a good idea to set the `'user-agent'` header so the provider can more easily see how their resource is used. By default, it's the URL to this repo. You can omit this header by setting it to `undefined`. + +```js +const got = require('got'); +const pkg = require('./package.json'); + +got('https://sindresorhus.com', { + headers: { + 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)` + } +}); + +got('https://sindresorhus.com', { + headers: { + 'user-agent': undefined + } +}); +``` + +### 304 Responses + +Bear in mind; if you send an `if-modified-since` header and receive a `304 Not Modified` response, the body will be empty. It's your responsibility to cache and retrieve the body contents. + +### Custom endpoints + +Use `got.extend()` to make it nicer to work with REST APIs. Especially if you use the `prefixUrl` option. + +```js +const got = require('got'); +const pkg = require('./package.json'); + +const custom = got.extend({ + prefixUrl: 'example.com', + responseType: 'json', + headers: { + 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)` + } +}); + +// Use `custom` exactly how you use `got` +(async () => { + const list = await custom('v1/users/list'); +})(); +``` + +## FAQ + +### Why yet another HTTP client? + +Got was created because the popular [`request`](https://github.com/request/request) package is bloated: [![Install size](https://packagephobia.now.sh/badge?p=request)](https://packagephobia.now.sh/result?p=request)\ +Furthermore, Got is fully written in TypeScript and actively maintained. + +### Electron support has been removed + +The Electron `net` module is not consistent with the Node.js `http` module. See [#899](https://github.com/sindresorhus/got/issues/899) for more info. + +## Comparison + +| | `got` | [`request`][r0] | [`node-fetch`][n0] | [`ky`][k0] | [`axios`][a0] | [`superagent`][s0] | +|-----------------------|:------------------:|:------------------:|:--------------------:|:------------------------:|:------------------:|:----------------------:| +| HTTP/2 support | :sparkle: | :x: | :x: | :x: | :x: | :heavy_check_mark:\*\* | +| Browser support | :x: | :x: | :heavy_check_mark:\* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Promise API | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Stream API | :heavy_check_mark: | :heavy_check_mark: | Node.js only | :x: | :x: | :heavy_check_mark: | +| Pagination API | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | +| Request cancelation | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| RFC compliant caching | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | +| Cookies (out-of-box) | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: | +| Follows redirects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Retries on failure | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: | +| Progress events | :heavy_check_mark: | :x: | :x: | :heavy_check_mark:\*\*\* | Browser only | :heavy_check_mark: | +| Handles gzip/deflate | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Advanced timeouts | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | +| Timings | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: | +| Errors with metadata | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | +| JSON mode | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Custom defaults | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | +| Composable | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | +| Hooks | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | +| Issues open | [![][gio]][g1] | [![][rio]][r1] | [![][nio]][n1] | [![][kio]][k1] | [![][aio]][a1] | [![][sio]][s1] | +| Issues closed | [![][gic]][g2] | [![][ric]][r2] | [![][nic]][n2] | [![][kic]][k2] | [![][aic]][a2] | [![][sic]][s2] | +| Downloads | [![][gd]][g3] | [![][rd]][r3] | [![][nd]][n3] | [![][kd]][k3] | [![][ad]][a3] | [![][sd]][s3] | +| Coverage | [![][gc]][g4] | [![][rc]][r4] | [![][nc]][n4] | [![][kc]][k4] | [![][ac]][a4] | [![][sc]][s4] | +| Build | [![][gb]][g5] | [![][rb]][r5] | [![][nb]][n5] | [![][kb]][k5] | [![][ab]][a5] | [![][sb]][s5] | +| Bugs | [![][gbg]][g6] | [![][rbg]][r6] | [![][nbg]][n6] | [![][kbg]][k6] | [![][abg]][a6] | [![][sbg]][s6] | +| Dependents | [![][gdp]][g7] | [![][rdp]][r7] | [![][ndp]][n7] | [![][kdp]][k7] | [![][adp]][a7] | [![][sdp]][s7] | +| Install size | [![][gis]][g8] | [![][ris]][r8] | [![][nis]][n8] | [![][kis]][k8] | [![][ais]][a8] | [![][sis]][s8] | +| GitHub stars | [![][gs]][g9] | [![][rs]][r9] | [![][ns]][n9] | [![][ks]][k9] | [![][as]][a9] | [![][ss]][s9] | +| TypeScript support | [![][gts]][g10] | [![][rts]][r10] | [![][nts]][n10] | [![][kts]][k10] | [![][ats]][a10] | [![][sts]][s11] | +| Last commit | [![][glc]][g11] | [![][rlc]][r11] | [![][nlc]][n11] | [![][klc]][k11] | [![][alc]][a11] | [![][slc]][s11] | + +\* It's almost API compatible with the browser `fetch` API.\ +\*\* Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.\ +\*\*\* Currently, only `DownloadProgress` event is supported, `UploadProgress` event is not supported.\ +:sparkle: Almost-stable feature, but the API may change. Don't hesitate to try it out!\ +:grey_question: Feature in early stage of development. Very experimental. + + +[k0]: https://github.com/sindresorhus/ky +[r0]: https://github.com/request/request +[n0]: https://github.com/node-fetch/node-fetch +[a0]: https://github.com/axios/axios +[s0]: https://github.com/visionmedia/superagent + + +[gio]: https://badgen.net/github/open-issues/sindresorhus/got?label +[kio]: https://badgen.net/github/open-issues/sindresorhus/ky?label +[rio]: https://badgen.net/github/open-issues/request/request?label +[nio]: https://badgen.net/github/open-issues/bitinn/node-fetch?label +[aio]: https://badgen.net/github/open-issues/axios/axios?label +[sio]: https://badgen.net/github/open-issues/visionmedia/superagent?label + +[g1]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc +[k1]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc +[r1]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc +[n1]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc +[a1]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc +[s1]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc + + +[gic]: https://badgen.net/github/closed-issues/sindresorhus/got?label +[kic]: https://badgen.net/github/closed-issues/sindresorhus/ky?label +[ric]: https://badgen.net/github/closed-issues/request/request?label +[nic]: https://badgen.net/github/closed-issues/bitinn/node-fetch?label +[aic]: https://badgen.net/github/closed-issues/axios/axios?label +[sic]: https://badgen.net/github/closed-issues/visionmedia/superagent?label + +[g2]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc +[k2]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc +[r2]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc +[n2]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc +[a2]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc +[s2]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc + + +[gd]: https://badgen.net/npm/dm/got?label +[kd]: https://badgen.net/npm/dm/ky?label +[rd]: https://badgen.net/npm/dm/request?label +[nd]: https://badgen.net/npm/dm/node-fetch?label +[ad]: https://badgen.net/npm/dm/axios?label +[sd]: https://badgen.net/npm/dm/superagent?label + +[g3]: https://www.npmjs.com/package/got +[k3]: https://www.npmjs.com/package/ky +[r3]: https://www.npmjs.com/package/request +[n3]: https://www.npmjs.com/package/node-fetch +[a3]: https://www.npmjs.com/package/axios +[s3]: https://www.npmjs.com/package/superagent + + +[gc]: https://badgen.net/coveralls/c/github/sindresorhus/got?label +[kc]: https://badgen.net/codecov/c/github/sindresorhus/ky?label +[rc]: https://badgen.net/coveralls/c/github/request/request?label +[nc]: https://badgen.net/coveralls/c/github/bitinn/node-fetch?label +[ac]: https://badgen.net/coveralls/c/github/mzabriskie/axios?label +[sc]: https://badgen.net/codecov/c/github/visionmedia/superagent?label + +[g4]: https://coveralls.io/github/sindresorhus/got +[k4]: https://codecov.io/gh/sindresorhus/ky +[r4]: https://coveralls.io/github/request/request +[n4]: https://coveralls.io/github/bitinn/node-fetch +[a4]: https://coveralls.io/github/mzabriskie/axios +[s4]: https://codecov.io/gh/visionmedia/superagent + + +[gb]: https://badgen.net/travis/sindresorhus/got?label +[kb]: https://badgen.net/travis/sindresorhus/ky?label +[rb]: https://badgen.net/travis/request/request?label +[nb]: https://badgen.net/travis/bitinn/node-fetch?label +[ab]: https://badgen.net/travis/axios/axios?label +[sb]: https://badgen.net/travis/visionmedia/superagent?label + +[g5]: https://travis-ci.com/github/sindresorhus/got +[k5]: https://travis-ci.com/github/sindresorhus/ky +[r5]: https://travis-ci.org/github/request/request +[n5]: https://travis-ci.org/github/bitinn/node-fetch +[a5]: https://travis-ci.org/github/axios/axios +[s5]: https://travis-ci.org/github/visionmedia/superagent + + +[gbg]: https://badgen.net/github/label-issues/sindresorhus/got/bug/open?label +[kbg]: https://badgen.net/github/label-issues/sindresorhus/ky/bug/open?label +[rbg]: https://badgen.net/github/label-issues/request/request/Needs%20investigation/open?label +[nbg]: https://badgen.net/github/label-issues/bitinn/node-fetch/bug/open?label +[abg]: https://badgen.net/github/label-issues/axios/axios/type:confirmed%20bug/open?label +[sbg]: https://badgen.net/github/label-issues/visionmedia/superagent/Bug/open?label + +[g6]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug +[k6]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug +[r6]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A"Needs+investigation" +[n6]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug +[a6]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22type%3Aconfirmed+bug%22 +[s6]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3ABug + + +[gdp]: https://badgen.net/npm/dependents/got?label +[kdp]: https://badgen.net/npm/dependents/ky?label +[rdp]: https://badgen.net/npm/dependents/request?label +[ndp]: https://badgen.net/npm/dependents/node-fetch?label +[adp]: https://badgen.net/npm/dependents/axios?label +[sdp]: https://badgen.net/npm/dependents/superagent?label + +[g7]: https://www.npmjs.com/package/got?activeTab=dependents +[k7]: https://www.npmjs.com/package/ky?activeTab=dependents +[r7]: https://www.npmjs.com/package/request?activeTab=dependents +[n7]: https://www.npmjs.com/package/node-fetch?activeTab=dependents +[a7]: https://www.npmjs.com/package/axios?activeTab=dependents +[s7]: https://www.npmjs.com/package/visionmedia?activeTab=dependents + + +[gis]: https://badgen.net/packagephobia/install/got?label +[kis]: https://badgen.net/packagephobia/install/ky?label +[ris]: https://badgen.net/packagephobia/install/request?label +[nis]: https://badgen.net/packagephobia/install/node-fetch?label +[ais]: https://badgen.net/packagephobia/install/axios?label +[sis]: https://badgen.net/packagephobia/install/superagent?label + +[g8]: https://packagephobia.now.sh/result?p=got +[k8]: https://packagephobia.now.sh/result?p=ky +[r8]: https://packagephobia.now.sh/result?p=request +[n8]: https://packagephobia.now.sh/result?p=node-fetch +[a8]: https://packagephobia.now.sh/result?p=axios +[s8]: https://packagephobia.now.sh/result?p=superagent + + +[gs]: https://badgen.net/github/stars/sindresorhus/got?label +[ks]: https://badgen.net/github/stars/sindresorhus/ky?label +[rs]: https://badgen.net/github/stars/request/request?label +[ns]: https://badgen.net/github/stars/bitinn/node-fetch?label +[as]: https://badgen.net/github/stars/axios/axios?label +[ss]: https://badgen.net/github/stars/visionmedia/superagent?label + +[g9]: https://github.com/sindresorhus/got +[k9]: https://github.com/sindresorhus/ky +[r9]: https://github.com/request/request +[n9]: https://github.com/node-fetch/node-fetch +[a9]: https://github.com/axios/axios +[s9]: https://github.com/visionmedia/superagent + + +[gts]: https://badgen.net/npm/types/got?label +[kts]: https://badgen.net/npm/types/ky?label +[rts]: https://badgen.net/npm/types/request?label +[nts]: https://badgen.net/npm/types/node-fetch?label +[ats]: https://badgen.net/npm/types/axios?label +[sts]: https://badgen.net/npm/types/superagent?label + +[g10]: https://github.com/sindresorhus/got +[k10]: https://github.com/sindresorhus/ky +[r10]: https://github.com/request/request +[n10]: https://github.com/node-fetch/node-fetch +[a10]: https://github.com/axios/axios +[s10]: https://github.com/visionmedia/superagent + + +[glc]: https://badgen.net/github/last-commit/sindresorhus/got?label +[klc]: https://badgen.net/github/last-commit/sindresorhus/ky?label +[rlc]: https://badgen.net/github/last-commit/request/request?label +[nlc]: https://badgen.net/github/last-commit/bitinn/node-fetch?label +[alc]: https://badgen.net/github/last-commit/axios/axios?label +[slc]: https://badgen.net/github/last-commit/visionmedia/superagent?label + +[g11]: https://github.com/sindresorhus/got/commits +[k11]: https://github.com/sindresorhus/ky/commits +[r11]: https://github.com/request/request/commits +[n11]: https://github.com/node-fetch/node-fetch/commits +[a11]: https://github.com/axios/axios/commits +[s11]: https://github.com/visionmedia/superagent/commits + +[Click here][InstallSizeOfTheDependencies] to see the install size of the Got dependencies. + +[InstallSizeOfTheDependencies]: https://packagephobia.com/result?p=@sindresorhus/is@3.0.0,@szmarczak/http-timer@4.0.5,@types/cacheable-request@6.0.1,@types/responselike@1.0.0,cacheable-lookup@5.0.3,cacheable-request@7.0.1,decompress-response@6.0.0,http2-wrapper@1.0.0,lowercase-keys@2.0.0,p-cancelable@2.0.0,responselike@2.0.0 + +## Related + +- [gh-got](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API +- [gl-got](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API +- [travis-got](https://github.com/samverschueren/travis-got) - Got convenience wrapper to interact with the Travis API +- [graphql-got](https://github.com/kevva/graphql-got) - Got convenience wrapper to interact with GraphQL +- [GotQL](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings +- [got-fetch](https://github.com/alexghr/got-fetch) - Got with a `fetch` interface + +## Maintainers + +[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Szymon Marczak](https://github.com/szmarczak.png?size=100)](https://github.com/szmarczak) | [![Giovanni Minotti](https://github.com/Giotino.png?size=100)](https://github.com/Giotino) +---|---|--- +[Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak) | [Giovanni Minotti](https://github.com/Giotino) + +###### Former + +- [Vsevolod Strukchinsky](https://github.com/floatdrop) +- [Alexander Tesfamichael](https://github.com/alextes) +- [Brandon Smith](https://github.com/brandon93s) +- [Luke Childs](https://github.com/lukechilds) + + +## These amazing companies are using Got + + +     + +     + +     + +     + +     + +     + +     + +     + +     + + +
+ +> Segment is a happy user of Got! Got powers the main backend API that our app talks to. It's used by our in-house RPC client that we use to communicate with all microservices. +> +> — Vadim Demedes + +> Antora, a static site generator for creating documentation sites, uses Got to download the UI bundle. In Antora, the UI bundle (aka theme) is maintained as a separate project. That project exports the UI as a zip file we call the UI bundle. The main site generator downloads that UI from a URL using Got and streams it to vinyl-zip to extract the files. Those files go on to be used to create the HTML pages and supporting assets. +> +> — Dan Allen + +> GetVoIP is happily using Got in production. One of the unique capabilities of Got is the ability to handle Unix sockets which enables us to build a full control interfaces for our docker stack. +> +> — Daniel Kalen + +> We're using Got inside of Exoframe to handle all the communication between CLI and server. Exoframe is a self-hosted tool that allows simple one-command deployments using Docker. +> +> — Tim Ermilov + +> Karaoke Mugen uses Got to fetch content updates from its online server. +> +> — Axel Terizaki + +> Renovate uses Got, gh-got and gl-got to send millions of queries per day to GitHub, GitLab, npmjs, PyPi, Packagist, Docker Hub, Terraform, CircleCI, and more. +> +> — Rhys Arkins + +> Resistbot uses Got to communicate from the API frontend where all correspondence ingresses to the officials lookup database in back. +> +> — Chris Erickson + +> Natural Cycles is using Got to communicate with all kinds of 3rd-party REST APIs (over 9000!). +> +> — Kirill Groshkov + +> Microlink is a cloud browser as an API service that uses Got widely as the main HTTP client, serving ~22M requests a month, every time a network call needs to be performed. +> +> — Kiko Beats + +> We’re using Got at Radity. Thanks for such an amazing work! +> +> — Mirzayev Farid + +## For enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of `got` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-got?utm_source=npm-got&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/node_modules/http-cache-semantics/LICENSE b/node_modules/http-cache-semantics/LICENSE new file mode 100644 index 0000000..493d2ea --- /dev/null +++ b/node_modules/http-cache-semantics/LICENSE @@ -0,0 +1,9 @@ +Copyright 2016-2018 Kornel Lesiński + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/http-cache-semantics/README.md b/node_modules/http-cache-semantics/README.md new file mode 100644 index 0000000..685aa55 --- /dev/null +++ b/node_modules/http-cache-semantics/README.md @@ -0,0 +1,203 @@ +# Can I cache this? [![Build Status](https://travis-ci.org/kornelski/http-cache-semantics.svg?branch=master)](https://travis-ci.org/kornelski/http-cache-semantics) + +`CachePolicy` tells when responses can be reused from a cache, taking into account [HTTP RFC 7234](http://httpwg.org/specs/rfc7234.html) rules for user agents and shared caches. +It also implements [RFC 5861](https://tools.ietf.org/html/rfc5861), implementing `stale-if-error` and `stale-while-revalidate`. +It's aware of many tricky details such as the `Vary` header, proxy revalidation, and authenticated responses. + +## Usage + +Cacheability of an HTTP response depends on how it was requested, so both `request` and `response` are required to create the policy. + +```js +const policy = new CachePolicy(request, response, options); + +if (!policy.storable()) { + // throw the response away, it's not usable at all + return; +} + +// Cache the data AND the policy object in your cache +// (this is pseudocode, roll your own cache (lru-cache package works)) +letsPretendThisIsSomeCache.set( + request.url, + { policy, response }, + policy.timeToLive() +); +``` + +```js +// And later, when you receive a new request: +const { policy, response } = letsPretendThisIsSomeCache.get(newRequest.url); + +// It's not enough that it exists in the cache, it has to match the new request, too: +if (policy && policy.satisfiesWithoutRevalidation(newRequest)) { + // OK, the previous response can be used to respond to the `newRequest`. + // Response headers have to be updated, e.g. to add Age and remove uncacheable headers. + response.headers = policy.responseHeaders(); + return response; +} +``` + +It may be surprising, but it's not enough for an HTTP response to be [fresh](#yo-fresh) to satisfy a request. It may need to match request headers specified in `Vary`. Even a matching fresh response may still not be usable if the new request restricted cacheability, etc. + +The key method is `satisfiesWithoutRevalidation(newRequest)`, which checks whether the `newRequest` is compatible with the original request and whether all caching conditions are met. + +### Constructor options + +Request and response must have a `headers` property with all header names in lower case. `url`, `status` and `method` are optional (defaults are any URL, status `200`, and `GET` method). + +```js +const request = { + url: '/', + method: 'GET', + headers: { + accept: '*/*', + }, +}; + +const response = { + status: 200, + headers: { + 'cache-control': 'public, max-age=7234', + }, +}; + +const options = { + shared: true, + cacheHeuristic: 0.1, + immutableMinTimeToLive: 24 * 3600 * 1000, // 24h + ignoreCargoCult: false, +}; +``` + +If `options.shared` is `true` (default), then the response is evaluated from a perspective of a shared cache (i.e. `private` is not cacheable and `s-maxage` is respected). If `options.shared` is `false`, then the response is evaluated from a perspective of a single-user cache (i.e. `private` is cacheable and `s-maxage` is ignored). `shared: true` is recommended for HTTP clients. + +`options.cacheHeuristic` is a fraction of response's age that is used as a fallback cache duration. The default is 0.1 (10%), e.g. if a file hasn't been modified for 100 days, it'll be cached for 100\*0.1 = 10 days. + +`options.immutableMinTimeToLive` is a number of milliseconds to assume as the default time to cache responses with `Cache-Control: immutable`. Note that [per RFC](http://httpwg.org/http-extensions/immutable.html) these can become stale, so `max-age` still overrides the default. + +If `options.ignoreCargoCult` is true, common anti-cache directives will be completely ignored if the non-standard `pre-check` and `post-check` directives are present. These two useless directives are most commonly found in bad StackOverflow answers and PHP's "session limiter" defaults. + +### `storable()` + +Returns `true` if the response can be stored in a cache. If it's `false` then you MUST NOT store either the request or the response. + +### `satisfiesWithoutRevalidation(newRequest)` + +This is the most important method. Use this method to check whether the cached response is still fresh in the context of the new request. + +If it returns `true`, then the given `request` matches the original response this cache policy has been created with, and the response can be reused without contacting the server. Note that the old response can't be returned without being updated, see `responseHeaders()`. + +If it returns `false`, then the response may not be matching at all (e.g. it's for a different URL or method), or may require to be refreshed first (see `revalidationHeaders()`). + +### `responseHeaders()` + +Returns updated, filtered set of response headers to return to clients receiving the cached response. This function is necessary, because proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) and update response's `Age` to avoid doubling cache time. + +```js +cachedResponse.headers = cachePolicy.responseHeaders(cachedResponse); +``` + +### `timeToLive()` + +Returns approximate time in _milliseconds_ until the response becomes stale (i.e. not fresh). + +After that time (when `timeToLive() <= 0`) the response might not be usable without revalidation. However, there are exceptions, e.g. a client can explicitly allow stale responses, so always check with `satisfiesWithoutRevalidation()`. +`stale-if-error` and `stale-while-revalidate` extend the time to live of the cache, that can still be used if stale. + +### `toObject()`/`fromObject(json)` + +Chances are you'll want to store the `CachePolicy` object along with the cached response. `obj = policy.toObject()` gives a plain JSON-serializable object. `policy = CachePolicy.fromObject(obj)` creates an instance from it. + +### Refreshing stale cache (revalidation) + +When a cached response has expired, it can be made fresh again by making a request to the origin server. The server may respond with status 304 (Not Modified) without sending the response body again, saving bandwidth. + +The following methods help perform the update efficiently and correctly. + +#### `revalidationHeaders(newRequest)` + +Returns updated, filtered set of request headers to send to the origin server to check if the cached response can be reused. These headers allow the origin server to return status 304 indicating the response is still fresh. All headers unrelated to caching are passed through as-is. + +Use this method when updating cache from the origin server. + +```js +updateRequest.headers = cachePolicy.revalidationHeaders(updateRequest); +``` + +#### `revalidatedPolicy(revalidationRequest, revalidationResponse)` + +Use this method to update the cache after receiving a new response from the origin server. It returns an object with two keys: + +- `policy` — A new `CachePolicy` with HTTP headers updated from `revalidationResponse`. You can always replace the old cached `CachePolicy` with the new one. +- `modified` — Boolean indicating whether the response body has changed. + - If `false`, then a valid 304 Not Modified response has been received, and you can reuse the old cached response body. This is also affected by `stale-if-error`. + - If `true`, you should use new response's body (if present), or make another request to the origin server without any conditional headers (i.e. don't use `revalidationHeaders()` this time) to get the new resource. + +```js +// When serving requests from cache: +const { oldPolicy, oldResponse } = letsPretendThisIsSomeCache.get( + newRequest.url +); + +if (!oldPolicy.satisfiesWithoutRevalidation(newRequest)) { + // Change the request to ask the origin server if the cached response can be used + newRequest.headers = oldPolicy.revalidationHeaders(newRequest); + + // Send request to the origin server. The server may respond with status 304 + const newResponse = await makeRequest(newRequest); + + // Create updated policy and combined response from the old and new data + const { policy, modified } = oldPolicy.revalidatedPolicy( + newRequest, + newResponse + ); + const response = modified ? newResponse : oldResponse; + + // Update the cache with the newer/fresher response + letsPretendThisIsSomeCache.set( + newRequest.url, + { policy, response }, + policy.timeToLive() + ); + + // And proceed returning cached response as usual + response.headers = policy.responseHeaders(); + return response; +} +``` + +# Yo, FRESH + +![satisfiesWithoutRevalidation](fresh.jpg) + +## Used by + +- [ImageOptim API](https://imageoptim.com/api), [make-fetch-happen](https://github.com/zkat/make-fetch-happen), [cacheable-request](https://www.npmjs.com/package/cacheable-request) ([got](https://www.npmjs.com/package/got)), [npm/registry-fetch](https://github.com/npm/registry-fetch), [etc.](https://github.com/kornelski/http-cache-semantics/network/dependents) + +## Implemented + +- `Cache-Control` response header with all the quirks. +- `Expires` with check for bad clocks. +- `Pragma` response header. +- `Age` response header. +- `Vary` response header. +- Default cacheability of statuses and methods. +- Requests for stale data. +- Filtering of hop-by-hop headers. +- Basic revalidation request +- `stale-if-error` + +## Unimplemented + +- Merging of range requests, `If-Range` (but correctly supports them as non-cacheable) +- Revalidation of multiple representations + +### Trusting server `Date` + +Per the RFC, the cache should take into account the time between server-supplied `Date` and the time it received the response. The RFC-mandated behavior creates two problems: + + * Servers with incorrectly set timezone may add several hours to cache age (or more, if the clock is completely wrong). + * Even reasonably correct clocks may be off by a couple of seconds, breaking `max-age=1` trick (which is useful for reverse proxies on high-traffic servers). + +Previous versions of this library had an option to ignore the server date if it was "too inaccurate". To support the `max-age=1` trick the library also has to ignore dates that pretty accurate. There's no point of having an option to trust dates that are only a bit inaccurate, so this library won't trust any server dates. `max-age` will be interpreted from the time the response has been received, not from when it has been sent. This will affect only [RFC 1149 networks](https://tools.ietf.org/html/rfc1149). diff --git a/node_modules/http-cache-semantics/index.js b/node_modules/http-cache-semantics/index.js new file mode 100644 index 0000000..4f6c2f3 --- /dev/null +++ b/node_modules/http-cache-semantics/index.js @@ -0,0 +1,673 @@ +'use strict'; +// rfc7231 6.1 +const statusCodeCacheableByDefault = new Set([ + 200, + 203, + 204, + 206, + 300, + 301, + 404, + 405, + 410, + 414, + 501, +]); + +// This implementation does not understand partial responses (206) +const understoodStatuses = new Set([ + 200, + 203, + 204, + 300, + 301, + 302, + 303, + 307, + 308, + 404, + 405, + 410, + 414, + 501, +]); + +const errorStatusCodes = new Set([ + 500, + 502, + 503, + 504, +]); + +const hopByHopHeaders = { + date: true, // included, because we add Age update Date + connection: true, + 'keep-alive': true, + 'proxy-authenticate': true, + 'proxy-authorization': true, + te: true, + trailer: true, + 'transfer-encoding': true, + upgrade: true, +}; + +const excludedFromRevalidationUpdate = { + // Since the old body is reused, it doesn't make sense to change properties of the body + 'content-length': true, + 'content-encoding': true, + 'transfer-encoding': true, + 'content-range': true, +}; + +function toNumberOrZero(s) { + const n = parseInt(s, 10); + return isFinite(n) ? n : 0; +} + +// RFC 5861 +function isErrorResponse(response) { + // consider undefined response as faulty + if(!response) { + return true + } + return errorStatusCodes.has(response.status); +} + +function parseCacheControl(header) { + const cc = {}; + if (!header) return cc; + + // TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives), + // the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale + const parts = header.trim().split(/\s*,\s*/); // TODO: lame parsing + for (const part of parts) { + const [k, v] = part.split(/\s*=\s*/, 2); + cc[k] = v === undefined ? true : v.replace(/^"|"$/g, ''); // TODO: lame unquoting + } + + return cc; +} + +function formatCacheControl(cc) { + let parts = []; + for (const k in cc) { + const v = cc[k]; + parts.push(v === true ? k : k + '=' + v); + } + if (!parts.length) { + return undefined; + } + return parts.join(', '); +} + +module.exports = class CachePolicy { + constructor( + req, + res, + { + shared, + cacheHeuristic, + immutableMinTimeToLive, + ignoreCargoCult, + _fromObject, + } = {} + ) { + if (_fromObject) { + this._fromObject(_fromObject); + return; + } + + if (!res || !res.headers) { + throw Error('Response headers missing'); + } + this._assertRequestHasHeaders(req); + + this._responseTime = this.now(); + this._isShared = shared !== false; + this._cacheHeuristic = + undefined !== cacheHeuristic ? cacheHeuristic : 0.1; // 10% matches IE + this._immutableMinTtl = + undefined !== immutableMinTimeToLive + ? immutableMinTimeToLive + : 24 * 3600 * 1000; + + this._status = 'status' in res ? res.status : 200; + this._resHeaders = res.headers; + this._rescc = parseCacheControl(res.headers['cache-control']); + this._method = 'method' in req ? req.method : 'GET'; + this._url = req.url; + this._host = req.headers.host; + this._noAuthorization = !req.headers.authorization; + this._reqHeaders = res.headers.vary ? req.headers : null; // Don't keep all request headers if they won't be used + this._reqcc = parseCacheControl(req.headers['cache-control']); + + // Assume that if someone uses legacy, non-standard uncecessary options they don't understand caching, + // so there's no point stricly adhering to the blindly copy&pasted directives. + if ( + ignoreCargoCult && + 'pre-check' in this._rescc && + 'post-check' in this._rescc + ) { + delete this._rescc['pre-check']; + delete this._rescc['post-check']; + delete this._rescc['no-cache']; + delete this._rescc['no-store']; + delete this._rescc['must-revalidate']; + this._resHeaders = Object.assign({}, this._resHeaders, { + 'cache-control': formatCacheControl(this._rescc), + }); + delete this._resHeaders.expires; + delete this._resHeaders.pragma; + } + + // When the Cache-Control header field is not present in a request, caches MUST consider the no-cache request pragma-directive + // as having the same effect as if "Cache-Control: no-cache" were present (see Section 5.2.1). + if ( + res.headers['cache-control'] == null && + /no-cache/.test(res.headers.pragma) + ) { + this._rescc['no-cache'] = true; + } + } + + now() { + return Date.now(); + } + + storable() { + // The "no-store" request directive indicates that a cache MUST NOT store any part of either this request or any response to it. + return !!( + !this._reqcc['no-store'] && + // A cache MUST NOT store a response to any request, unless: + // The request method is understood by the cache and defined as being cacheable, and + ('GET' === this._method || + 'HEAD' === this._method || + ('POST' === this._method && this._hasExplicitExpiration())) && + // the response status code is understood by the cache, and + understoodStatuses.has(this._status) && + // the "no-store" cache directive does not appear in request or response header fields, and + !this._rescc['no-store'] && + // the "private" response directive does not appear in the response, if the cache is shared, and + (!this._isShared || !this._rescc.private) && + // the Authorization header field does not appear in the request, if the cache is shared, + (!this._isShared || + this._noAuthorization || + this._allowsStoringAuthenticated()) && + // the response either: + // contains an Expires header field, or + (this._resHeaders.expires || + // contains a max-age response directive, or + // contains a s-maxage response directive and the cache is shared, or + // contains a public response directive. + this._rescc['max-age'] || + (this._isShared && this._rescc['s-maxage']) || + this._rescc.public || + // has a status code that is defined as cacheable by default + statusCodeCacheableByDefault.has(this._status)) + ); + } + + _hasExplicitExpiration() { + // 4.2.1 Calculating Freshness Lifetime + return ( + (this._isShared && this._rescc['s-maxage']) || + this._rescc['max-age'] || + this._resHeaders.expires + ); + } + + _assertRequestHasHeaders(req) { + if (!req || !req.headers) { + throw Error('Request headers missing'); + } + } + + satisfiesWithoutRevalidation(req) { + this._assertRequestHasHeaders(req); + + // When presented with a request, a cache MUST NOT reuse a stored response, unless: + // the presented request does not contain the no-cache pragma (Section 5.4), nor the no-cache cache directive, + // unless the stored response is successfully validated (Section 4.3), and + const requestCC = parseCacheControl(req.headers['cache-control']); + if (requestCC['no-cache'] || /no-cache/.test(req.headers.pragma)) { + return false; + } + + if (requestCC['max-age'] && this.age() > requestCC['max-age']) { + return false; + } + + if ( + requestCC['min-fresh'] && + this.timeToLive() < 1000 * requestCC['min-fresh'] + ) { + return false; + } + + // the stored response is either: + // fresh, or allowed to be served stale + if (this.stale()) { + const allowsStale = + requestCC['max-stale'] && + !this._rescc['must-revalidate'] && + (true === requestCC['max-stale'] || + requestCC['max-stale'] > this.age() - this.maxAge()); + if (!allowsStale) { + return false; + } + } + + return this._requestMatches(req, false); + } + + _requestMatches(req, allowHeadMethod) { + // The presented effective request URI and that of the stored response match, and + return ( + (!this._url || this._url === req.url) && + this._host === req.headers.host && + // the request method associated with the stored response allows it to be used for the presented request, and + (!req.method || + this._method === req.method || + (allowHeadMethod && 'HEAD' === req.method)) && + // selecting header fields nominated by the stored response (if any) match those presented, and + this._varyMatches(req) + ); + } + + _allowsStoringAuthenticated() { + // following Cache-Control response directives (Section 5.2.2) have such an effect: must-revalidate, public, and s-maxage. + return ( + this._rescc['must-revalidate'] || + this._rescc.public || + this._rescc['s-maxage'] + ); + } + + _varyMatches(req) { + if (!this._resHeaders.vary) { + return true; + } + + // A Vary header field-value of "*" always fails to match + if (this._resHeaders.vary === '*') { + return false; + } + + const fields = this._resHeaders.vary + .trim() + .toLowerCase() + .split(/\s*,\s*/); + for (const name of fields) { + if (req.headers[name] !== this._reqHeaders[name]) return false; + } + return true; + } + + _copyWithoutHopByHopHeaders(inHeaders) { + const headers = {}; + for (const name in inHeaders) { + if (hopByHopHeaders[name]) continue; + headers[name] = inHeaders[name]; + } + // 9.1. Connection + if (inHeaders.connection) { + const tokens = inHeaders.connection.trim().split(/\s*,\s*/); + for (const name of tokens) { + delete headers[name]; + } + } + if (headers.warning) { + const warnings = headers.warning.split(/,/).filter(warning => { + return !/^\s*1[0-9][0-9]/.test(warning); + }); + if (!warnings.length) { + delete headers.warning; + } else { + headers.warning = warnings.join(',').trim(); + } + } + return headers; + } + + responseHeaders() { + const headers = this._copyWithoutHopByHopHeaders(this._resHeaders); + const age = this.age(); + + // A cache SHOULD generate 113 warning if it heuristically chose a freshness + // lifetime greater than 24 hours and the response's age is greater than 24 hours. + if ( + age > 3600 * 24 && + !this._hasExplicitExpiration() && + this.maxAge() > 3600 * 24 + ) { + headers.warning = + (headers.warning ? `${headers.warning}, ` : '') + + '113 - "rfc7234 5.5.4"'; + } + headers.age = `${Math.round(age)}`; + headers.date = new Date(this.now()).toUTCString(); + return headers; + } + + /** + * Value of the Date response header or current time if Date was invalid + * @return timestamp + */ + date() { + const serverDate = Date.parse(this._resHeaders.date); + if (isFinite(serverDate)) { + return serverDate; + } + return this._responseTime; + } + + /** + * Value of the Age header, in seconds, updated for the current time. + * May be fractional. + * + * @return Number + */ + age() { + let age = this._ageValue(); + + const residentTime = (this.now() - this._responseTime) / 1000; + return age + residentTime; + } + + _ageValue() { + return toNumberOrZero(this._resHeaders.age); + } + + /** + * Value of applicable max-age (or heuristic equivalent) in seconds. This counts since response's `Date`. + * + * For an up-to-date value, see `timeToLive()`. + * + * @return Number + */ + maxAge() { + if (!this.storable() || this._rescc['no-cache']) { + return 0; + } + + // Shared responses with cookies are cacheable according to the RFC, but IMHO it'd be unwise to do so by default + // so this implementation requires explicit opt-in via public header + if ( + this._isShared && + (this._resHeaders['set-cookie'] && + !this._rescc.public && + !this._rescc.immutable) + ) { + return 0; + } + + if (this._resHeaders.vary === '*') { + return 0; + } + + if (this._isShared) { + if (this._rescc['proxy-revalidate']) { + return 0; + } + // if a response includes the s-maxage directive, a shared cache recipient MUST ignore the Expires field. + if (this._rescc['s-maxage']) { + return toNumberOrZero(this._rescc['s-maxage']); + } + } + + // If a response includes a Cache-Control field with the max-age directive, a recipient MUST ignore the Expires field. + if (this._rescc['max-age']) { + return toNumberOrZero(this._rescc['max-age']); + } + + const defaultMinTtl = this._rescc.immutable ? this._immutableMinTtl : 0; + + const serverDate = this.date(); + if (this._resHeaders.expires) { + const expires = Date.parse(this._resHeaders.expires); + // A cache recipient MUST interpret invalid date formats, especially the value "0", as representing a time in the past (i.e., "already expired"). + if (Number.isNaN(expires) || expires < serverDate) { + return 0; + } + return Math.max(defaultMinTtl, (expires - serverDate) / 1000); + } + + if (this._resHeaders['last-modified']) { + const lastModified = Date.parse(this._resHeaders['last-modified']); + if (isFinite(lastModified) && serverDate > lastModified) { + return Math.max( + defaultMinTtl, + ((serverDate - lastModified) / 1000) * this._cacheHeuristic + ); + } + } + + return defaultMinTtl; + } + + timeToLive() { + const age = this.maxAge() - this.age(); + const staleIfErrorAge = age + toNumberOrZero(this._rescc['stale-if-error']); + const staleWhileRevalidateAge = age + toNumberOrZero(this._rescc['stale-while-revalidate']); + return Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1000; + } + + stale() { + return this.maxAge() <= this.age(); + } + + _useStaleIfError() { + return this.maxAge() + toNumberOrZero(this._rescc['stale-if-error']) > this.age(); + } + + useStaleWhileRevalidate() { + return this.maxAge() + toNumberOrZero(this._rescc['stale-while-revalidate']) > this.age(); + } + + static fromObject(obj) { + return new this(undefined, undefined, { _fromObject: obj }); + } + + _fromObject(obj) { + if (this._responseTime) throw Error('Reinitialized'); + if (!obj || obj.v !== 1) throw Error('Invalid serialization'); + + this._responseTime = obj.t; + this._isShared = obj.sh; + this._cacheHeuristic = obj.ch; + this._immutableMinTtl = + obj.imm !== undefined ? obj.imm : 24 * 3600 * 1000; + this._status = obj.st; + this._resHeaders = obj.resh; + this._rescc = obj.rescc; + this._method = obj.m; + this._url = obj.u; + this._host = obj.h; + this._noAuthorization = obj.a; + this._reqHeaders = obj.reqh; + this._reqcc = obj.reqcc; + } + + toObject() { + return { + v: 1, + t: this._responseTime, + sh: this._isShared, + ch: this._cacheHeuristic, + imm: this._immutableMinTtl, + st: this._status, + resh: this._resHeaders, + rescc: this._rescc, + m: this._method, + u: this._url, + h: this._host, + a: this._noAuthorization, + reqh: this._reqHeaders, + reqcc: this._reqcc, + }; + } + + /** + * Headers for sending to the origin server to revalidate stale response. + * Allows server to return 304 to allow reuse of the previous response. + * + * Hop by hop headers are always stripped. + * Revalidation headers may be added or removed, depending on request. + */ + revalidationHeaders(incomingReq) { + this._assertRequestHasHeaders(incomingReq); + const headers = this._copyWithoutHopByHopHeaders(incomingReq.headers); + + // This implementation does not understand range requests + delete headers['if-range']; + + if (!this._requestMatches(incomingReq, true) || !this.storable()) { + // revalidation allowed via HEAD + // not for the same resource, or wasn't allowed to be cached anyway + delete headers['if-none-match']; + delete headers['if-modified-since']; + return headers; + } + + /* MUST send that entity-tag in any cache validation request (using If-Match or If-None-Match) if an entity-tag has been provided by the origin server. */ + if (this._resHeaders.etag) { + headers['if-none-match'] = headers['if-none-match'] + ? `${headers['if-none-match']}, ${this._resHeaders.etag}` + : this._resHeaders.etag; + } + + // Clients MAY issue simple (non-subrange) GET requests with either weak validators or strong validators. Clients MUST NOT use weak validators in other forms of request. + const forbidsWeakValidators = + headers['accept-ranges'] || + headers['if-match'] || + headers['if-unmodified-since'] || + (this._method && this._method != 'GET'); + + /* SHOULD send the Last-Modified value in non-subrange cache validation requests (using If-Modified-Since) if only a Last-Modified value has been provided by the origin server. + Note: This implementation does not understand partial responses (206) */ + if (forbidsWeakValidators) { + delete headers['if-modified-since']; + + if (headers['if-none-match']) { + const etags = headers['if-none-match'] + .split(/,/) + .filter(etag => { + return !/^\s*W\//.test(etag); + }); + if (!etags.length) { + delete headers['if-none-match']; + } else { + headers['if-none-match'] = etags.join(',').trim(); + } + } + } else if ( + this._resHeaders['last-modified'] && + !headers['if-modified-since'] + ) { + headers['if-modified-since'] = this._resHeaders['last-modified']; + } + + return headers; + } + + /** + * Creates new CachePolicy with information combined from the previews response, + * and the new revalidation response. + * + * Returns {policy, modified} where modified is a boolean indicating + * whether the response body has been modified, and old cached body can't be used. + * + * @return {Object} {policy: CachePolicy, modified: Boolean} + */ + revalidatedPolicy(request, response) { + this._assertRequestHasHeaders(request); + if(this._useStaleIfError() && isErrorResponse(response)) { // I consider the revalidation request unsuccessful + return { + modified: false, + matches: false, + policy: this, + }; + } + if (!response || !response.headers) { + throw Error('Response headers missing'); + } + + // These aren't going to be supported exactly, since one CachePolicy object + // doesn't know about all the other cached objects. + let matches = false; + if (response.status !== undefined && response.status != 304) { + matches = false; + } else if ( + response.headers.etag && + !/^\s*W\//.test(response.headers.etag) + ) { + // "All of the stored responses with the same strong validator are selected. + // If none of the stored responses contain the same strong validator, + // then the cache MUST NOT use the new response to update any stored responses." + matches = + this._resHeaders.etag && + this._resHeaders.etag.replace(/^\s*W\//, '') === + response.headers.etag; + } else if (this._resHeaders.etag && response.headers.etag) { + // "If the new response contains a weak validator and that validator corresponds + // to one of the cache's stored responses, + // then the most recent of those matching stored responses is selected for update." + matches = + this._resHeaders.etag.replace(/^\s*W\//, '') === + response.headers.etag.replace(/^\s*W\//, ''); + } else if (this._resHeaders['last-modified']) { + matches = + this._resHeaders['last-modified'] === + response.headers['last-modified']; + } else { + // If the new response does not include any form of validator (such as in the case where + // a client generates an If-Modified-Since request from a source other than the Last-Modified + // response header field), and there is only one stored response, and that stored response also + // lacks a validator, then that stored response is selected for update. + if ( + !this._resHeaders.etag && + !this._resHeaders['last-modified'] && + !response.headers.etag && + !response.headers['last-modified'] + ) { + matches = true; + } + } + + if (!matches) { + return { + policy: new this.constructor(request, response), + // Client receiving 304 without body, even if it's invalid/mismatched has no option + // but to reuse a cached body. We don't have a good way to tell clients to do + // error recovery in such case. + modified: response.status != 304, + matches: false, + }; + } + + // use other header fields provided in the 304 (Not Modified) response to replace all instances + // of the corresponding header fields in the stored response. + const headers = {}; + for (const k in this._resHeaders) { + headers[k] = + k in response.headers && !excludedFromRevalidationUpdate[k] + ? response.headers[k] + : this._resHeaders[k]; + } + + const newResponse = Object.assign({}, response, { + status: this._status, + method: this._method, + headers, + }); + return { + policy: new this.constructor(request, newResponse, { + shared: this._isShared, + cacheHeuristic: this._cacheHeuristic, + immutableMinTimeToLive: this._immutableMinTtl, + }), + modified: false, + matches: true, + }; + } +}; diff --git a/node_modules/http-cache-semantics/package.json b/node_modules/http-cache-semantics/package.json new file mode 100644 index 0000000..897798d --- /dev/null +++ b/node_modules/http-cache-semantics/package.json @@ -0,0 +1,24 @@ +{ + "name": "http-cache-semantics", + "version": "4.1.0", + "description": "Parses Cache-Control and other headers. Helps building correct HTTP caches and proxies", + "repository": "https://github.com/kornelski/http-cache-semantics.git", + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "files": [ + "index.js" + ], + "author": "Kornel Lesiński (https://kornel.ski/)", + "license": "BSD-2-Clause", + "devDependencies": { + "eslint": "^5.13.0", + "eslint-plugin-prettier": "^3.0.1", + "husky": "^0.14.3", + "lint-staged": "^8.1.3", + "mocha": "^5.1.0", + "prettier": "^1.14.3", + "prettier-eslint-cli": "^4.7.1" + } +} diff --git a/node_modules/http2-wrapper/LICENSE b/node_modules/http2-wrapper/LICENSE new file mode 100644 index 0000000..15ad2e8 --- /dev/null +++ b/node_modules/http2-wrapper/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Szymon Marczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/http2-wrapper/README.md b/node_modules/http2-wrapper/README.md new file mode 100644 index 0000000..09b5f48 --- /dev/null +++ b/node_modules/http2-wrapper/README.md @@ -0,0 +1,470 @@ +# http2-wrapper +> HTTP/2 client, just with the familiar `https` API + +[![Node CI](https://github.com/szmarczak/http2-wrapper/workflows/Node%20CI/badge.svg)](https://github.com/szmarczak/http2-wrapper/actions) +[![codecov](https://codecov.io/gh/szmarczak/http2-wrapper/branch/master/graph/badge.svg)](https://codecov.io/gh/szmarczak/http2-wrapper) +[![npm](https://img.shields.io/npm/dm/http2-wrapper.svg)](https://www.npmjs.com/package/http2-wrapper) +[![install size](https://packagephobia.now.sh/badge?p=http2-wrapper)](https://packagephobia.now.sh/result?p=http2-wrapper) + +This package was created to support HTTP/2 without the need to rewrite your code.
+I recommend adapting to the [`http2`](https://nodejs.org/api/http2.html) module if possible - it's much simpler to use and has many cool features! + +**Tip**: `http2-wrapper` is very useful when you rely on other modules that use the HTTP/1 API and you want to support HTTP/2. + +**Pro Tip**: While the native `http2` doesn't have agents yet, you can use `http2-wrapper` Agents and still operate on the native HTTP/2 streams. + +## Installation + +> `$ npm install http2-wrapper`
+> `$ yarn add http2-wrapper` + +## Usage +```js +const http2 = require('http2-wrapper'); + +const options = { + hostname: 'nghttp2.org', + protocol: 'https:', + path: '/httpbin/post', + method: 'POST', + headers: { + 'content-length': 6 + } +}; + +const request = http2.request(options, response => { + console.log('statusCode:', response.statusCode); + console.log('headers:', response.headers); + + const body = []; + response.on('data', chunk => { + body.push(chunk); + }); + response.on('end', () => { + console.log('body:', Buffer.concat(body).toString()); + }); +}); + +request.on('error', console.error); + +request.write('123'); +request.end('456'); + +// statusCode: 200 +// headers: [Object: null prototype] { +// ':status': 200, +// date: 'Fri, 27 Sep 2019 19:45:46 GMT', +// 'content-type': 'application/json', +// 'access-control-allow-origin': '*', +// 'access-control-allow-credentials': 'true', +// 'content-length': '239', +// 'x-backend-header-rtt': '0.002516', +// 'strict-transport-security': 'max-age=31536000', +// server: 'nghttpx', +// via: '1.1 nghttpx', +// 'alt-svc': 'h3-23=":4433"; ma=3600', +// 'x-frame-options': 'SAMEORIGIN', +// 'x-xss-protection': '1; mode=block', +// 'x-content-type-options': 'nosniff' +// } +// body: { +// "args": {}, +// "data": "123456", +// "files": {}, +// "form": {}, +// "headers": { +// "Content-Length": "6", +// "Host": "nghttp2.org" +// }, +// "json": 123456, +// "origin": "xxx.xxx.xxx.xxx", +// "url": "https://nghttp2.org/httpbin/post" +// } +``` + +## API + +**Note:** The `session` option was renamed to `tlsSession` for better readability. + +### http2.auto(url, options, callback) + +Performs [ALPN](https://nodejs.org/api/tls.html#tls_alpn_and_sni) negotiation. +Returns a Promise giving proper `ClientRequest` instance (depending on the ALPN). + +**Note**: The `agent` option represents an object with `http`, `https` and `http2` properties. + +```js +const http2 = require('http2-wrapper'); + +const options = { + hostname: 'httpbin.org', + protocol: 'http:', // Note the `http:` protocol here + path: '/post', + method: 'POST', + headers: { + 'content-length': 6 + } +}; + +(async () => { + try { + const request = await http2.auto(options, response => { + console.log('statusCode:', response.statusCode); + console.log('headers:', response.headers); + + const body = []; + response.on('data', chunk => body.push(chunk)); + response.on('end', () => { + console.log('body:', Buffer.concat(body).toString()); + }); + }); + + request.on('error', console.error); + + request.write('123'); + request.end('456'); + } catch (error) { + console.error(error); + } +})(); + +// statusCode: 200 +// headers: { connection: 'close', +// server: 'gunicorn/19.9.0', +// date: 'Sat, 15 Dec 2018 18:19:32 GMT', +// 'content-type': 'application/json', +// 'content-length': '259', +// 'access-control-allow-origin': '*', +// 'access-control-allow-credentials': 'true', +// via: '1.1 vegur' } +// body: { +// "args": {}, +// "data": "123456", +// "files": {}, +// "form": {}, +// "headers": { +// "Connection": "close", +// "Content-Length": "6", +// "Host": "httpbin.org" +// }, +// "json": 123456, +// "origin": "xxx.xxx.xxx.xxx", +// "url": "http://httpbin.org/post" +// } +``` + +### http2.auto.protocolCache + +An instance of [`quick-lru`](https://github.com/sindresorhus/quick-lru) used for ALPN cache. + +There is a maximum of 100 entries. You can modify the limit through `protocolCache.maxSize` - note that the change will be visible globally. + +### http2.request(url, options, callback) + +Same as [`https.request`](https://nodejs.org/api/https.html#https_https_request_options_callback). + +##### options.h2session + +Type: `Http2Session`
+ +The session used to make the actual request. If none provided, it will use `options.agent`. + +### http2.get(url, options, callback) + +Same as [`https.get`](https://nodejs.org/api/https.html#https_https_get_options_callback). + +### new http2.ClientRequest(url, options, callback) + +Same as [`https.ClientRequest`](https://nodejs.org/api/https.html#https_class_https_clientrequest). + +### new http2.IncomingMessage(socket) + +Same as [`https.IncomingMessage`](https://nodejs.org/api/https.html#https_class_https_incomingmessage). + +### new http2.Agent(options) + +**Note:** this is **not** compatible with the classic `http.Agent`. + +Usage example: + +```js +const http2 = require('http2-wrapper'); + +class MyAgent extends http2.Agent { + createConnection(origin, options) { + console.log(`Connecting to ${http2.Agent.normalizeOrigin(origin)}`); + return http2.Agent.connect(origin, options); + } +} + +http2.get({ + hostname: 'google.com', + agent: new MyAgent() +}, res => { + res.on('data', chunk => console.log(`Received chunk of ${chunk.length} bytes`)); +}); +``` + +#### options + +Each option is assigned to each `Agent` instance and can be changed later. + +##### timeout + +Type: `number`
+Default: `60000` + +If there's no activity after `timeout` milliseconds, the session will be closed. + +##### maxSessions + +Type: `number`
+Default: `Infinity` + +The maximum amount of sessions in total. + +##### maxFreeSessions + +Type: `number`
+Default: `10` + +The maximum amount of free sessions in total. This only applies to sessions with no pending requests. + +**Note:** It is possible that the amount will be exceeded when sessions have at least 1 pending request. + +##### maxCachedTlsSessions + +Type: `number`
+Default: `100` + +The maximum amount of cached TLS sessions. + +#### Agent.normalizeOrigin(url) + +Returns a string representing the origin of the URL. + +#### agent.settings + +Type: `object`
+Default: `{enablePush: false}` + +[Settings](https://nodejs.org/api/http2.html#http2_settings_object) used by the current agent instance. + +#### agent.normalizeOptions([options](https://github.com/szmarczak/http2-wrapper/blob/master/source/agent.js)) + +Returns a string representing normalized options. + +```js +Agent.normalizeOptions({servername: 'example.com'}); +// => ':example.com' +``` + +#### agent.getSession(origin, options) + +##### [origin](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener) + +Type: `string` `URL` `object` + +An origin used to create new session. + +##### [options](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener) + +Type: `object` + +The options used to create new session. + +Returns a Promise giving free `Http2Session`. If no free sessions are found, a new one is created. + +#### agent.getSession([origin](#origin), [options](options-1), listener) + +##### listener + +Type: `object` + +``` +{ + reject: error => void, + resolve: session => void +} +``` + +If the `listener` argument is present, the Promise will resolve immediately. It will use the `resolve` function to pass the session. + +#### agent.request([origin](#origin), [options](#options-1), [headers](https://nodejs.org/api/http2.html#http2_headers_object), [streamOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)) + +Returns a Promise giving `Http2Stream`. + +#### agent.createConnection([origin](#origin), [options](#options-1)) + +Returns a new `TLSSocket`. It defaults to `Agent.connect(origin, options)`. + +#### agent.closeFreeSessions() + +Makes an attempt to close free sessions. Only sessions with 0 concurrent streams will be closed. + +#### agent.destroy(reason) + +Destroys **all** sessions. + +#### Event: 'session' + +```js +agent.on('session', session => { + // A new session has been created by the Agent. +}); +``` + +## Proxy support + +An example of a full-featured proxy server can be found [here](examples/proxy/server.js). It supports **mirroring, custom authorities and the CONNECT protocol**. + +### Mirroring + +To mirror another server we need to use only [`http2-proxy`](https://github.com/nxtedition/node-http2-proxy). We don't need the CONNECT protocol or custom authorities. + +To see the result, just navigate to the server's address. + +### HTTP/1 over HTTP/2 + +Since we don't care about mirroring, the server needs to support the CONNECT protocol in this case. + +The client looks like this: + +```js +const https = require('https'); +const http2 = require('http2'); + +const session = http2.connect('https://localhost:8000', { + // For demo purposes only! + rejectUnauthorized: false +}); + +session.ref(); + +https.request('https://httpbin.org/anything', { + createConnection: options => { + return session.request({ + ':method': 'CONNECT', + ':authority': `${options.host}:${options.port}` + }); + } +}, response => { + console.log('statusCode:', response.statusCode); + console.log('headers:', response.headers); + + const body = []; + response.on('data', chunk => { + body.push(chunk); + }); + response.on('end', () => { + console.log('body:', Buffer.concat(body).toString()); + + session.unref(); + }); +}).end(); +``` + +### HTTP/2 over HTTP/2 + +It's a tricky one! We cannot create an HTTP/2 session on top of an HTTP/2 stream. But... we can still specify the `:authority` header, no need to use the CONNECT protocol here. + +The client looks like this: + +```js +const http2 = require('../../source'); +const {Agent} = http2; + +class ProxyAgent extends Agent { + constructor(url, options) { + super(options); + + this.origin = url; + } + + request(origin, sessionOptions, headers, streamOptions) { + return super.request(this.origin, sessionOptions, { + ...headers, + ':authority': (new URL(origin)).host + }, streamOptions); + } +} + +const request = http2.request({ + hostname: 'httpbin.org', + protocol: 'https:', + path: '/anything', + agent: new ProxyAgent('https://localhost:8000'), + // For demo purposes only! + rejectUnauthorized: false +}, response => { + console.log('statusCode:', response.statusCode); + console.log('headers:', response.headers); + + const body = []; + response.on('data', chunk => { + body.push(chunk); + }); + response.on('end', () => { + console.log('body:', Buffer.concat(body).toString()); + }); +}); + +request.on('error', console.error); + +request.end(); +``` + +## Notes + + - If you're interested in [WebSockets over HTTP/2](https://tools.ietf.org/html/rfc8441), then [check out this discussion](https://github.com/websockets/ws/issues/1458). + - [HTTP/2 sockets cannot be malformed](https://github.com/nodejs/node/blob/cc8250fab86486632fdeb63892be735d7628cd13/lib/internal/http2/core.js#L725), therefore modifying the socket will have no effect. + - You can make [a custom Agent](examples/push-stream/index.js) to support push streams. + +## Benchmarks + +CPU: Intel i7-7700k (governor: performance)
+Server: H2O v2.2.5 [`h2o.conf`](h2o.conf)
+Node: v14.5.0 +Linux: 5.6.18-156.current + +`auto` means `http2wrapper.auto`. + +``` +http2-wrapper x 12,181 ops/sec ±3.39% (75 runs sampled) +http2-wrapper - preconfigured session x 13,140 ops/sec ±2.51% (79 runs sampled) +http2-wrapper - auto x 11,412 ops/sec ±2.55% (78 runs sampled) +http2 x 16,050 ops/sec ±1.39% (86 runs sampled) +https - auto - keepalive x 12,288 ops/sec ±2.69% (79 runs sampled) +https - keepalive x 12,155 ops/sec ±3.32% (78 runs sampled) +https x 1,604 ops/sec ±2.03% (77 runs sampled) +http x 6,041 ops/sec ±3.82% (76 runs sampled) +Fastest is http2 +``` + +`http2-wrapper`: +- 32% **less** performant than `http2` +- as performant as `https - keepalive` +- 100% **more** performant than `http` + +`http2-wrapper - preconfigured session`: +- 22% **less** performant than `http2` +- 8% **more** performant than `https - keepalive` +- 118% **more** performant than `http` + +`http2-wrapper - auto`: +- 41% **less** performant than `http2` +- 8% **less** performant than `https - keepalive` +- 89% **more** performant than `http` + +`https - auto - keepalive`: +- 31% **less** performant than `http2` +- as performant as `https - keepalive` +- 103% **more** performant than `http` + +## Related + + - [`got`](https://github.com/sindresorhus/got) - Simplified HTTP requests + +## License + +MIT diff --git a/node_modules/http2-wrapper/package.json b/node_modules/http2-wrapper/package.json new file mode 100644 index 0000000..d47894f --- /dev/null +++ b/node_modules/http2-wrapper/package.json @@ -0,0 +1,54 @@ +{ + "name": "http2-wrapper", + "version": "1.0.3", + "description": "HTTP2 client, just with the familiar `https` API", + "main": "source", + "engines": { + "node": ">=10.19.0" + }, + "scripts": { + "test": "xo && nyc --reporter=lcovonly --reporter=text --reporter=html ava" + }, + "files": [ + "source" + ], + "keywords": [ + "http2", + "https", + "http", + "request" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/szmarczak/http2-wrapper.git" + }, + "author": "Szymon Marczak", + "license": "MIT", + "bugs": { + "url": "https://github.com/szmarczak/http2-wrapper/issues" + }, + "homepage": "https://github.com/szmarczak/http2-wrapper#readme", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "devDependencies": { + "@sindresorhus/is": "^3.0.0", + "ava": "^3.10.1", + "benchmark": "^2.1.4", + "get-stream": "^5.1.0", + "got": "^11.5.0", + "http2-proxy": "^5.0.51", + "lolex": "^6.0.0", + "many-keys-map": "^1.0.2", + "nyc": "^15.1.0", + "p-event": "^4.2.0", + "tempy": "^0.5.0", + "to-readable-stream": "^2.1.0", + "tsd": "^0.13.1", + "xo": "^0.32.1" + }, + "ava": { + "timeout": "2m" + } +} diff --git a/node_modules/http2-wrapper/source/agent.js b/node_modules/http2-wrapper/source/agent.js new file mode 100644 index 0000000..b2b1cff --- /dev/null +++ b/node_modules/http2-wrapper/source/agent.js @@ -0,0 +1,670 @@ +'use strict'; +const EventEmitter = require('events'); +const tls = require('tls'); +const http2 = require('http2'); +const QuickLRU = require('quick-lru'); + +const kCurrentStreamsCount = Symbol('currentStreamsCount'); +const kRequest = Symbol('request'); +const kOriginSet = Symbol('cachedOriginSet'); +const kGracefullyClosing = Symbol('gracefullyClosing'); + +const nameKeys = [ + // `http2.connect()` options + 'maxDeflateDynamicTableSize', + 'maxSessionMemory', + 'maxHeaderListPairs', + 'maxOutstandingPings', + 'maxReservedRemoteStreams', + 'maxSendHeaderBlockLength', + 'paddingStrategy', + + // `tls.connect()` options + 'localAddress', + 'path', + 'rejectUnauthorized', + 'minDHSize', + + // `tls.createSecureContext()` options + 'ca', + 'cert', + 'clientCertEngine', + 'ciphers', + 'key', + 'pfx', + 'servername', + 'minVersion', + 'maxVersion', + 'secureProtocol', + 'crl', + 'honorCipherOrder', + 'ecdhCurve', + 'dhparam', + 'secureOptions', + 'sessionIdContext' +]; + +const getSortedIndex = (array, value, compare) => { + let low = 0; + let high = array.length; + + while (low < high) { + const mid = (low + high) >>> 1; + + /* istanbul ignore next */ + if (compare(array[mid], value)) { + // This never gets called because we use descending sort. Better to have this anyway. + low = mid + 1; + } else { + high = mid; + } + } + + return low; +}; + +const compareSessions = (a, b) => { + return a.remoteSettings.maxConcurrentStreams > b.remoteSettings.maxConcurrentStreams; +}; + +// See https://tools.ietf.org/html/rfc8336 +const closeCoveredSessions = (where, session) => { + // Clients SHOULD NOT emit new requests on any connection whose Origin + // Set is a proper subset of another connection's Origin Set, and they + // SHOULD close it once all outstanding requests are satisfied. + for (const coveredSession of where) { + if ( + // The set is a proper subset when its length is less than the other set. + coveredSession[kOriginSet].length < session[kOriginSet].length && + + // And the other set includes all elements of the subset. + coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) && + + // Makes sure that the session can handle all requests from the covered session. + coveredSession[kCurrentStreamsCount] + session[kCurrentStreamsCount] <= session.remoteSettings.maxConcurrentStreams + ) { + // This allows pending requests to finish and prevents making new requests. + gracefullyClose(coveredSession); + } + } +}; + +// This is basically inverted `closeCoveredSessions(...)`. +const closeSessionIfCovered = (where, coveredSession) => { + for (const session of where) { + if ( + coveredSession[kOriginSet].length < session[kOriginSet].length && + coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) && + coveredSession[kCurrentStreamsCount] + session[kCurrentStreamsCount] <= session.remoteSettings.maxConcurrentStreams + ) { + gracefullyClose(coveredSession); + } + } +}; + +const getSessions = ({agent, isFree}) => { + const result = {}; + + // eslint-disable-next-line guard-for-in + for (const normalizedOptions in agent.sessions) { + const sessions = agent.sessions[normalizedOptions]; + + const filtered = sessions.filter(session => { + const result = session[Agent.kCurrentStreamsCount] < session.remoteSettings.maxConcurrentStreams; + + return isFree ? result : !result; + }); + + if (filtered.length !== 0) { + result[normalizedOptions] = filtered; + } + } + + return result; +}; + +const gracefullyClose = session => { + session[kGracefullyClosing] = true; + + if (session[kCurrentStreamsCount] === 0) { + session.close(); + } +}; + +class Agent extends EventEmitter { + constructor({timeout = 60000, maxSessions = Infinity, maxFreeSessions = 10, maxCachedTlsSessions = 100} = {}) { + super(); + + // A session is considered busy when its current streams count + // is equal to or greater than the `maxConcurrentStreams` value. + + // A session is considered free when its current streams count + // is less than the `maxConcurrentStreams` value. + + // SESSIONS[NORMALIZED_OPTIONS] = []; + this.sessions = {}; + + // The queue for creating new sessions. It looks like this: + // QUEUE[NORMALIZED_OPTIONS][NORMALIZED_ORIGIN] = ENTRY_FUNCTION + // + // The entry function has `listeners`, `completed` and `destroyed` properties. + // `listeners` is an array of objects containing `resolve` and `reject` functions. + // `completed` is a boolean. It's set to true after ENTRY_FUNCTION is executed. + // `destroyed` is a boolean. If it's set to true, the session will be destroyed if hasn't connected yet. + this.queue = {}; + + // Each session will use this timeout value. + this.timeout = timeout; + + // Max sessions in total + this.maxSessions = maxSessions; + + // Max free sessions in total + // TODO: decreasing `maxFreeSessions` should close some sessions + this.maxFreeSessions = maxFreeSessions; + + this._freeSessionsCount = 0; + this._sessionsCount = 0; + + // We don't support push streams by default. + this.settings = { + enablePush: false + }; + + // Reusing TLS sessions increases performance. + this.tlsSessionCache = new QuickLRU({maxSize: maxCachedTlsSessions}); + } + + static normalizeOrigin(url, servername) { + if (typeof url === 'string') { + url = new URL(url); + } + + if (servername && url.hostname !== servername) { + url.hostname = servername; + } + + return url.origin; + } + + normalizeOptions(options) { + let normalized = ''; + + if (options) { + for (const key of nameKeys) { + if (options[key]) { + normalized += `:${options[key]}`; + } + } + } + + return normalized; + } + + _tryToCreateNewSession(normalizedOptions, normalizedOrigin) { + if (!(normalizedOptions in this.queue) || !(normalizedOrigin in this.queue[normalizedOptions])) { + return; + } + + const item = this.queue[normalizedOptions][normalizedOrigin]; + + // The entry function can be run only once. + // BUG: The session may be never created when: + // - the first condition is false AND + // - this function is never called with the same arguments in the future. + if (this._sessionsCount < this.maxSessions && !item.completed) { + item.completed = true; + + item(); + } + } + + getSession(origin, options, listeners) { + return new Promise((resolve, reject) => { + if (Array.isArray(listeners)) { + listeners = [...listeners]; + + // Resolve the current promise ASAP, we're just moving the listeners. + // They will be executed at a different time. + resolve(); + } else { + listeners = [{resolve, reject}]; + } + + const normalizedOptions = this.normalizeOptions(options); + const normalizedOrigin = Agent.normalizeOrigin(origin, options && options.servername); + + if (normalizedOrigin === undefined) { + for (const {reject} of listeners) { + reject(new TypeError('The `origin` argument needs to be a string or an URL object')); + } + + return; + } + + if (normalizedOptions in this.sessions) { + const sessions = this.sessions[normalizedOptions]; + + let maxConcurrentStreams = -1; + let currentStreamsCount = -1; + let optimalSession; + + // We could just do this.sessions[normalizedOptions].find(...) but that isn't optimal. + // Additionally, we are looking for session which has biggest current pending streams count. + for (const session of sessions) { + const sessionMaxConcurrentStreams = session.remoteSettings.maxConcurrentStreams; + + if (sessionMaxConcurrentStreams < maxConcurrentStreams) { + break; + } + + if (session[kOriginSet].includes(normalizedOrigin)) { + const sessionCurrentStreamsCount = session[kCurrentStreamsCount]; + + if ( + sessionCurrentStreamsCount >= sessionMaxConcurrentStreams || + session[kGracefullyClosing] || + // Unfortunately the `close` event isn't called immediately, + // so `session.destroyed` is `true`, but `session.closed` is `false`. + session.destroyed + ) { + continue; + } + + // We only need set this once. + if (!optimalSession) { + maxConcurrentStreams = sessionMaxConcurrentStreams; + } + + // We're looking for the session which has biggest current pending stream count, + // in order to minimalize the amount of active sessions. + if (sessionCurrentStreamsCount > currentStreamsCount) { + optimalSession = session; + currentStreamsCount = sessionCurrentStreamsCount; + } + } + } + + if (optimalSession) { + /* istanbul ignore next: safety check */ + if (listeners.length !== 1) { + for (const {reject} of listeners) { + const error = new Error( + `Expected the length of listeners to be 1, got ${listeners.length}.\n` + + 'Please report this to https://github.com/szmarczak/http2-wrapper/' + ); + + reject(error); + } + + return; + } + + listeners[0].resolve(optimalSession); + return; + } + } + + if (normalizedOptions in this.queue) { + if (normalizedOrigin in this.queue[normalizedOptions]) { + // There's already an item in the queue, just attach ourselves to it. + this.queue[normalizedOptions][normalizedOrigin].listeners.push(...listeners); + + // This shouldn't be executed here. + // See the comment inside _tryToCreateNewSession. + this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); + return; + } + } else { + this.queue[normalizedOptions] = {}; + } + + // The entry must be removed from the queue IMMEDIATELY when: + // 1. the session connects successfully, + // 2. an error occurs. + const removeFromQueue = () => { + // Our entry can be replaced. We cannot remove the new one. + if (normalizedOptions in this.queue && this.queue[normalizedOptions][normalizedOrigin] === entry) { + delete this.queue[normalizedOptions][normalizedOrigin]; + + if (Object.keys(this.queue[normalizedOptions]).length === 0) { + delete this.queue[normalizedOptions]; + } + } + }; + + // The main logic is here + const entry = () => { + const name = `${normalizedOrigin}:${normalizedOptions}`; + let receivedSettings = false; + + try { + const session = http2.connect(origin, { + createConnection: this.createConnection, + settings: this.settings, + session: this.tlsSessionCache.get(name), + ...options + }); + session[kCurrentStreamsCount] = 0; + session[kGracefullyClosing] = false; + + const isFree = () => session[kCurrentStreamsCount] < session.remoteSettings.maxConcurrentStreams; + let wasFree = true; + + session.socket.once('session', tlsSession => { + this.tlsSessionCache.set(name, tlsSession); + }); + + session.once('error', error => { + // Listeners are empty when the session successfully connected. + for (const {reject} of listeners) { + reject(error); + } + + // The connection got broken, purge the cache. + this.tlsSessionCache.delete(name); + }); + + session.setTimeout(this.timeout, () => { + // Terminates all streams owned by this session. + // TODO: Maybe the streams should have a "Session timed out" error? + session.destroy(); + }); + + session.once('close', () => { + if (receivedSettings) { + // 1. If it wasn't free then no need to decrease because + // it has been decreased already in session.request(). + // 2. `stream.once('close')` won't increment the count + // because the session is already closed. + if (wasFree) { + this._freeSessionsCount--; + } + + this._sessionsCount--; + + // This cannot be moved to the stream logic, + // because there may be a session that hadn't made a single request. + const where = this.sessions[normalizedOptions]; + where.splice(where.indexOf(session), 1); + + if (where.length === 0) { + delete this.sessions[normalizedOptions]; + } + } else { + // Broken connection + const error = new Error('Session closed without receiving a SETTINGS frame'); + error.code = 'HTTP2WRAPPER_NOSETTINGS'; + + for (const {reject} of listeners) { + reject(error); + } + + removeFromQueue(); + } + + // There may be another session awaiting. + this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); + }); + + // Iterates over the queue and processes listeners. + const processListeners = () => { + if (!(normalizedOptions in this.queue) || !isFree()) { + return; + } + + for (const origin of session[kOriginSet]) { + if (origin in this.queue[normalizedOptions]) { + const {listeners} = this.queue[normalizedOptions][origin]; + + // Prevents session overloading. + while (listeners.length !== 0 && isFree()) { + // We assume `resolve(...)` calls `request(...)` *directly*, + // otherwise the session will get overloaded. + listeners.shift().resolve(session); + } + + const where = this.queue[normalizedOptions]; + if (where[origin].listeners.length === 0) { + delete where[origin]; + + if (Object.keys(where).length === 0) { + delete this.queue[normalizedOptions]; + break; + } + } + + // We're no longer free, no point in continuing. + if (!isFree()) { + break; + } + } + } + }; + + // The Origin Set cannot shrink. No need to check if it suddenly became covered by another one. + session.on('origin', () => { + session[kOriginSet] = session.originSet; + + if (!isFree()) { + // The session is full. + return; + } + + processListeners(); + + // Close covered sessions (if possible). + closeCoveredSessions(this.sessions[normalizedOptions], session); + }); + + session.once('remoteSettings', () => { + // Fix Node.js bug preventing the process from exiting + session.ref(); + session.unref(); + + this._sessionsCount++; + + // The Agent could have been destroyed already. + if (entry.destroyed) { + const error = new Error('Agent has been destroyed'); + + for (const listener of listeners) { + listener.reject(error); + } + + session.destroy(); + return; + } + + session[kOriginSet] = session.originSet; + + { + const where = this.sessions; + + if (normalizedOptions in where) { + const sessions = where[normalizedOptions]; + sessions.splice(getSortedIndex(sessions, session, compareSessions), 0, session); + } else { + where[normalizedOptions] = [session]; + } + } + + this._freeSessionsCount += 1; + receivedSettings = true; + + this.emit('session', session); + + processListeners(); + removeFromQueue(); + + // TODO: Close last recently used (or least used?) session + if (session[kCurrentStreamsCount] === 0 && this._freeSessionsCount > this.maxFreeSessions) { + session.close(); + } + + // Check if we haven't managed to execute all listeners. + if (listeners.length !== 0) { + // Request for a new session with predefined listeners. + this.getSession(normalizedOrigin, options, listeners); + listeners.length = 0; + } + + // `session.remoteSettings.maxConcurrentStreams` might get increased + session.on('remoteSettings', () => { + processListeners(); + + // In case the Origin Set changes + closeCoveredSessions(this.sessions[normalizedOptions], session); + }); + }); + + // Shim `session.request()` in order to catch all streams + session[kRequest] = session.request; + session.request = (headers, streamOptions) => { + if (session[kGracefullyClosing]) { + throw new Error('The session is gracefully closing. No new streams are allowed.'); + } + + const stream = session[kRequest](headers, streamOptions); + + // The process won't exit until the session is closed or all requests are gone. + session.ref(); + + ++session[kCurrentStreamsCount]; + + if (session[kCurrentStreamsCount] === session.remoteSettings.maxConcurrentStreams) { + this._freeSessionsCount--; + } + + stream.once('close', () => { + wasFree = isFree(); + + --session[kCurrentStreamsCount]; + + if (!session.destroyed && !session.closed) { + closeSessionIfCovered(this.sessions[normalizedOptions], session); + + if (isFree() && !session.closed) { + if (!wasFree) { + this._freeSessionsCount++; + + wasFree = true; + } + + const isEmpty = session[kCurrentStreamsCount] === 0; + + if (isEmpty) { + session.unref(); + } + + if ( + isEmpty && + ( + this._freeSessionsCount > this.maxFreeSessions || + session[kGracefullyClosing] + ) + ) { + session.close(); + } else { + closeCoveredSessions(this.sessions[normalizedOptions], session); + processListeners(); + } + } + } + }); + + return stream; + }; + } catch (error) { + for (const listener of listeners) { + listener.reject(error); + } + + removeFromQueue(); + } + }; + + entry.listeners = listeners; + entry.completed = false; + entry.destroyed = false; + + this.queue[normalizedOptions][normalizedOrigin] = entry; + this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); + }); + } + + request(origin, options, headers, streamOptions) { + return new Promise((resolve, reject) => { + this.getSession(origin, options, [{ + reject, + resolve: session => { + try { + resolve(session.request(headers, streamOptions)); + } catch (error) { + reject(error); + } + } + }]); + }); + } + + createConnection(origin, options) { + return Agent.connect(origin, options); + } + + static connect(origin, options) { + options.ALPNProtocols = ['h2']; + + const port = origin.port || 443; + const host = origin.hostname || origin.host; + + if (typeof options.servername === 'undefined') { + options.servername = host; + } + + return tls.connect(port, host, options); + } + + closeFreeSessions() { + for (const sessions of Object.values(this.sessions)) { + for (const session of sessions) { + if (session[kCurrentStreamsCount] === 0) { + session.close(); + } + } + } + } + + destroy(reason) { + for (const sessions of Object.values(this.sessions)) { + for (const session of sessions) { + session.destroy(reason); + } + } + + for (const entriesOfAuthority of Object.values(this.queue)) { + for (const entry of Object.values(entriesOfAuthority)) { + entry.destroyed = true; + } + } + + // New requests should NOT attach to destroyed sessions + this.queue = {}; + } + + get freeSessions() { + return getSessions({agent: this, isFree: true}); + } + + get busySessions() { + return getSessions({agent: this, isFree: false}); + } +} + +Agent.kCurrentStreamsCount = kCurrentStreamsCount; +Agent.kGracefullyClosing = kGracefullyClosing; + +module.exports = { + Agent, + globalAgent: new Agent() +}; diff --git a/node_modules/http2-wrapper/source/auto.js b/node_modules/http2-wrapper/source/auto.js new file mode 100644 index 0000000..af4e9ba --- /dev/null +++ b/node_modules/http2-wrapper/source/auto.js @@ -0,0 +1,149 @@ +'use strict'; +const http = require('http'); +const https = require('https'); +const resolveALPN = require('resolve-alpn'); +const QuickLRU = require('quick-lru'); +const Http2ClientRequest = require('./client-request'); +const calculateServerName = require('./utils/calculate-server-name'); +const urlToOptions = require('./utils/url-to-options'); + +const cache = new QuickLRU({maxSize: 100}); +const queue = new Map(); + +const installSocket = (agent, socket, options) => { + socket._httpMessage = {shouldKeepAlive: true}; + + const onFree = () => { + agent.emit('free', socket, options); + }; + + socket.on('free', onFree); + + const onClose = () => { + agent.removeSocket(socket, options); + }; + + socket.on('close', onClose); + + const onRemove = () => { + agent.removeSocket(socket, options); + socket.off('close', onClose); + socket.off('free', onFree); + socket.off('agentRemove', onRemove); + }; + + socket.on('agentRemove', onRemove); + + agent.emit('free', socket, options); +}; + +const resolveProtocol = async options => { + const name = `${options.host}:${options.port}:${options.ALPNProtocols.sort()}`; + + if (!cache.has(name)) { + if (queue.has(name)) { + const result = await queue.get(name); + return result.alpnProtocol; + } + + const {path, agent} = options; + options.path = options.socketPath; + + const resultPromise = resolveALPN(options); + queue.set(name, resultPromise); + + try { + const {socket, alpnProtocol} = await resultPromise; + cache.set(name, alpnProtocol); + + options.path = path; + + if (alpnProtocol === 'h2') { + // https://github.com/nodejs/node/issues/33343 + socket.destroy(); + } else { + const {globalAgent} = https; + const defaultCreateConnection = https.Agent.prototype.createConnection; + + if (agent) { + if (agent.createConnection === defaultCreateConnection) { + installSocket(agent, socket, options); + } else { + socket.destroy(); + } + } else if (globalAgent.createConnection === defaultCreateConnection) { + installSocket(globalAgent, socket, options); + } else { + socket.destroy(); + } + } + + queue.delete(name); + + return alpnProtocol; + } catch (error) { + queue.delete(name); + + throw error; + } + } + + return cache.get(name); +}; + +module.exports = async (input, options, callback) => { + if (typeof input === 'string' || input instanceof URL) { + input = urlToOptions(new URL(input)); + } + + if (typeof options === 'function') { + callback = options; + options = undefined; + } + + options = { + ALPNProtocols: ['h2', 'http/1.1'], + ...input, + ...options, + resolveSocket: true + }; + + if (!Array.isArray(options.ALPNProtocols) || options.ALPNProtocols.length === 0) { + throw new Error('The `ALPNProtocols` option must be an Array with at least one entry'); + } + + options.protocol = options.protocol || 'https:'; + const isHttps = options.protocol === 'https:'; + + options.host = options.hostname || options.host || 'localhost'; + options.session = options.tlsSession; + options.servername = options.servername || calculateServerName(options); + options.port = options.port || (isHttps ? 443 : 80); + options._defaultAgent = isHttps ? https.globalAgent : http.globalAgent; + + const agents = options.agent; + + if (agents) { + if (agents.addRequest) { + throw new Error('The `options.agent` object can contain only `http`, `https` or `http2` properties'); + } + + options.agent = agents[isHttps ? 'https' : 'http']; + } + + if (isHttps) { + const protocol = await resolveProtocol(options); + + if (protocol === 'h2') { + if (agents) { + options.agent = agents.http2; + } + + return new Http2ClientRequest(options, callback); + } + } + + return http.request(options, callback); +}; + +module.exports.protocolCache = cache; diff --git a/node_modules/http2-wrapper/source/client-request.js b/node_modules/http2-wrapper/source/client-request.js new file mode 100644 index 0000000..b712967 --- /dev/null +++ b/node_modules/http2-wrapper/source/client-request.js @@ -0,0 +1,445 @@ +'use strict'; +const http2 = require('http2'); +const {Writable} = require('stream'); +const {Agent, globalAgent} = require('./agent'); +const IncomingMessage = require('./incoming-message'); +const urlToOptions = require('./utils/url-to-options'); +const proxyEvents = require('./utils/proxy-events'); +const isRequestPseudoHeader = require('./utils/is-request-pseudo-header'); +const { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_PROTOCOL, + ERR_HTTP_HEADERS_SENT, + ERR_INVALID_HTTP_TOKEN, + ERR_HTTP_INVALID_HEADER_VALUE, + ERR_INVALID_CHAR +} = require('./utils/errors'); + +const { + HTTP2_HEADER_STATUS, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_METHOD_CONNECT +} = http2.constants; + +const kHeaders = Symbol('headers'); +const kOrigin = Symbol('origin'); +const kSession = Symbol('session'); +const kOptions = Symbol('options'); +const kFlushedHeaders = Symbol('flushedHeaders'); +const kJobs = Symbol('jobs'); + +const isValidHttpToken = /^[\^`\-\w!#$%&*+.|~]+$/; +const isInvalidHeaderValue = /[^\t\u0020-\u007E\u0080-\u00FF]/; + +class ClientRequest extends Writable { + constructor(input, options, callback) { + super({ + autoDestroy: false + }); + + const hasInput = typeof input === 'string' || input instanceof URL; + if (hasInput) { + input = urlToOptions(input instanceof URL ? input : new URL(input)); + } + + if (typeof options === 'function' || options === undefined) { + // (options, callback) + callback = options; + options = hasInput ? input : {...input}; + } else { + // (input, options, callback) + options = {...input, ...options}; + } + + if (options.h2session) { + this[kSession] = options.h2session; + } else if (options.agent === false) { + this.agent = new Agent({maxFreeSessions: 0}); + } else if (typeof options.agent === 'undefined' || options.agent === null) { + if (typeof options.createConnection === 'function') { + // This is a workaround - we don't have to create the session on our own. + this.agent = new Agent({maxFreeSessions: 0}); + this.agent.createConnection = options.createConnection; + } else { + this.agent = globalAgent; + } + } else if (typeof options.agent.request === 'function') { + this.agent = options.agent; + } else { + throw new ERR_INVALID_ARG_TYPE('options.agent', ['Agent-like Object', 'undefined', 'false'], options.agent); + } + + if (options.protocol && options.protocol !== 'https:') { + throw new ERR_INVALID_PROTOCOL(options.protocol, 'https:'); + } + + const port = options.port || options.defaultPort || (this.agent && this.agent.defaultPort) || 443; + const host = options.hostname || options.host || 'localhost'; + + // Don't enforce the origin via options. It may be changed in an Agent. + delete options.hostname; + delete options.host; + delete options.port; + + const {timeout} = options; + options.timeout = undefined; + + this[kHeaders] = Object.create(null); + this[kJobs] = []; + + this.socket = null; + this.connection = null; + + this.method = options.method || 'GET'; + this.path = options.path; + + this.res = null; + this.aborted = false; + this.reusedSocket = false; + + if (options.headers) { + for (const [header, value] of Object.entries(options.headers)) { + this.setHeader(header, value); + } + } + + if (options.auth && !('authorization' in this[kHeaders])) { + this[kHeaders].authorization = 'Basic ' + Buffer.from(options.auth).toString('base64'); + } + + options.session = options.tlsSession; + options.path = options.socketPath; + + this[kOptions] = options; + + // Clients that generate HTTP/2 requests directly SHOULD use the :authority pseudo-header field instead of the Host header field. + if (port === 443) { + this[kOrigin] = `https://${host}`; + + if (!(':authority' in this[kHeaders])) { + this[kHeaders][':authority'] = host; + } + } else { + this[kOrigin] = `https://${host}:${port}`; + + if (!(':authority' in this[kHeaders])) { + this[kHeaders][':authority'] = `${host}:${port}`; + } + } + + if (timeout) { + this.setTimeout(timeout); + } + + if (callback) { + this.once('response', callback); + } + + this[kFlushedHeaders] = false; + } + + get method() { + return this[kHeaders][HTTP2_HEADER_METHOD]; + } + + set method(value) { + if (value) { + this[kHeaders][HTTP2_HEADER_METHOD] = value.toUpperCase(); + } + } + + get path() { + return this[kHeaders][HTTP2_HEADER_PATH]; + } + + set path(value) { + if (value) { + this[kHeaders][HTTP2_HEADER_PATH] = value; + } + } + + get _mustNotHaveABody() { + return this.method === 'GET' || this.method === 'HEAD' || this.method === 'DELETE'; + } + + _write(chunk, encoding, callback) { + // https://github.com/nodejs/node/blob/654df09ae0c5e17d1b52a900a545f0664d8c7627/lib/internal/http2/util.js#L148-L156 + if (this._mustNotHaveABody) { + callback(new Error('The GET, HEAD and DELETE methods must NOT have a body')); + /* istanbul ignore next: Node.js 12 throws directly */ + return; + } + + this.flushHeaders(); + + const callWrite = () => this._request.write(chunk, encoding, callback); + if (this._request) { + callWrite(); + } else { + this[kJobs].push(callWrite); + } + } + + _final(callback) { + if (this.destroyed) { + return; + } + + this.flushHeaders(); + + const callEnd = () => { + // For GET, HEAD and DELETE + if (this._mustNotHaveABody) { + callback(); + return; + } + + this._request.end(callback); + }; + + if (this._request) { + callEnd(); + } else { + this[kJobs].push(callEnd); + } + } + + abort() { + if (this.res && this.res.complete) { + return; + } + + if (!this.aborted) { + process.nextTick(() => this.emit('abort')); + } + + this.aborted = true; + + this.destroy(); + } + + _destroy(error, callback) { + if (this.res) { + this.res._dump(); + } + + if (this._request) { + this._request.destroy(); + } + + callback(error); + } + + async flushHeaders() { + if (this[kFlushedHeaders] || this.destroyed) { + return; + } + + this[kFlushedHeaders] = true; + + const isConnectMethod = this.method === HTTP2_METHOD_CONNECT; + + // The real magic is here + const onStream = stream => { + this._request = stream; + + if (this.destroyed) { + stream.destroy(); + return; + } + + // Forwards `timeout`, `continue`, `close` and `error` events to this instance. + if (!isConnectMethod) { + proxyEvents(stream, this, ['timeout', 'continue', 'close', 'error']); + } + + // Wait for the `finish` event. We don't want to emit the `response` event + // before `request.end()` is called. + const waitForEnd = fn => { + return (...args) => { + if (!this.writable && !this.destroyed) { + fn(...args); + } else { + this.once('finish', () => { + fn(...args); + }); + } + }; + }; + + // This event tells we are ready to listen for the data. + stream.once('response', waitForEnd((headers, flags, rawHeaders) => { + // If we were to emit raw request stream, it would be as fast as the native approach. + // Note that wrapping the raw stream in a Proxy instance won't improve the performance (already tested it). + const response = new IncomingMessage(this.socket, stream.readableHighWaterMark); + this.res = response; + + response.req = this; + response.statusCode = headers[HTTP2_HEADER_STATUS]; + response.headers = headers; + response.rawHeaders = rawHeaders; + + response.once('end', () => { + if (this.aborted) { + response.aborted = true; + response.emit('aborted'); + } else { + response.complete = true; + + // Has no effect, just be consistent with the Node.js behavior + response.socket = null; + response.connection = null; + } + }); + + if (isConnectMethod) { + response.upgrade = true; + + // The HTTP1 API says the socket is detached here, + // but we can't do that so we pass the original HTTP2 request. + if (this.emit('connect', response, stream, Buffer.alloc(0))) { + this.emit('close'); + } else { + // No listeners attached, destroy the original request. + stream.destroy(); + } + } else { + // Forwards data + stream.on('data', chunk => { + if (!response._dumped && !response.push(chunk)) { + stream.pause(); + } + }); + + stream.once('end', () => { + response.push(null); + }); + + if (!this.emit('response', response)) { + // No listeners attached, dump the response. + response._dump(); + } + } + })); + + // Emits `information` event + stream.once('headers', waitForEnd( + headers => this.emit('information', {statusCode: headers[HTTP2_HEADER_STATUS]}) + )); + + stream.once('trailers', waitForEnd((trailers, flags, rawTrailers) => { + const {res} = this; + + // Assigns trailers to the response object. + res.trailers = trailers; + res.rawTrailers = rawTrailers; + })); + + const {socket} = stream.session; + this.socket = socket; + this.connection = socket; + + for (const job of this[kJobs]) { + job(); + } + + this.emit('socket', this.socket); + }; + + // Makes a HTTP2 request + if (this[kSession]) { + try { + onStream(this[kSession].request(this[kHeaders])); + } catch (error) { + this.emit('error', error); + } + } else { + this.reusedSocket = true; + + try { + onStream(await this.agent.request(this[kOrigin], this[kOptions], this[kHeaders])); + } catch (error) { + this.emit('error', error); + } + } + } + + getHeader(name) { + if (typeof name !== 'string') { + throw new ERR_INVALID_ARG_TYPE('name', 'string', name); + } + + return this[kHeaders][name.toLowerCase()]; + } + + get headersSent() { + return this[kFlushedHeaders]; + } + + removeHeader(name) { + if (typeof name !== 'string') { + throw new ERR_INVALID_ARG_TYPE('name', 'string', name); + } + + if (this.headersSent) { + throw new ERR_HTTP_HEADERS_SENT('remove'); + } + + delete this[kHeaders][name.toLowerCase()]; + } + + setHeader(name, value) { + if (this.headersSent) { + throw new ERR_HTTP_HEADERS_SENT('set'); + } + + if (typeof name !== 'string' || (!isValidHttpToken.test(name) && !isRequestPseudoHeader(name))) { + throw new ERR_INVALID_HTTP_TOKEN('Header name', name); + } + + if (typeof value === 'undefined') { + throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name); + } + + if (isInvalidHeaderValue.test(value)) { + throw new ERR_INVALID_CHAR('header content', name); + } + + this[kHeaders][name.toLowerCase()] = value; + } + + setNoDelay() { + // HTTP2 sockets cannot be malformed, do nothing. + } + + setSocketKeepAlive() { + // HTTP2 sockets cannot be malformed, do nothing. + } + + setTimeout(ms, callback) { + const applyTimeout = () => this._request.setTimeout(ms, callback); + + if (this._request) { + applyTimeout(); + } else { + this[kJobs].push(applyTimeout); + } + + return this; + } + + get maxHeadersCount() { + if (!this.destroyed && this._request) { + return this._request.session.localSettings.maxHeaderListSize; + } + + return undefined; + } + + set maxHeadersCount(_value) { + // Updating HTTP2 settings would affect all requests, do nothing. + } +} + +module.exports = ClientRequest; diff --git a/node_modules/http2-wrapper/source/incoming-message.js b/node_modules/http2-wrapper/source/incoming-message.js new file mode 100644 index 0000000..7d5c0d3 --- /dev/null +++ b/node_modules/http2-wrapper/source/incoming-message.js @@ -0,0 +1,58 @@ +'use strict'; +const {Readable} = require('stream'); + +class IncomingMessage extends Readable { + constructor(socket, highWaterMark) { + super({ + highWaterMark, + autoDestroy: false + }); + + this.statusCode = null; + this.statusMessage = ''; + this.httpVersion = '2.0'; + this.httpVersionMajor = 2; + this.httpVersionMinor = 0; + this.headers = {}; + this.trailers = {}; + this.req = null; + + this.aborted = false; + this.complete = false; + this.upgrade = null; + + this.rawHeaders = []; + this.rawTrailers = []; + + this.socket = socket; + this.connection = socket; + + this._dumped = false; + } + + _destroy(error) { + this.req._request.destroy(error); + } + + setTimeout(ms, callback) { + this.req.setTimeout(ms, callback); + return this; + } + + _dump() { + if (!this._dumped) { + this._dumped = true; + + this.removeAllListeners('data'); + this.resume(); + } + } + + _read() { + if (this.req) { + this.req._request.resume(); + } + } +} + +module.exports = IncomingMessage; diff --git a/node_modules/http2-wrapper/source/index.js b/node_modules/http2-wrapper/source/index.js new file mode 100644 index 0000000..fb83349 --- /dev/null +++ b/node_modules/http2-wrapper/source/index.js @@ -0,0 +1,28 @@ +'use strict'; +const http2 = require('http2'); +const agent = require('./agent'); +const ClientRequest = require('./client-request'); +const IncomingMessage = require('./incoming-message'); +const auto = require('./auto'); + +const request = (url, options, callback) => { + return new ClientRequest(url, options, callback); +}; + +const get = (url, options, callback) => { + // eslint-disable-next-line unicorn/prevent-abbreviations + const req = new ClientRequest(url, options, callback); + req.end(); + + return req; +}; + +module.exports = { + ...http2, + ClientRequest, + IncomingMessage, + ...agent, + request, + get, + auto +}; diff --git a/node_modules/http2-wrapper/source/utils/calculate-server-name.js b/node_modules/http2-wrapper/source/utils/calculate-server-name.js new file mode 100644 index 0000000..b05c099 --- /dev/null +++ b/node_modules/http2-wrapper/source/utils/calculate-server-name.js @@ -0,0 +1,27 @@ +'use strict'; +const net = require('net'); +/* istanbul ignore file: https://github.com/nodejs/node/blob/v13.0.1/lib/_http_agent.js */ + +module.exports = options => { + let servername = options.host; + const hostHeader = options.headers && options.headers.host; + + if (hostHeader) { + if (hostHeader.startsWith('[')) { + const index = hostHeader.indexOf(']'); + if (index === -1) { + servername = hostHeader; + } else { + servername = hostHeader.slice(1, -1); + } + } else { + servername = hostHeader.split(':', 1)[0]; + } + } + + if (net.isIP(servername)) { + return ''; + } + + return servername; +}; diff --git a/node_modules/http2-wrapper/source/utils/errors.js b/node_modules/http2-wrapper/source/utils/errors.js new file mode 100644 index 0000000..5018283 --- /dev/null +++ b/node_modules/http2-wrapper/source/utils/errors.js @@ -0,0 +1,45 @@ +'use strict'; +/* istanbul ignore file: https://github.com/nodejs/node/blob/master/lib/internal/errors.js */ + +const makeError = (Base, key, getMessage) => { + module.exports[key] = class NodeError extends Base { + constructor(...args) { + super(typeof getMessage === 'string' ? getMessage : getMessage(args)); + this.name = `${super.name} [${key}]`; + this.code = key; + } + }; +}; + +makeError(TypeError, 'ERR_INVALID_ARG_TYPE', args => { + const type = args[0].includes('.') ? 'property' : 'argument'; + + let valid = args[1]; + const isManyTypes = Array.isArray(valid); + + if (isManyTypes) { + valid = `${valid.slice(0, -1).join(', ')} or ${valid.slice(-1)}`; + } + + return `The "${args[0]}" ${type} must be ${isManyTypes ? 'one of' : 'of'} type ${valid}. Received ${typeof args[2]}`; +}); + +makeError(TypeError, 'ERR_INVALID_PROTOCOL', args => { + return `Protocol "${args[0]}" not supported. Expected "${args[1]}"`; +}); + +makeError(Error, 'ERR_HTTP_HEADERS_SENT', args => { + return `Cannot ${args[0]} headers after they are sent to the client`; +}); + +makeError(TypeError, 'ERR_INVALID_HTTP_TOKEN', args => { + return `${args[0]} must be a valid HTTP token [${args[1]}]`; +}); + +makeError(TypeError, 'ERR_HTTP_INVALID_HEADER_VALUE', args => { + return `Invalid value "${args[0]} for header "${args[1]}"`; +}); + +makeError(TypeError, 'ERR_INVALID_CHAR', args => { + return `Invalid character in ${args[0]} [${args[1]}]`; +}); diff --git a/node_modules/http2-wrapper/source/utils/is-request-pseudo-header.js b/node_modules/http2-wrapper/source/utils/is-request-pseudo-header.js new file mode 100644 index 0000000..bed31cd --- /dev/null +++ b/node_modules/http2-wrapper/source/utils/is-request-pseudo-header.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = header => { + switch (header) { + case ':method': + case ':scheme': + case ':authority': + case ':path': + return true; + default: + return false; + } +}; diff --git a/node_modules/http2-wrapper/source/utils/proxy-events.js b/node_modules/http2-wrapper/source/utils/proxy-events.js new file mode 100644 index 0000000..35e2ae0 --- /dev/null +++ b/node_modules/http2-wrapper/source/utils/proxy-events.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = (from, to, events) => { + for (const event of events) { + from.on(event, (...args) => to.emit(event, ...args)); + } +}; diff --git a/node_modules/http2-wrapper/source/utils/url-to-options.js b/node_modules/http2-wrapper/source/utils/url-to-options.js new file mode 100644 index 0000000..36d1580 --- /dev/null +++ b/node_modules/http2-wrapper/source/utils/url-to-options.js @@ -0,0 +1,25 @@ +'use strict'; +/* istanbul ignore file: https://github.com/nodejs/node/blob/a91293d4d9ab403046ab5eb022332e4e3d249bd3/lib/internal/url.js#L1257 */ + +module.exports = url => { + const options = { + protocol: url.protocol, + hostname: typeof url.hostname === 'string' && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, + host: url.host, + hash: url.hash, + search: url.search, + pathname: url.pathname, + href: url.href, + path: `${url.pathname || ''}${url.search || ''}` + }; + + if (typeof url.port === 'string' && url.port.length !== 0) { + options.port = Number(url.port); + } + + if (url.username || url.password) { + options.auth = `${url.username || ''}:${url.password || ''}`; + } + + return options; +}; diff --git a/node_modules/json-buffer/.travis.yml b/node_modules/json-buffer/.travis.yml new file mode 100644 index 0000000..244b7e8 --- /dev/null +++ b/node_modules/json-buffer/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - '0.10' diff --git a/node_modules/json-buffer/LICENSE b/node_modules/json-buffer/LICENSE new file mode 100644 index 0000000..b799ec0 --- /dev/null +++ b/node_modules/json-buffer/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013 Dominic Tarr + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/json-buffer/README.md b/node_modules/json-buffer/README.md new file mode 100644 index 0000000..4773d63 --- /dev/null +++ b/node_modules/json-buffer/README.md @@ -0,0 +1,24 @@ +# json-buffer + +JSON functions that can convert buffers! + +[![build status](https://secure.travis-ci.org/dominictarr/json-buffer.png)](http://travis-ci.org/dominictarr/json-buffer) + +[![testling badge](https://ci.testling.com/dominictarr/json-buffer.png)](https://ci.testling.com/dominictarr/json-buffer) + +JSON mangles buffers by converting to an array... +which isn't helpful. json-buffers converts to base64 instead, +and deconverts base64 to a buffer. + +``` js +var JSONB = require('json-buffer') +var Buffer = require('buffer').Buffer + +var str = JSONB.stringify(Buffer.from('hello there!')) + +console.log(JSONB.parse(str)) //GET a BUFFER back +``` + +## License + +MIT diff --git a/node_modules/json-buffer/index.js b/node_modules/json-buffer/index.js new file mode 100644 index 0000000..16f012e --- /dev/null +++ b/node_modules/json-buffer/index.js @@ -0,0 +1,58 @@ +//TODO: handle reviver/dehydrate function like normal +//and handle indentation, like normal. +//if anyone needs this... please send pull request. + +exports.stringify = function stringify (o) { + if('undefined' == typeof o) return o + + if(o && Buffer.isBuffer(o)) + return JSON.stringify(':base64:' + o.toString('base64')) + + if(o && o.toJSON) + o = o.toJSON() + + if(o && 'object' === typeof o) { + var s = '' + var array = Array.isArray(o) + s = array ? '[' : '{' + var first = true + + for(var k in o) { + var ignore = 'function' == typeof o[k] || (!array && 'undefined' === typeof o[k]) + if(Object.hasOwnProperty.call(o, k) && !ignore) { + if(!first) + s += ',' + first = false + if (array) { + if(o[k] == undefined) + s += 'null' + else + s += stringify(o[k]) + } else if (o[k] !== void(0)) { + s += stringify(k) + ':' + stringify(o[k]) + } + } + } + + s += array ? ']' : '}' + + return s + } else if ('string' === typeof o) { + return JSON.stringify(/^:/.test(o) ? ':' + o : o) + } else if ('undefined' === typeof o) { + return 'null'; + } else + return JSON.stringify(o) +} + +exports.parse = function (s) { + return JSON.parse(s, function (key, value) { + if('string' === typeof value) { + if(/^:base64:/.test(value)) + return Buffer.from(value.substring(8), 'base64') + else + return /^:/.test(value) ? value.substring(1) : value + } + return value + }) +} diff --git a/node_modules/json-buffer/package.json b/node_modules/json-buffer/package.json new file mode 100644 index 0000000..346747f --- /dev/null +++ b/node_modules/json-buffer/package.json @@ -0,0 +1,34 @@ +{ + "name": "json-buffer", + "description": "JSON parse & stringify that supports binary via bops & base64", + "version": "3.0.1", + "homepage": "https://github.com/dominictarr/json-buffer", + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/json-buffer.git" + }, + "devDependencies": { + "tape": "^4.6.3" + }, + "scripts": { + "test": "set -e; for t in test/*.js; do node $t; done" + }, + "author": "Dominic Tarr (http://dominictarr.com)", + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/17..latest", + "firefox/nightly", + "chrome/22..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + } +} diff --git a/node_modules/json-buffer/test/index.js b/node_modules/json-buffer/test/index.js new file mode 100644 index 0000000..94e8372 --- /dev/null +++ b/node_modules/json-buffer/test/index.js @@ -0,0 +1,63 @@ + +var test = require('tape') +var _JSON = require('../') + +function clone (o) { + return JSON.parse(JSON.stringify(o)) +} + +var examples = { + simple: { foo: [], bar: {}, baz: Buffer.from('some binary data') }, + just_buffer: Buffer.from('JUST A BUFFER'), + all_types: { + string:'hello', + number: 3145, + null: null, + object: {}, + array: [], + boolean: true, + boolean2: false + }, + foo: Buffer.from('foo'), + foo2: Buffer.from('foo2'), + escape: { + buffer: Buffer.from('x'), + string: _JSON.stringify(Buffer.from('x')) + }, + escape2: { + buffer: Buffer.from('x'), + string: ':base64:'+ Buffer.from('x').toString('base64') + }, + undefined: { + empty: undefined, test: true + }, + undefined2: { + first: 1, empty: undefined, test: true + }, + undefinedArray: { + array: [undefined, 1, 'two'] + }, + fn: { + fn: function () {} + }, + undefined: undefined +} + +for(k in examples) +(function (value, k) { + test(k, function (t) { + var s = _JSON.stringify(value) + console.log('parse', s) + if(JSON.stringify(value) !== undefined) { + console.log(s) + var _value = _JSON.parse(s) + t.deepEqual(clone(_value), clone(value)) + } + else + t.equal(s, undefined) + t.end() + }) +})(examples[k], k) + + + diff --git a/node_modules/keyv/LICENSE b/node_modules/keyv/LICENSE new file mode 100644 index 0000000..f27ee9b --- /dev/null +++ b/node_modules/keyv/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Luke Childs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/keyv/README.md b/node_modules/keyv/README.md new file mode 100644 index 0000000..1829d09 --- /dev/null +++ b/node_modules/keyv/README.md @@ -0,0 +1,288 @@ +

+ keyv +
+
+

+ +> Simple key-value storage with support for multiple backends + +[![Build Status](https://travis-ci.org/lukechilds/keyv.svg?branch=master)](https://travis-ci.org/lukechilds/keyv) +[![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv?branch=master) +[![npm](https://img.shields.io/npm/dm/keyv.svg)](https://www.npmjs.com/package/keyv) +[![npm](https://img.shields.io/npm/v/keyv.svg)](https://www.npmjs.com/package/keyv) + +Keyv provides a consistent interface for key-value storage across multiple backends via storage adapters. It supports TTL based expiry, making it suitable as a cache or a persistent key-value store. + +## Features + +There are a few existing modules similar to Keyv, however Keyv is different because it: + +- Isn't bloated +- Has a simple Promise based API +- Suitable as a TTL based cache or persistent key-value store +- [Easily embeddable](#add-cache-support-to-your-module) inside another module +- Works with any storage that implements the [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) API +- Handles all JSON types plus `Buffer` +- Supports namespaces +- Wide range of [**efficient, well tested**](#official-storage-adapters) storage adapters +- Connection errors are passed through (db failures won't kill your app) +- Supports the current active LTS version of Node.js or higher + +## Usage + +Install Keyv. + +``` +npm install --save keyv +``` + +By default everything is stored in memory, you can optionally also install a storage adapter. + +``` +npm install --save @keyv/redis +npm install --save @keyv/mongo +npm install --save @keyv/sqlite +npm install --save @keyv/postgres +npm install --save @keyv/mysql +``` + +Create a new Keyv instance, passing your connection string if applicable. Keyv will automatically load the correct storage adapter. + +```js +const Keyv = require('keyv'); + +// One of the following +const keyv = new Keyv(); +const keyv = new Keyv('redis://user:pass@localhost:6379'); +const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname'); +const keyv = new Keyv('sqlite://path/to/database.sqlite'); +const keyv = new Keyv('postgresql://user:pass@localhost:5432/dbname'); +const keyv = new Keyv('mysql://user:pass@localhost:3306/dbname'); + +// Handle DB connection errors +keyv.on('error', err => console.log('Connection Error', err)); + +await keyv.set('foo', 'expires in 1 second', 1000); // true +await keyv.set('foo', 'never expires'); // true +await keyv.get('foo'); // 'never expires' +await keyv.delete('foo'); // true +await keyv.clear(); // undefined +``` + +### Namespaces + +You can namespace your Keyv instance to avoid key collisions and allow you to clear only a certain namespace while using the same database. + +```js +const users = new Keyv('redis://user:pass@localhost:6379', { namespace: 'users' }); +const cache = new Keyv('redis://user:pass@localhost:6379', { namespace: 'cache' }); + +await users.set('foo', 'users'); // true +await cache.set('foo', 'cache'); // true +await users.get('foo'); // 'users' +await cache.get('foo'); // 'cache' +await users.clear(); // undefined +await users.get('foo'); // undefined +await cache.get('foo'); // 'cache' +``` + +### Custom Serializers + +Keyv uses [`json-buffer`](https://github.com/dominictarr/json-buffer) for data serialization to ensure consistency across different backends. + +You can optionally provide your own serialization functions to support extra data types or to serialize to something other than JSON. + +```js +const keyv = new Keyv({ serialize: JSON.stringify, deserialize: JSON.parse }); +``` + +**Warning:** Using custom serializers means you lose any guarantee of data consistency. You should do extensive testing with your serialisation functions and chosen storage engine. + +## Official Storage Adapters + +The official storage adapters are covered by [over 150 integration tests](https://travis-ci.org/lukechilds/keyv/jobs/260418145) to guarantee consistent behaviour. They are lightweight, efficient wrappers over the DB clients making use of indexes and native TTLs where available. + +Database | Adapter | Native TTL | Status +---|---|---|--- +Redis | [@keyv/redis](https://github.com/lukechilds/keyv-redis) | Yes | [![Build Status](https://travis-ci.org/lukechilds/keyv-redis.svg?branch=master)](https://travis-ci.org/lukechilds/keyv-redis) [![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv-redis/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv-redis?branch=master) +MongoDB | [@keyv/mongo](https://github.com/lukechilds/keyv-mongo) | Yes | [![Build Status](https://travis-ci.org/lukechilds/keyv-mongo.svg?branch=master)](https://travis-ci.org/lukechilds/keyv-mongo) [![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv-mongo/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv-mongo?branch=master) +SQLite | [@keyv/sqlite](https://github.com/lukechilds/keyv-sqlite) | No | [![Build Status](https://travis-ci.org/lukechilds/keyv-sqlite.svg?branch=master)](https://travis-ci.org/lukechilds/keyv-sqlite) [![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv-sqlite/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv-sqlite?branch=master) +PostgreSQL | [@keyv/postgres](https://github.com/lukechilds/keyv-postgres) | No | [![Build Status](https://travis-ci.org/lukechilds/keyv-postgres.svg?branch=master)](https://travis-ci.org/lukechildskeyv-postgreskeyv) [![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv-postgres/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv-postgres?branch=master) +MySQL | [@keyv/mysql](https://github.com/lukechilds/keyv-mysql) | No | [![Build Status](https://travis-ci.org/lukechilds/keyv-mysql.svg?branch=master)](https://travis-ci.org/lukechilds/keyv-mysql) [![Coverage Status](https://coveralls.io/repos/github/lukechilds/keyv-mysql/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/keyv-mysql?branch=master) + +## Third-party Storage Adapters + +You can also use third-party storage adapters or build your own. Keyv will wrap these storage adapters in TTL functionality and handle complex types internally. + +```js +const Keyv = require('keyv'); +const myAdapter = require('./my-storage-adapter'); + +const keyv = new Keyv({ store: myAdapter }); +``` + +Any store that follows the [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) api will work. + +```js +new Keyv({ store: new Map() }); +``` + +For example, [`quick-lru`](https://github.com/sindresorhus/quick-lru) is a completely unrelated module that implements the Map API. + +```js +const Keyv = require('keyv'); +const QuickLRU = require('quick-lru'); + +const lru = new QuickLRU({ maxSize: 1000 }); +const keyv = new Keyv({ store: lru }); +``` + +The following are third-party storage adapters compatible with Keyv: + +- [quick-lru](https://github.com/sindresorhus/quick-lru) - Simple "Least Recently Used" (LRU) cache +- [keyv-file](https://github.com/zaaack/keyv-file) - File system storage adapter for Keyv +- [keyv-dynamodb](https://www.npmjs.com/package/keyv-dynamodb) - DynamoDB storage adapter for Keyv +- [keyv-firestore ](https://github.com/goto-bus-stop/keyv-firestore) – Firebase Cloud Firestore adapter for Keyv +- [keyv-mssql](https://github.com/pmorgan3/keyv-mssql) - Microsoft Sql Server adapter for Keyv +- [keyv-memcache](https://github.com/jaredwray/keyv-memcache) - Memcache storage adapter for Keyv + +## Add Cache Support to your Module + +Keyv is designed to be easily embedded into other modules to add cache support. The recommended pattern is to expose a `cache` option in your modules options which is passed through to Keyv. Caching will work in memory by default and users have the option to also install a Keyv storage adapter and pass in a connection string, or any other storage that implements the `Map` API. + +You should also set a namespace for your module so you can safely call `.clear()` without clearing unrelated app data. + +Inside your module: + +```js +class AwesomeModule { + constructor(opts) { + this.cache = new Keyv({ + uri: typeof opts.cache === 'string' && opts.cache, + store: typeof opts.cache !== 'string' && opts.cache, + namespace: 'awesome-module' + }); + } +} +``` + +Now it can be consumed like this: + +```js +const AwesomeModule = require('awesome-module'); + +// Caches stuff in memory by default +const awesomeModule = new AwesomeModule(); + +// After npm install --save keyv-redis +const awesomeModule = new AwesomeModule({ cache: 'redis://localhost' }); + +// Some third-party module that implements the Map API +const awesomeModule = new AwesomeModule({ cache: some3rdPartyStore }); +``` + +## API + +### new Keyv([uri], [options]) + +Returns a new Keyv instance. + +The Keyv instance is also an `EventEmitter` that will emit an `'error'` event if the storage adapter connection fails. + +### uri + +Type: `String`
+Default: `undefined` + +The connection string URI. + +Merged into the options object as options.uri. + +### options + +Type: `Object` + +The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options. + +#### options.namespace + +Type: `String`
+Default: `'keyv'` + +Namespace for the current instance. + +#### options.ttl + +Type: `Number`
+Default: `undefined` + +Default TTL. Can be overridden by specififying a TTL on `.set()`. + +#### options.serialize + +Type: `Function`
+Default: `JSONB.stringify` + +A custom serialization function. + +#### options.deserialize + +Type: `Function`
+Default: `JSONB.parse` + +A custom deserialization function. + +#### options.store + +Type: `Storage adapter instance`
+Default: `new Map()` + +The storage adapter instance to be used by Keyv. + +#### options.adapter + +Type: `String`
+Default: `undefined` + +Specify an adapter to use. e.g `'redis'` or `'mongodb'`. + +### Instance + +Keys must always be strings. Values can be of any type. + +#### .set(key, value, [ttl]) + +Set a value. + +By default keys are persistent. You can set an expiry TTL in milliseconds. + +Returns a promise which resolves to `true`. + +#### .get(key, [options]) + +Returns a promise which resolves to the retrieved value. + +##### options.raw + +Type: `Boolean`
+Default: `false` + +If set to true the raw DB object Keyv stores internally will be returned instead of just the value. + +This contains the TTL timestamp. + +#### .delete(key) + +Deletes an entry. + +Returns a promise which resolves to `true` if the key existed, `false` if not. + +#### .clear() + +Delete all entries in the current namespace. + +Returns a promise which is resolved when the entries have been cleared. + +## License + +MIT © Luke Childs diff --git a/node_modules/keyv/package.json b/node_modules/keyv/package.json new file mode 100644 index 0000000..5e2106b --- /dev/null +++ b/node_modules/keyv/package.json @@ -0,0 +1,49 @@ +{ + "name": "keyv", + "version": "4.0.3", + "description": "Simple key-value storage with support for multiple backends", + "main": "src/index.js", + "scripts": { + "test": "xo && nyc ava test/keyv.js", + "test:full": "xo && nyc ava --serial", + "coverage": "nyc report --reporter=text-lcov | coveralls" + }, + "xo": { + "extends": "xo-lukechilds" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lukechilds/keyv.git" + }, + "keywords": [ + "key", + "value", + "store", + "cache", + "ttl" + ], + "author": "Luke Childs (http://lukechilds.co.uk)", + "license": "MIT", + "bugs": { + "url": "https://github.com/lukechilds/keyv/issues" + }, + "homepage": "https://github.com/lukechilds/keyv", + "dependencies": { + "json-buffer": "3.0.1" + }, + "devDependencies": { + "ava": "^2.2.0", + "coveralls": "^3.0.0", + "eslint-config-xo-lukechilds": "^1.0.0", + "@keyv/mongo": "*", + "@keyv/mysql": "*", + "@keyv/postgres": "*", + "@keyv/redis": "*", + "@keyv/sqlite": "*", + "@keyv/test-suite": "*", + "nyc": "^14.1.1", + "this": "^1.0.2", + "timekeeper": "^2.0.0", + "xo": "^0.25.3" + } +} diff --git a/node_modules/keyv/src/index.js b/node_modules/keyv/src/index.js new file mode 100644 index 0000000..9f88d1a --- /dev/null +++ b/node_modules/keyv/src/index.js @@ -0,0 +1,111 @@ +'use strict'; + +const EventEmitter = require('events'); +const JSONB = require('json-buffer'); + +const loadStore = opts => { + const adapters = { + redis: '@keyv/redis', + mongodb: '@keyv/mongo', + mongo: '@keyv/mongo', + sqlite: '@keyv/sqlite', + postgresql: '@keyv/postgres', + postgres: '@keyv/postgres', + mysql: '@keyv/mysql' + }; + if (opts.adapter || opts.uri) { + const adapter = opts.adapter || /^[^:]*/.exec(opts.uri)[0]; + return new (require(adapters[adapter]))(opts); + } + + return new Map(); +}; + +class Keyv extends EventEmitter { + constructor(uri, opts) { + super(); + this.opts = Object.assign( + { + namespace: 'keyv', + serialize: JSONB.stringify, + deserialize: JSONB.parse + }, + (typeof uri === 'string') ? { uri } : uri, + opts + ); + + if (!this.opts.store) { + const adapterOpts = Object.assign({}, this.opts); + this.opts.store = loadStore(adapterOpts); + } + + if (typeof this.opts.store.on === 'function') { + this.opts.store.on('error', err => this.emit('error', err)); + } + + this.opts.store.namespace = this.opts.namespace; + } + + _getKeyPrefix(key) { + return `${this.opts.namespace}:${key}`; + } + + get(key, opts) { + const keyPrefixed = this._getKeyPrefix(key); + const { store } = this.opts; + return Promise.resolve() + .then(() => store.get(keyPrefixed)) + .then(data => { + return (typeof data === 'string') ? this.opts.deserialize(data) : data; + }) + .then(data => { + if (data === undefined) { + return undefined; + } + + if (typeof data.expires === 'number' && Date.now() > data.expires) { + this.delete(key); + return undefined; + } + + return (opts && opts.raw) ? data : data.value; + }); + } + + set(key, value, ttl) { + const keyPrefixed = this._getKeyPrefix(key); + if (typeof ttl === 'undefined') { + ttl = this.opts.ttl; + } + + if (ttl === 0) { + ttl = undefined; + } + + const { store } = this.opts; + + return Promise.resolve() + .then(() => { + const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : null; + value = { value, expires }; + return this.opts.serialize(value); + }) + .then(value => store.set(keyPrefixed, value, ttl)) + .then(() => true); + } + + delete(key) { + const keyPrefixed = this._getKeyPrefix(key); + const { store } = this.opts; + return Promise.resolve() + .then(() => store.delete(keyPrefixed)); + } + + clear() { + const { store } = this.opts; + return Promise.resolve() + .then(() => store.clear()); + } +} + +module.exports = Keyv; diff --git a/node_modules/lowercase-keys/index.d.ts b/node_modules/lowercase-keys/index.d.ts new file mode 100644 index 0000000..dc90a75 --- /dev/null +++ b/node_modules/lowercase-keys/index.d.ts @@ -0,0 +1,16 @@ +/** +Lowercase the keys of an object. + +@returns A new object with the keys lowercased. + +@example +``` +import lowercaseKeys = require('lowercase-keys'); + +lowercaseKeys({FOO: true, bAr: false}); +//=> {foo: true, bar: false} +``` +*/ +declare function lowercaseKeys(object: {[key: string]: T}): {[key: string]: T}; + +export = lowercaseKeys; diff --git a/node_modules/lowercase-keys/index.js b/node_modules/lowercase-keys/index.js new file mode 100644 index 0000000..357fb8f --- /dev/null +++ b/node_modules/lowercase-keys/index.js @@ -0,0 +1,10 @@ +'use strict'; +module.exports = object => { + const result = {}; + + for (const [key, value] of Object.entries(object)) { + result[key.toLowerCase()] = value; + } + + return result; +}; diff --git a/node_modules/lowercase-keys/license b/node_modules/lowercase-keys/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/lowercase-keys/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/lowercase-keys/package.json b/node_modules/lowercase-keys/package.json new file mode 100644 index 0000000..c11d813 --- /dev/null +++ b/node_modules/lowercase-keys/package.json @@ -0,0 +1,38 @@ +{ + "name": "lowercase-keys", + "version": "2.0.0", + "description": "Lowercase the keys of an object", + "license": "MIT", + "repository": "sindresorhus/lowercase-keys", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "object", + "assign", + "extend", + "properties", + "lowercase", + "lower-case", + "case", + "keys", + "key" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/lowercase-keys/readme.md b/node_modules/lowercase-keys/readme.md new file mode 100644 index 0000000..b1ed061 --- /dev/null +++ b/node_modules/lowercase-keys/readme.md @@ -0,0 +1,32 @@ +# lowercase-keys [![Build Status](https://travis-ci.org/sindresorhus/lowercase-keys.svg?branch=master)](https://travis-ci.org/sindresorhus/lowercase-keys) + +> Lowercase the keys of an object + + +## Install + +``` +$ npm install lowercase-keys +``` + + +## Usage + +```js +const lowercaseKeys = require('lowercase-keys'); + +lowercaseKeys({FOO: true, bAr: false}); +//=> {foo: true, bar: false} +``` + + +## API + +### lowercaseKeys(object) + +Returns a new object with the keys lowercased. + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/mime-db/HISTORY.md b/node_modules/mime-db/HISTORY.md new file mode 100644 index 0000000..1555055 --- /dev/null +++ b/node_modules/mime-db/HISTORY.md @@ -0,0 +1,473 @@ +1.47.0 / 2021-04-01 +=================== + + * Add new upstream MIME types + * Remove ambigious extensions from IANA for `application/*+xml` types + * Update primary extension to `.es` for `application/ecmascript` + +1.46.0 / 2021-02-13 +=================== + + * Add extension `.amr` to `audio/amr` + * Add extension `.m4s` to `video/iso.segment` + * Add extension `.opus` to `audio/ogg` + * Add new upstream MIME types + +1.45.0 / 2020-09-22 +=================== + + * Add `application/ubjson` with extension `.ubj` + * Add `image/avif` with extension `.avif` + * Add `image/ktx2` with extension `.ktx2` + * Add extension `.dbf` to `application/vnd.dbf` + * Add extension `.rar` to `application/vnd.rar` + * Add extension `.td` to `application/urc-targetdesc+xml` + * Add new upstream MIME types + * Fix extension of `application/vnd.apple.keynote` to be `.key` + +1.44.0 / 2020-04-22 +=================== + + * Add charsets from IANA + * Add extension `.cjs` to `application/node` + * Add new upstream MIME types + +1.43.0 / 2020-01-05 +=================== + + * Add `application/x-keepass2` with extension `.kdbx` + * Add extension `.mxmf` to `audio/mobile-xmf` + * Add extensions from IANA for `application/*+xml` types + * Add new upstream MIME types + +1.42.0 / 2019-09-25 +=================== + + * Add `image/vnd.ms-dds` with extension `.dds` + * Add new upstream MIME types + * Remove compressible from `multipart/mixed` + +1.41.0 / 2019-08-30 +=================== + + * Add new upstream MIME types + * Add `application/toml` with extension `.toml` + * Mark `font/ttf` as compressible + +1.40.0 / 2019-04-20 +=================== + + * Add extensions from IANA for `model/*` types + * Add `text/mdx` with extension `.mdx` + +1.39.0 / 2019-04-04 +=================== + + * Add extensions `.siv` and `.sieve` to `application/sieve` + * Add new upstream MIME types + +1.38.0 / 2019-02-04 +=================== + + * Add extension `.nq` to `application/n-quads` + * Add extension `.nt` to `application/n-triples` + * Add new upstream MIME types + * Mark `text/less` as compressible + +1.37.0 / 2018-10-19 +=================== + + * Add extensions to HEIC image types + * Add new upstream MIME types + +1.36.0 / 2018-08-20 +=================== + + * Add Apple file extensions from IANA + * Add extensions from IANA for `image/*` types + * Add new upstream MIME types + +1.35.0 / 2018-07-15 +=================== + + * Add extension `.owl` to `application/rdf+xml` + * Add new upstream MIME types + - Removes extension `.woff` from `application/font-woff` + +1.34.0 / 2018-06-03 +=================== + + * Add extension `.csl` to `application/vnd.citationstyles.style+xml` + * Add extension `.es` to `application/ecmascript` + * Add new upstream MIME types + * Add `UTF-8` as default charset for `text/turtle` + * Mark all XML-derived types as compressible + +1.33.0 / 2018-02-15 +=================== + + * Add extensions from IANA for `message/*` types + * Add new upstream MIME types + * Fix some incorrect OOXML types + * Remove `application/font-woff2` + +1.32.0 / 2017-11-29 +=================== + + * Add new upstream MIME types + * Update `text/hjson` to registered `application/hjson` + * Add `text/shex` with extension `.shex` + +1.31.0 / 2017-10-25 +=================== + + * Add `application/raml+yaml` with extension `.raml` + * Add `application/wasm` with extension `.wasm` + * Add new `font` type from IANA + * Add new upstream font extensions + * Add new upstream MIME types + * Add extensions for JPEG-2000 images + +1.30.0 / 2017-08-27 +=================== + + * Add `application/vnd.ms-outlook` + * Add `application/x-arj` + * Add extension `.mjs` to `application/javascript` + * Add glTF types and extensions + * Add new upstream MIME types + * Add `text/x-org` + * Add VirtualBox MIME types + * Fix `source` records for `video/*` types that are IANA + * Update `font/opentype` to registered `font/otf` + +1.29.0 / 2017-07-10 +=================== + + * Add `application/fido.trusted-apps+json` + * Add extension `.wadl` to `application/vnd.sun.wadl+xml` + * Add new upstream MIME types + * Add `UTF-8` as default charset for `text/css` + +1.28.0 / 2017-05-14 +=================== + + * Add new upstream MIME types + * Add extension `.gz` to `application/gzip` + * Update extensions `.md` and `.markdown` to be `text/markdown` + +1.27.0 / 2017-03-16 +=================== + + * Add new upstream MIME types + * Add `image/apng` with extension `.apng` + +1.26.0 / 2017-01-14 +=================== + + * Add new upstream MIME types + * Add extension `.geojson` to `application/geo+json` + +1.25.0 / 2016-11-11 +=================== + + * Add new upstream MIME types + +1.24.0 / 2016-09-18 +=================== + + * Add `audio/mp3` + * Add new upstream MIME types + +1.23.0 / 2016-05-01 +=================== + + * Add new upstream MIME types + * Add extension `.3gpp` to `audio/3gpp` + +1.22.0 / 2016-02-15 +=================== + + * Add `text/slim` + * Add extension `.rng` to `application/xml` + * Add new upstream MIME types + * Fix extension of `application/dash+xml` to be `.mpd` + * Update primary extension to `.m4a` for `audio/mp4` + +1.21.0 / 2016-01-06 +=================== + + * Add Google document types + * Add new upstream MIME types + +1.20.0 / 2015-11-10 +=================== + + * Add `text/x-suse-ymp` + * Add new upstream MIME types + +1.19.0 / 2015-09-17 +=================== + + * Add `application/vnd.apple.pkpass` + * Add new upstream MIME types + +1.18.0 / 2015-09-03 +=================== + + * Add new upstream MIME types + +1.17.0 / 2015-08-13 +=================== + + * Add `application/x-msdos-program` + * Add `audio/g711-0` + * Add `image/vnd.mozilla.apng` + * Add extension `.exe` to `application/x-msdos-program` + +1.16.0 / 2015-07-29 +=================== + + * Add `application/vnd.uri-map` + +1.15.0 / 2015-07-13 +=================== + + * Add `application/x-httpd-php` + +1.14.0 / 2015-06-25 +=================== + + * Add `application/scim+json` + * Add `application/vnd.3gpp.ussd+xml` + * Add `application/vnd.biopax.rdf+xml` + * Add `text/x-processing` + +1.13.0 / 2015-06-07 +=================== + + * Add nginx as a source + * Add `application/x-cocoa` + * Add `application/x-java-archive-diff` + * Add `application/x-makeself` + * Add `application/x-perl` + * Add `application/x-pilot` + * Add `application/x-redhat-package-manager` + * Add `application/x-sea` + * Add `audio/x-m4a` + * Add `audio/x-realaudio` + * Add `image/x-jng` + * Add `text/mathml` + +1.12.0 / 2015-06-05 +=================== + + * Add `application/bdoc` + * Add `application/vnd.hyperdrive+json` + * Add `application/x-bdoc` + * Add extension `.rtf` to `text/rtf` + +1.11.0 / 2015-05-31 +=================== + + * Add `audio/wav` + * Add `audio/wave` + * Add extension `.litcoffee` to `text/coffeescript` + * Add extension `.sfd-hdstx` to `application/vnd.hydrostatix.sof-data` + * Add extension `.n-gage` to `application/vnd.nokia.n-gage.symbian.install` + +1.10.0 / 2015-05-19 +=================== + + * Add `application/vnd.balsamiq.bmpr` + * Add `application/vnd.microsoft.portable-executable` + * Add `application/x-ns-proxy-autoconfig` + +1.9.1 / 2015-04-19 +================== + + * Remove `.json` extension from `application/manifest+json` + - This is causing bugs downstream + +1.9.0 / 2015-04-19 +================== + + * Add `application/manifest+json` + * Add `application/vnd.micro+json` + * Add `image/vnd.zbrush.pcx` + * Add `image/x-ms-bmp` + +1.8.0 / 2015-03-13 +================== + + * Add `application/vnd.citationstyles.style+xml` + * Add `application/vnd.fastcopy-disk-image` + * Add `application/vnd.gov.sk.xmldatacontainer+xml` + * Add extension `.jsonld` to `application/ld+json` + +1.7.0 / 2015-02-08 +================== + + * Add `application/vnd.gerber` + * Add `application/vnd.msa-disk-image` + +1.6.1 / 2015-02-05 +================== + + * Community extensions ownership transferred from `node-mime` + +1.6.0 / 2015-01-29 +================== + + * Add `application/jose` + * Add `application/jose+json` + * Add `application/json-seq` + * Add `application/jwk+json` + * Add `application/jwk-set+json` + * Add `application/jwt` + * Add `application/rdap+json` + * Add `application/vnd.gov.sk.e-form+xml` + * Add `application/vnd.ims.imsccv1p3` + +1.5.0 / 2014-12-30 +================== + + * Add `application/vnd.oracle.resource+json` + * Fix various invalid MIME type entries + - `application/mbox+xml` + - `application/oscp-response` + - `application/vwg-multiplexed` + - `audio/g721` + +1.4.0 / 2014-12-21 +================== + + * Add `application/vnd.ims.imsccv1p2` + * Fix various invalid MIME type entries + - `application/vnd-acucobol` + - `application/vnd-curl` + - `application/vnd-dart` + - `application/vnd-dxr` + - `application/vnd-fdf` + - `application/vnd-mif` + - `application/vnd-sema` + - `application/vnd-wap-wmlc` + - `application/vnd.adobe.flash-movie` + - `application/vnd.dece-zip` + - `application/vnd.dvb_service` + - `application/vnd.micrografx-igx` + - `application/vnd.sealed-doc` + - `application/vnd.sealed-eml` + - `application/vnd.sealed-mht` + - `application/vnd.sealed-ppt` + - `application/vnd.sealed-tiff` + - `application/vnd.sealed-xls` + - `application/vnd.sealedmedia.softseal-html` + - `application/vnd.sealedmedia.softseal-pdf` + - `application/vnd.wap-slc` + - `application/vnd.wap-wbxml` + - `audio/vnd.sealedmedia.softseal-mpeg` + - `image/vnd-djvu` + - `image/vnd-svf` + - `image/vnd-wap-wbmp` + - `image/vnd.sealed-png` + - `image/vnd.sealedmedia.softseal-gif` + - `image/vnd.sealedmedia.softseal-jpg` + - `model/vnd-dwf` + - `model/vnd.parasolid.transmit-binary` + - `model/vnd.parasolid.transmit-text` + - `text/vnd-a` + - `text/vnd-curl` + - `text/vnd.wap-wml` + * Remove example template MIME types + - `application/example` + - `audio/example` + - `image/example` + - `message/example` + - `model/example` + - `multipart/example` + - `text/example` + - `video/example` + +1.3.1 / 2014-12-16 +================== + + * Fix missing extensions + - `application/json5` + - `text/hjson` + +1.3.0 / 2014-12-07 +================== + + * Add `application/a2l` + * Add `application/aml` + * Add `application/atfx` + * Add `application/atxml` + * Add `application/cdfx+xml` + * Add `application/dii` + * Add `application/json5` + * Add `application/lxf` + * Add `application/mf4` + * Add `application/vnd.apache.thrift.compact` + * Add `application/vnd.apache.thrift.json` + * Add `application/vnd.coffeescript` + * Add `application/vnd.enphase.envoy` + * Add `application/vnd.ims.imsccv1p1` + * Add `text/csv-schema` + * Add `text/hjson` + * Add `text/markdown` + * Add `text/yaml` + +1.2.0 / 2014-11-09 +================== + + * Add `application/cea` + * Add `application/dit` + * Add `application/vnd.gov.sk.e-form+zip` + * Add `application/vnd.tmd.mediaflex.api+xml` + * Type `application/epub+zip` is now IANA-registered + +1.1.2 / 2014-10-23 +================== + + * Rebuild database for `application/x-www-form-urlencoded` change + +1.1.1 / 2014-10-20 +================== + + * Mark `application/x-www-form-urlencoded` as compressible. + +1.1.0 / 2014-09-28 +================== + + * Add `application/font-woff2` + +1.0.3 / 2014-09-25 +================== + + * Fix engine requirement in package + +1.0.2 / 2014-09-25 +================== + + * Add `application/coap-group+json` + * Add `application/dcd` + * Add `application/vnd.apache.thrift.binary` + * Add `image/vnd.tencent.tap` + * Mark all JSON-derived types as compressible + * Update `text/vtt` data + +1.0.1 / 2014-08-30 +================== + + * Fix extension ordering + +1.0.0 / 2014-08-30 +================== + + * Add `application/atf` + * Add `application/merge-patch+json` + * Add `multipart/x-mixed-replace` + * Add `source: 'apache'` metadata + * Add `source: 'iana'` metadata + * Remove badly-assumed charset data diff --git a/node_modules/mime-db/LICENSE b/node_modules/mime-db/LICENSE new file mode 100644 index 0000000..a7ae8ee --- /dev/null +++ b/node_modules/mime-db/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/mime-db/README.md b/node_modules/mime-db/README.md new file mode 100644 index 0000000..41c696a --- /dev/null +++ b/node_modules/mime-db/README.md @@ -0,0 +1,100 @@ +# mime-db + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][ci-image]][ci-url] +[![Coverage Status][coveralls-image]][coveralls-url] + +This is a database of all mime types. +It consists of a single, public JSON file and does not include any logic, +allowing it to remain as un-opinionated as possible with an API. +It aggregates data from the following sources: + +- http://www.iana.org/assignments/media-types/media-types.xhtml +- http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +- http://hg.nginx.org/nginx/raw-file/default/conf/mime.types + +## Installation + +```bash +npm install mime-db +``` + +### Database Download + +If you're crazy enough to use this in the browser, you can just grab the +JSON file using [jsDelivr](https://www.jsdelivr.com/). It is recommended to +replace `master` with [a release tag](https://github.com/jshttp/mime-db/tags) +as the JSON format may change in the future. + +``` +https://cdn.jsdelivr.net/gh/jshttp/mime-db@master/db.json +``` + +## Usage + +```js +var db = require('mime-db') + +// grab data on .js files +var data = db['application/javascript'] +``` + +## Data Structure + +The JSON file is a map lookup for lowercased mime types. +Each mime type has the following properties: + +- `.source` - where the mime type is defined. + If not set, it's probably a custom media type. + - `apache` - [Apache common media types](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types) + - `iana` - [IANA-defined media types](http://www.iana.org/assignments/media-types/media-types.xhtml) + - `nginx` - [nginx media types](http://hg.nginx.org/nginx/raw-file/default/conf/mime.types) +- `.extensions[]` - known extensions associated with this mime type. +- `.compressible` - whether a file of this type can be gzipped. +- `.charset` - the default charset associated with this type, if any. + +If unknown, every property could be `undefined`. + +## Contributing + +To edit the database, only make PRs against `src/custom-types.json` or +`src/custom-suffix.json`. + +The `src/custom-types.json` file is a JSON object with the MIME type as the +keys and the values being an object with the following keys: + +- `compressible` - leave out if you don't know, otherwise `true`/`false` to + indicate whether the data represented by the type is typically compressible. +- `extensions` - include an array of file extensions that are associated with + the type. +- `notes` - human-readable notes about the type, typically what the type is. +- `sources` - include an array of URLs of where the MIME type and the associated + extensions are sourced from. This needs to be a [primary source](https://en.wikipedia.org/wiki/Primary_source); + links to type aggregating sites and Wikipedia are _not acceptable_. + +To update the build, run `npm run build`. + +### Adding Custom Media Types + +The best way to get new media types included in this library is to register +them with the IANA. The community registration procedure is outlined in +[RFC 6838 section 5](http://tools.ietf.org/html/rfc6838#section-5). Types +registered with the IANA are automatically pulled into this library. + +If that is not possible / feasible, they can be added directly here as a +"custom" type. To do this, it is required to have a primary source that +definitively lists the media type. If an extension is going to be listed as +associateed with this media type, the source must definitively link the +media type and extension as well. + +[ci-image]: https://badgen.net/github/checks/jshttp/mime-db/master?label=ci +[ci-url]: https://github.com/jshttp/mime-db/actions?query=workflow%3Aci +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-db/master +[coveralls-url]: https://coveralls.io/r/jshttp/mime-db?branch=master +[node-image]: https://badgen.net/npm/node/mime-db +[node-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/mime-db +[npm-url]: https://npmjs.org/package/mime-db +[npm-version-image]: https://badgen.net/npm/v/mime-db diff --git a/node_modules/mime-db/db.json b/node_modules/mime-db/db.json new file mode 100644 index 0000000..63c189e --- /dev/null +++ b/node_modules/mime-db/db.json @@ -0,0 +1,8323 @@ +{ + "application/1d-interleaved-parityfec": { + "source": "iana" + }, + "application/3gpdash-qoe-report+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/3gpp-ims+xml": { + "source": "iana", + "compressible": true + }, + "application/a2l": { + "source": "iana" + }, + "application/activemessage": { + "source": "iana" + }, + "application/activity+json": { + "source": "iana", + "compressible": true + }, + "application/alto-costmap+json": { + "source": "iana", + "compressible": true + }, + "application/alto-costmapfilter+json": { + "source": "iana", + "compressible": true + }, + "application/alto-directory+json": { + "source": "iana", + "compressible": true + }, + "application/alto-endpointcost+json": { + "source": "iana", + "compressible": true + }, + "application/alto-endpointcostparams+json": { + "source": "iana", + "compressible": true + }, + "application/alto-endpointprop+json": { + "source": "iana", + "compressible": true + }, + "application/alto-endpointpropparams+json": { + "source": "iana", + "compressible": true + }, + "application/alto-error+json": { + "source": "iana", + "compressible": true + }, + "application/alto-networkmap+json": { + "source": "iana", + "compressible": true + }, + "application/alto-networkmapfilter+json": { + "source": "iana", + "compressible": true + }, + "application/alto-updatestreamcontrol+json": { + "source": "iana", + "compressible": true + }, + "application/alto-updatestreamparams+json": { + "source": "iana", + "compressible": true + }, + "application/aml": { + "source": "iana" + }, + "application/andrew-inset": { + "source": "iana", + "extensions": ["ez"] + }, + "application/applefile": { + "source": "iana" + }, + "application/applixware": { + "source": "apache", + "extensions": ["aw"] + }, + "application/atf": { + "source": "iana" + }, + "application/atfx": { + "source": "iana" + }, + "application/atom+xml": { + "source": "iana", + "compressible": true, + "extensions": ["atom"] + }, + "application/atomcat+xml": { + "source": "iana", + "compressible": true, + "extensions": ["atomcat"] + }, + "application/atomdeleted+xml": { + "source": "iana", + "compressible": true, + "extensions": ["atomdeleted"] + }, + "application/atomicmail": { + "source": "iana" + }, + "application/atomsvc+xml": { + "source": "iana", + "compressible": true, + "extensions": ["atomsvc"] + }, + "application/atsc-dwd+xml": { + "source": "iana", + "compressible": true, + "extensions": ["dwd"] + }, + "application/atsc-dynamic-event-message": { + "source": "iana" + }, + "application/atsc-held+xml": { + "source": "iana", + "compressible": true, + "extensions": ["held"] + }, + "application/atsc-rdt+json": { + "source": "iana", + "compressible": true + }, + "application/atsc-rsat+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rsat"] + }, + "application/atxml": { + "source": "iana" + }, + "application/auth-policy+xml": { + "source": "iana", + "compressible": true + }, + "application/bacnet-xdd+zip": { + "source": "iana", + "compressible": false + }, + "application/batch-smtp": { + "source": "iana" + }, + "application/bdoc": { + "compressible": false, + "extensions": ["bdoc"] + }, + "application/beep+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/calendar+json": { + "source": "iana", + "compressible": true + }, + "application/calendar+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xcs"] + }, + "application/call-completion": { + "source": "iana" + }, + "application/cals-1840": { + "source": "iana" + }, + "application/captive+json": { + "source": "iana", + "compressible": true + }, + "application/cbor": { + "source": "iana" + }, + "application/cbor-seq": { + "source": "iana" + }, + "application/cccex": { + "source": "iana" + }, + "application/ccmp+xml": { + "source": "iana", + "compressible": true + }, + "application/ccxml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["ccxml"] + }, + "application/cdfx+xml": { + "source": "iana", + "compressible": true, + "extensions": ["cdfx"] + }, + "application/cdmi-capability": { + "source": "iana", + "extensions": ["cdmia"] + }, + "application/cdmi-container": { + "source": "iana", + "extensions": ["cdmic"] + }, + "application/cdmi-domain": { + "source": "iana", + "extensions": ["cdmid"] + }, + "application/cdmi-object": { + "source": "iana", + "extensions": ["cdmio"] + }, + "application/cdmi-queue": { + "source": "iana", + "extensions": ["cdmiq"] + }, + "application/cdni": { + "source": "iana" + }, + "application/cea": { + "source": "iana" + }, + "application/cea-2018+xml": { + "source": "iana", + "compressible": true + }, + "application/cellml+xml": { + "source": "iana", + "compressible": true + }, + "application/cfw": { + "source": "iana" + }, + "application/clr": { + "source": "iana" + }, + "application/clue+xml": { + "source": "iana", + "compressible": true + }, + "application/clue_info+xml": { + "source": "iana", + "compressible": true + }, + "application/cms": { + "source": "iana" + }, + "application/cnrp+xml": { + "source": "iana", + "compressible": true + }, + "application/coap-group+json": { + "source": "iana", + "compressible": true + }, + "application/coap-payload": { + "source": "iana" + }, + "application/commonground": { + "source": "iana" + }, + "application/conference-info+xml": { + "source": "iana", + "compressible": true + }, + "application/cose": { + "source": "iana" + }, + "application/cose-key": { + "source": "iana" + }, + "application/cose-key-set": { + "source": "iana" + }, + "application/cpl+xml": { + "source": "iana", + "compressible": true + }, + "application/csrattrs": { + "source": "iana" + }, + "application/csta+xml": { + "source": "iana", + "compressible": true + }, + "application/cstadata+xml": { + "source": "iana", + "compressible": true + }, + "application/csvm+json": { + "source": "iana", + "compressible": true + }, + "application/cu-seeme": { + "source": "apache", + "extensions": ["cu"] + }, + "application/cwt": { + "source": "iana" + }, + "application/cybercash": { + "source": "iana" + }, + "application/dart": { + "compressible": true + }, + "application/dash+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mpd"] + }, + "application/dashdelta": { + "source": "iana" + }, + "application/davmount+xml": { + "source": "iana", + "compressible": true, + "extensions": ["davmount"] + }, + "application/dca-rft": { + "source": "iana" + }, + "application/dcd": { + "source": "iana" + }, + "application/dec-dx": { + "source": "iana" + }, + "application/dialog-info+xml": { + "source": "iana", + "compressible": true + }, + "application/dicom": { + "source": "iana" + }, + "application/dicom+json": { + "source": "iana", + "compressible": true + }, + "application/dicom+xml": { + "source": "iana", + "compressible": true + }, + "application/dii": { + "source": "iana" + }, + "application/dit": { + "source": "iana" + }, + "application/dns": { + "source": "iana" + }, + "application/dns+json": { + "source": "iana", + "compressible": true + }, + "application/dns-message": { + "source": "iana" + }, + "application/docbook+xml": { + "source": "apache", + "compressible": true, + "extensions": ["dbk"] + }, + "application/dots+cbor": { + "source": "iana" + }, + "application/dskpp+xml": { + "source": "iana", + "compressible": true + }, + "application/dssc+der": { + "source": "iana", + "extensions": ["dssc"] + }, + "application/dssc+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xdssc"] + }, + "application/dvcs": { + "source": "iana" + }, + "application/ecmascript": { + "source": "iana", + "compressible": true, + "extensions": ["es","ecma"] + }, + "application/edi-consent": { + "source": "iana" + }, + "application/edi-x12": { + "source": "iana", + "compressible": false + }, + "application/edifact": { + "source": "iana", + "compressible": false + }, + "application/efi": { + "source": "iana" + }, + "application/elm+json": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/elm+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.cap+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/emergencycalldata.comment+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.control+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.deviceinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.ecall.msd": { + "source": "iana" + }, + "application/emergencycalldata.providerinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.serviceinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.subscriberinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/emergencycalldata.veds+xml": { + "source": "iana", + "compressible": true + }, + "application/emma+xml": { + "source": "iana", + "compressible": true, + "extensions": ["emma"] + }, + "application/emotionml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["emotionml"] + }, + "application/encaprtp": { + "source": "iana" + }, + "application/epp+xml": { + "source": "iana", + "compressible": true + }, + "application/epub+zip": { + "source": "iana", + "compressible": false, + "extensions": ["epub"] + }, + "application/eshop": { + "source": "iana" + }, + "application/exi": { + "source": "iana", + "extensions": ["exi"] + }, + "application/expect-ct-report+json": { + "source": "iana", + "compressible": true + }, + "application/fastinfoset": { + "source": "iana" + }, + "application/fastsoap": { + "source": "iana" + }, + "application/fdt+xml": { + "source": "iana", + "compressible": true, + "extensions": ["fdt"] + }, + "application/fhir+json": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/fhir+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/fido.trusted-apps+json": { + "compressible": true + }, + "application/fits": { + "source": "iana" + }, + "application/flexfec": { + "source": "iana" + }, + "application/font-sfnt": { + "source": "iana" + }, + "application/font-tdpfr": { + "source": "iana", + "extensions": ["pfr"] + }, + "application/font-woff": { + "source": "iana", + "compressible": false + }, + "application/framework-attributes+xml": { + "source": "iana", + "compressible": true + }, + "application/geo+json": { + "source": "iana", + "compressible": true, + "extensions": ["geojson"] + }, + "application/geo+json-seq": { + "source": "iana" + }, + "application/geopackage+sqlite3": { + "source": "iana" + }, + "application/geoxacml+xml": { + "source": "iana", + "compressible": true + }, + "application/gltf-buffer": { + "source": "iana" + }, + "application/gml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["gml"] + }, + "application/gpx+xml": { + "source": "apache", + "compressible": true, + "extensions": ["gpx"] + }, + "application/gxf": { + "source": "apache", + "extensions": ["gxf"] + }, + "application/gzip": { + "source": "iana", + "compressible": false, + "extensions": ["gz"] + }, + "application/h224": { + "source": "iana" + }, + "application/held+xml": { + "source": "iana", + "compressible": true + }, + "application/hjson": { + "extensions": ["hjson"] + }, + "application/http": { + "source": "iana" + }, + "application/hyperstudio": { + "source": "iana", + "extensions": ["stk"] + }, + "application/ibe-key-request+xml": { + "source": "iana", + "compressible": true + }, + "application/ibe-pkg-reply+xml": { + "source": "iana", + "compressible": true + }, + "application/ibe-pp-data": { + "source": "iana" + }, + "application/iges": { + "source": "iana" + }, + "application/im-iscomposing+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/index": { + "source": "iana" + }, + "application/index.cmd": { + "source": "iana" + }, + "application/index.obj": { + "source": "iana" + }, + "application/index.response": { + "source": "iana" + }, + "application/index.vnd": { + "source": "iana" + }, + "application/inkml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["ink","inkml"] + }, + "application/iotp": { + "source": "iana" + }, + "application/ipfix": { + "source": "iana", + "extensions": ["ipfix"] + }, + "application/ipp": { + "source": "iana" + }, + "application/isup": { + "source": "iana" + }, + "application/its+xml": { + "source": "iana", + "compressible": true, + "extensions": ["its"] + }, + "application/java-archive": { + "source": "apache", + "compressible": false, + "extensions": ["jar","war","ear"] + }, + "application/java-serialized-object": { + "source": "apache", + "compressible": false, + "extensions": ["ser"] + }, + "application/java-vm": { + "source": "apache", + "compressible": false, + "extensions": ["class"] + }, + "application/javascript": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["js","mjs"] + }, + "application/jf2feed+json": { + "source": "iana", + "compressible": true + }, + "application/jose": { + "source": "iana" + }, + "application/jose+json": { + "source": "iana", + "compressible": true + }, + "application/jrd+json": { + "source": "iana", + "compressible": true + }, + "application/jscalendar+json": { + "source": "iana", + "compressible": true + }, + "application/json": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["json","map"] + }, + "application/json-patch+json": { + "source": "iana", + "compressible": true + }, + "application/json-seq": { + "source": "iana" + }, + "application/json5": { + "extensions": ["json5"] + }, + "application/jsonml+json": { + "source": "apache", + "compressible": true, + "extensions": ["jsonml"] + }, + "application/jwk+json": { + "source": "iana", + "compressible": true + }, + "application/jwk-set+json": { + "source": "iana", + "compressible": true + }, + "application/jwt": { + "source": "iana" + }, + "application/kpml-request+xml": { + "source": "iana", + "compressible": true + }, + "application/kpml-response+xml": { + "source": "iana", + "compressible": true + }, + "application/ld+json": { + "source": "iana", + "compressible": true, + "extensions": ["jsonld"] + }, + "application/lgr+xml": { + "source": "iana", + "compressible": true, + "extensions": ["lgr"] + }, + "application/link-format": { + "source": "iana" + }, + "application/load-control+xml": { + "source": "iana", + "compressible": true + }, + "application/lost+xml": { + "source": "iana", + "compressible": true, + "extensions": ["lostxml"] + }, + "application/lostsync+xml": { + "source": "iana", + "compressible": true + }, + "application/lpf+zip": { + "source": "iana", + "compressible": false + }, + "application/lxf": { + "source": "iana" + }, + "application/mac-binhex40": { + "source": "iana", + "extensions": ["hqx"] + }, + "application/mac-compactpro": { + "source": "apache", + "extensions": ["cpt"] + }, + "application/macwriteii": { + "source": "iana" + }, + "application/mads+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mads"] + }, + "application/manifest+json": { + "charset": "UTF-8", + "compressible": true, + "extensions": ["webmanifest"] + }, + "application/marc": { + "source": "iana", + "extensions": ["mrc"] + }, + "application/marcxml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mrcx"] + }, + "application/mathematica": { + "source": "iana", + "extensions": ["ma","nb","mb"] + }, + "application/mathml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mathml"] + }, + "application/mathml-content+xml": { + "source": "iana", + "compressible": true + }, + "application/mathml-presentation+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-associated-procedure-description+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-deregister+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-envelope+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-msk+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-msk-response+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-protection-description+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-reception-report+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-register+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-register-response+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-schedule+xml": { + "source": "iana", + "compressible": true + }, + "application/mbms-user-service-description+xml": { + "source": "iana", + "compressible": true + }, + "application/mbox": { + "source": "iana", + "extensions": ["mbox"] + }, + "application/media-policy-dataset+xml": { + "source": "iana", + "compressible": true + }, + "application/media_control+xml": { + "source": "iana", + "compressible": true + }, + "application/mediaservercontrol+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mscml"] + }, + "application/merge-patch+json": { + "source": "iana", + "compressible": true + }, + "application/metalink+xml": { + "source": "apache", + "compressible": true, + "extensions": ["metalink"] + }, + "application/metalink4+xml": { + "source": "iana", + "compressible": true, + "extensions": ["meta4"] + }, + "application/mets+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mets"] + }, + "application/mf4": { + "source": "iana" + }, + "application/mikey": { + "source": "iana" + }, + "application/mipc": { + "source": "iana" + }, + "application/mmt-aei+xml": { + "source": "iana", + "compressible": true, + "extensions": ["maei"] + }, + "application/mmt-usd+xml": { + "source": "iana", + "compressible": true, + "extensions": ["musd"] + }, + "application/mods+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mods"] + }, + "application/moss-keys": { + "source": "iana" + }, + "application/moss-signature": { + "source": "iana" + }, + "application/mosskey-data": { + "source": "iana" + }, + "application/mosskey-request": { + "source": "iana" + }, + "application/mp21": { + "source": "iana", + "extensions": ["m21","mp21"] + }, + "application/mp4": { + "source": "iana", + "extensions": ["mp4s","m4p"] + }, + "application/mpeg4-generic": { + "source": "iana" + }, + "application/mpeg4-iod": { + "source": "iana" + }, + "application/mpeg4-iod-xmt": { + "source": "iana" + }, + "application/mrb-consumer+xml": { + "source": "iana", + "compressible": true + }, + "application/mrb-publish+xml": { + "source": "iana", + "compressible": true + }, + "application/msc-ivr+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/msc-mixer+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/msword": { + "source": "iana", + "compressible": false, + "extensions": ["doc","dot"] + }, + "application/mud+json": { + "source": "iana", + "compressible": true + }, + "application/multipart-core": { + "source": "iana" + }, + "application/mxf": { + "source": "iana", + "extensions": ["mxf"] + }, + "application/n-quads": { + "source": "iana", + "extensions": ["nq"] + }, + "application/n-triples": { + "source": "iana", + "extensions": ["nt"] + }, + "application/nasdata": { + "source": "iana" + }, + "application/news-checkgroups": { + "source": "iana", + "charset": "US-ASCII" + }, + "application/news-groupinfo": { + "source": "iana", + "charset": "US-ASCII" + }, + "application/news-transmission": { + "source": "iana" + }, + "application/nlsml+xml": { + "source": "iana", + "compressible": true + }, + "application/node": { + "source": "iana", + "extensions": ["cjs"] + }, + "application/nss": { + "source": "iana" + }, + "application/ocsp-request": { + "source": "iana" + }, + "application/ocsp-response": { + "source": "iana" + }, + "application/octet-stream": { + "source": "iana", + "compressible": false, + "extensions": ["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"] + }, + "application/oda": { + "source": "iana", + "extensions": ["oda"] + }, + "application/odm+xml": { + "source": "iana", + "compressible": true + }, + "application/odx": { + "source": "iana" + }, + "application/oebps-package+xml": { + "source": "iana", + "compressible": true, + "extensions": ["opf"] + }, + "application/ogg": { + "source": "iana", + "compressible": false, + "extensions": ["ogx"] + }, + "application/omdoc+xml": { + "source": "apache", + "compressible": true, + "extensions": ["omdoc"] + }, + "application/onenote": { + "source": "apache", + "extensions": ["onetoc","onetoc2","onetmp","onepkg"] + }, + "application/opc-nodeset+xml": { + "source": "iana", + "compressible": true + }, + "application/oscore": { + "source": "iana" + }, + "application/oxps": { + "source": "iana", + "extensions": ["oxps"] + }, + "application/p2p-overlay+xml": { + "source": "iana", + "compressible": true, + "extensions": ["relo"] + }, + "application/parityfec": { + "source": "iana" + }, + "application/passport": { + "source": "iana" + }, + "application/patch-ops-error+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xer"] + }, + "application/pdf": { + "source": "iana", + "compressible": false, + "extensions": ["pdf"] + }, + "application/pdx": { + "source": "iana" + }, + "application/pem-certificate-chain": { + "source": "iana" + }, + "application/pgp-encrypted": { + "source": "iana", + "compressible": false, + "extensions": ["pgp"] + }, + "application/pgp-keys": { + "source": "iana" + }, + "application/pgp-signature": { + "source": "iana", + "extensions": ["asc","sig"] + }, + "application/pics-rules": { + "source": "apache", + "extensions": ["prf"] + }, + "application/pidf+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/pidf-diff+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/pkcs10": { + "source": "iana", + "extensions": ["p10"] + }, + "application/pkcs12": { + "source": "iana" + }, + "application/pkcs7-mime": { + "source": "iana", + "extensions": ["p7m","p7c"] + }, + "application/pkcs7-signature": { + "source": "iana", + "extensions": ["p7s"] + }, + "application/pkcs8": { + "source": "iana", + "extensions": ["p8"] + }, + "application/pkcs8-encrypted": { + "source": "iana" + }, + "application/pkix-attr-cert": { + "source": "iana", + "extensions": ["ac"] + }, + "application/pkix-cert": { + "source": "iana", + "extensions": ["cer"] + }, + "application/pkix-crl": { + "source": "iana", + "extensions": ["crl"] + }, + "application/pkix-pkipath": { + "source": "iana", + "extensions": ["pkipath"] + }, + "application/pkixcmp": { + "source": "iana", + "extensions": ["pki"] + }, + "application/pls+xml": { + "source": "iana", + "compressible": true, + "extensions": ["pls"] + }, + "application/poc-settings+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/postscript": { + "source": "iana", + "compressible": true, + "extensions": ["ai","eps","ps"] + }, + "application/ppsp-tracker+json": { + "source": "iana", + "compressible": true + }, + "application/problem+json": { + "source": "iana", + "compressible": true + }, + "application/problem+xml": { + "source": "iana", + "compressible": true + }, + "application/provenance+xml": { + "source": "iana", + "compressible": true, + "extensions": ["provx"] + }, + "application/prs.alvestrand.titrax-sheet": { + "source": "iana" + }, + "application/prs.cww": { + "source": "iana", + "extensions": ["cww"] + }, + "application/prs.cyn": { + "source": "iana", + "charset": "7-BIT" + }, + "application/prs.hpub+zip": { + "source": "iana", + "compressible": false + }, + "application/prs.nprend": { + "source": "iana" + }, + "application/prs.plucker": { + "source": "iana" + }, + "application/prs.rdf-xml-crypt": { + "source": "iana" + }, + "application/prs.xsf+xml": { + "source": "iana", + "compressible": true + }, + "application/pskc+xml": { + "source": "iana", + "compressible": true, + "extensions": ["pskcxml"] + }, + "application/pvd+json": { + "source": "iana", + "compressible": true + }, + "application/qsig": { + "source": "iana" + }, + "application/raml+yaml": { + "compressible": true, + "extensions": ["raml"] + }, + "application/raptorfec": { + "source": "iana" + }, + "application/rdap+json": { + "source": "iana", + "compressible": true + }, + "application/rdf+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rdf","owl"] + }, + "application/reginfo+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rif"] + }, + "application/relax-ng-compact-syntax": { + "source": "iana", + "extensions": ["rnc"] + }, + "application/remote-printing": { + "source": "iana" + }, + "application/reputon+json": { + "source": "iana", + "compressible": true + }, + "application/resource-lists+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rl"] + }, + "application/resource-lists-diff+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rld"] + }, + "application/rfc+xml": { + "source": "iana", + "compressible": true + }, + "application/riscos": { + "source": "iana" + }, + "application/rlmi+xml": { + "source": "iana", + "compressible": true + }, + "application/rls-services+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rs"] + }, + "application/route-apd+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rapd"] + }, + "application/route-s-tsid+xml": { + "source": "iana", + "compressible": true, + "extensions": ["sls"] + }, + "application/route-usd+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rusd"] + }, + "application/rpki-ghostbusters": { + "source": "iana", + "extensions": ["gbr"] + }, + "application/rpki-manifest": { + "source": "iana", + "extensions": ["mft"] + }, + "application/rpki-publication": { + "source": "iana" + }, + "application/rpki-roa": { + "source": "iana", + "extensions": ["roa"] + }, + "application/rpki-updown": { + "source": "iana" + }, + "application/rsd+xml": { + "source": "apache", + "compressible": true, + "extensions": ["rsd"] + }, + "application/rss+xml": { + "source": "apache", + "compressible": true, + "extensions": ["rss"] + }, + "application/rtf": { + "source": "iana", + "compressible": true, + "extensions": ["rtf"] + }, + "application/rtploopback": { + "source": "iana" + }, + "application/rtx": { + "source": "iana" + }, + "application/samlassertion+xml": { + "source": "iana", + "compressible": true + }, + "application/samlmetadata+xml": { + "source": "iana", + "compressible": true + }, + "application/sarif+json": { + "source": "iana", + "compressible": true + }, + "application/sbe": { + "source": "iana" + }, + "application/sbml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["sbml"] + }, + "application/scaip+xml": { + "source": "iana", + "compressible": true + }, + "application/scim+json": { + "source": "iana", + "compressible": true + }, + "application/scvp-cv-request": { + "source": "iana", + "extensions": ["scq"] + }, + "application/scvp-cv-response": { + "source": "iana", + "extensions": ["scs"] + }, + "application/scvp-vp-request": { + "source": "iana", + "extensions": ["spq"] + }, + "application/scvp-vp-response": { + "source": "iana", + "extensions": ["spp"] + }, + "application/sdp": { + "source": "iana", + "extensions": ["sdp"] + }, + "application/secevent+jwt": { + "source": "iana" + }, + "application/senml+cbor": { + "source": "iana" + }, + "application/senml+json": { + "source": "iana", + "compressible": true + }, + "application/senml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["senmlx"] + }, + "application/senml-etch+cbor": { + "source": "iana" + }, + "application/senml-etch+json": { + "source": "iana", + "compressible": true + }, + "application/senml-exi": { + "source": "iana" + }, + "application/sensml+cbor": { + "source": "iana" + }, + "application/sensml+json": { + "source": "iana", + "compressible": true + }, + "application/sensml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["sensmlx"] + }, + "application/sensml-exi": { + "source": "iana" + }, + "application/sep+xml": { + "source": "iana", + "compressible": true + }, + "application/sep-exi": { + "source": "iana" + }, + "application/session-info": { + "source": "iana" + }, + "application/set-payment": { + "source": "iana" + }, + "application/set-payment-initiation": { + "source": "iana", + "extensions": ["setpay"] + }, + "application/set-registration": { + "source": "iana" + }, + "application/set-registration-initiation": { + "source": "iana", + "extensions": ["setreg"] + }, + "application/sgml": { + "source": "iana" + }, + "application/sgml-open-catalog": { + "source": "iana" + }, + "application/shf+xml": { + "source": "iana", + "compressible": true, + "extensions": ["shf"] + }, + "application/sieve": { + "source": "iana", + "extensions": ["siv","sieve"] + }, + "application/simple-filter+xml": { + "source": "iana", + "compressible": true + }, + "application/simple-message-summary": { + "source": "iana" + }, + "application/simplesymbolcontainer": { + "source": "iana" + }, + "application/sipc": { + "source": "iana" + }, + "application/slate": { + "source": "iana" + }, + "application/smil": { + "source": "iana" + }, + "application/smil+xml": { + "source": "iana", + "compressible": true, + "extensions": ["smi","smil"] + }, + "application/smpte336m": { + "source": "iana" + }, + "application/soap+fastinfoset": { + "source": "iana" + }, + "application/soap+xml": { + "source": "iana", + "compressible": true + }, + "application/sparql-query": { + "source": "iana", + "extensions": ["rq"] + }, + "application/sparql-results+xml": { + "source": "iana", + "compressible": true, + "extensions": ["srx"] + }, + "application/spirits-event+xml": { + "source": "iana", + "compressible": true + }, + "application/sql": { + "source": "iana" + }, + "application/srgs": { + "source": "iana", + "extensions": ["gram"] + }, + "application/srgs+xml": { + "source": "iana", + "compressible": true, + "extensions": ["grxml"] + }, + "application/sru+xml": { + "source": "iana", + "compressible": true, + "extensions": ["sru"] + }, + "application/ssdl+xml": { + "source": "apache", + "compressible": true, + "extensions": ["ssdl"] + }, + "application/ssml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["ssml"] + }, + "application/stix+json": { + "source": "iana", + "compressible": true + }, + "application/swid+xml": { + "source": "iana", + "compressible": true, + "extensions": ["swidtag"] + }, + "application/tamp-apex-update": { + "source": "iana" + }, + "application/tamp-apex-update-confirm": { + "source": "iana" + }, + "application/tamp-community-update": { + "source": "iana" + }, + "application/tamp-community-update-confirm": { + "source": "iana" + }, + "application/tamp-error": { + "source": "iana" + }, + "application/tamp-sequence-adjust": { + "source": "iana" + }, + "application/tamp-sequence-adjust-confirm": { + "source": "iana" + }, + "application/tamp-status-query": { + "source": "iana" + }, + "application/tamp-status-response": { + "source": "iana" + }, + "application/tamp-update": { + "source": "iana" + }, + "application/tamp-update-confirm": { + "source": "iana" + }, + "application/tar": { + "compressible": true + }, + "application/taxii+json": { + "source": "iana", + "compressible": true + }, + "application/td+json": { + "source": "iana", + "compressible": true + }, + "application/tei+xml": { + "source": "iana", + "compressible": true, + "extensions": ["tei","teicorpus"] + }, + "application/tetra_isi": { + "source": "iana" + }, + "application/thraud+xml": { + "source": "iana", + "compressible": true, + "extensions": ["tfi"] + }, + "application/timestamp-query": { + "source": "iana" + }, + "application/timestamp-reply": { + "source": "iana" + }, + "application/timestamped-data": { + "source": "iana", + "extensions": ["tsd"] + }, + "application/tlsrpt+gzip": { + "source": "iana" + }, + "application/tlsrpt+json": { + "source": "iana", + "compressible": true + }, + "application/tnauthlist": { + "source": "iana" + }, + "application/toml": { + "compressible": true, + "extensions": ["toml"] + }, + "application/trickle-ice-sdpfrag": { + "source": "iana" + }, + "application/trig": { + "source": "iana" + }, + "application/ttml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["ttml"] + }, + "application/tve-trigger": { + "source": "iana" + }, + "application/tzif": { + "source": "iana" + }, + "application/tzif-leap": { + "source": "iana" + }, + "application/ubjson": { + "compressible": false, + "extensions": ["ubj"] + }, + "application/ulpfec": { + "source": "iana" + }, + "application/urc-grpsheet+xml": { + "source": "iana", + "compressible": true + }, + "application/urc-ressheet+xml": { + "source": "iana", + "compressible": true, + "extensions": ["rsheet"] + }, + "application/urc-targetdesc+xml": { + "source": "iana", + "compressible": true, + "extensions": ["td"] + }, + "application/urc-uisocketdesc+xml": { + "source": "iana", + "compressible": true + }, + "application/vcard+json": { + "source": "iana", + "compressible": true + }, + "application/vcard+xml": { + "source": "iana", + "compressible": true + }, + "application/vemmi": { + "source": "iana" + }, + "application/vividence.scriptfile": { + "source": "apache" + }, + "application/vnd.1000minds.decision-model+xml": { + "source": "iana", + "compressible": true, + "extensions": ["1km"] + }, + "application/vnd.3gpp-prose+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp-prose-pc3ch+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp-v2x-local-service-information": { + "source": "iana" + }, + "application/vnd.3gpp.access-transfer-events+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.bsf+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.gmop+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.interworking-data": { + "source": "iana" + }, + "application/vnd.3gpp.mc-signalling-ear": { + "source": "iana" + }, + "application/vnd.3gpp.mcdata-affiliation-command+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcdata-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcdata-payload": { + "source": "iana" + }, + "application/vnd.3gpp.mcdata-service-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcdata-signalling": { + "source": "iana" + }, + "application/vnd.3gpp.mcdata-ue-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcdata-user-profile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-affiliation-command+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-floor-request+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-location-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-mbms-usage-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-service-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-signed+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-ue-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-ue-init-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcptt-user-profile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-affiliation-command+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-affiliation-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-location-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-mbms-usage-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-service-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-transmission-request+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-ue-config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mcvideo-user-profile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.mid-call+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.pic-bw-large": { + "source": "iana", + "extensions": ["plb"] + }, + "application/vnd.3gpp.pic-bw-small": { + "source": "iana", + "extensions": ["psb"] + }, + "application/vnd.3gpp.pic-bw-var": { + "source": "iana", + "extensions": ["pvb"] + }, + "application/vnd.3gpp.sms": { + "source": "iana" + }, + "application/vnd.3gpp.sms+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.srvcc-ext+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.srvcc-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.state-and-event-info+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp.ussd+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp2.bcmcsinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.3gpp2.sms": { + "source": "iana" + }, + "application/vnd.3gpp2.tcap": { + "source": "iana", + "extensions": ["tcap"] + }, + "application/vnd.3lightssoftware.imagescal": { + "source": "iana" + }, + "application/vnd.3m.post-it-notes": { + "source": "iana", + "extensions": ["pwn"] + }, + "application/vnd.accpac.simply.aso": { + "source": "iana", + "extensions": ["aso"] + }, + "application/vnd.accpac.simply.imp": { + "source": "iana", + "extensions": ["imp"] + }, + "application/vnd.acucobol": { + "source": "iana", + "extensions": ["acu"] + }, + "application/vnd.acucorp": { + "source": "iana", + "extensions": ["atc","acutc"] + }, + "application/vnd.adobe.air-application-installer-package+zip": { + "source": "apache", + "compressible": false, + "extensions": ["air"] + }, + "application/vnd.adobe.flash.movie": { + "source": "iana" + }, + "application/vnd.adobe.formscentral.fcdt": { + "source": "iana", + "extensions": ["fcdt"] + }, + "application/vnd.adobe.fxp": { + "source": "iana", + "extensions": ["fxp","fxpl"] + }, + "application/vnd.adobe.partial-upload": { + "source": "iana" + }, + "application/vnd.adobe.xdp+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xdp"] + }, + "application/vnd.adobe.xfdf": { + "source": "iana", + "extensions": ["xfdf"] + }, + "application/vnd.aether.imp": { + "source": "iana" + }, + "application/vnd.afpc.afplinedata": { + "source": "iana" + }, + "application/vnd.afpc.afplinedata-pagedef": { + "source": "iana" + }, + "application/vnd.afpc.cmoca-cmresource": { + "source": "iana" + }, + "application/vnd.afpc.foca-charset": { + "source": "iana" + }, + "application/vnd.afpc.foca-codedfont": { + "source": "iana" + }, + "application/vnd.afpc.foca-codepage": { + "source": "iana" + }, + "application/vnd.afpc.modca": { + "source": "iana" + }, + "application/vnd.afpc.modca-cmtable": { + "source": "iana" + }, + "application/vnd.afpc.modca-formdef": { + "source": "iana" + }, + "application/vnd.afpc.modca-mediummap": { + "source": "iana" + }, + "application/vnd.afpc.modca-objectcontainer": { + "source": "iana" + }, + "application/vnd.afpc.modca-overlay": { + "source": "iana" + }, + "application/vnd.afpc.modca-pagesegment": { + "source": "iana" + }, + "application/vnd.ah-barcode": { + "source": "iana" + }, + "application/vnd.ahead.space": { + "source": "iana", + "extensions": ["ahead"] + }, + "application/vnd.airzip.filesecure.azf": { + "source": "iana", + "extensions": ["azf"] + }, + "application/vnd.airzip.filesecure.azs": { + "source": "iana", + "extensions": ["azs"] + }, + "application/vnd.amadeus+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.amazon.ebook": { + "source": "apache", + "extensions": ["azw"] + }, + "application/vnd.amazon.mobi8-ebook": { + "source": "iana" + }, + "application/vnd.americandynamics.acc": { + "source": "iana", + "extensions": ["acc"] + }, + "application/vnd.amiga.ami": { + "source": "iana", + "extensions": ["ami"] + }, + "application/vnd.amundsen.maze+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.android.ota": { + "source": "iana" + }, + "application/vnd.android.package-archive": { + "source": "apache", + "compressible": false, + "extensions": ["apk"] + }, + "application/vnd.anki": { + "source": "iana" + }, + "application/vnd.anser-web-certificate-issue-initiation": { + "source": "iana", + "extensions": ["cii"] + }, + "application/vnd.anser-web-funds-transfer-initiation": { + "source": "apache", + "extensions": ["fti"] + }, + "application/vnd.antix.game-component": { + "source": "iana", + "extensions": ["atx"] + }, + "application/vnd.apache.thrift.binary": { + "source": "iana" + }, + "application/vnd.apache.thrift.compact": { + "source": "iana" + }, + "application/vnd.apache.thrift.json": { + "source": "iana" + }, + "application/vnd.api+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.aplextor.warrp+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.apothekende.reservation+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.apple.installer+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mpkg"] + }, + "application/vnd.apple.keynote": { + "source": "iana", + "extensions": ["key"] + }, + "application/vnd.apple.mpegurl": { + "source": "iana", + "extensions": ["m3u8"] + }, + "application/vnd.apple.numbers": { + "source": "iana", + "extensions": ["numbers"] + }, + "application/vnd.apple.pages": { + "source": "iana", + "extensions": ["pages"] + }, + "application/vnd.apple.pkpass": { + "compressible": false, + "extensions": ["pkpass"] + }, + "application/vnd.arastra.swi": { + "source": "iana" + }, + "application/vnd.aristanetworks.swi": { + "source": "iana", + "extensions": ["swi"] + }, + "application/vnd.artisan+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.artsquare": { + "source": "iana" + }, + "application/vnd.astraea-software.iota": { + "source": "iana", + "extensions": ["iota"] + }, + "application/vnd.audiograph": { + "source": "iana", + "extensions": ["aep"] + }, + "application/vnd.autopackage": { + "source": "iana" + }, + "application/vnd.avalon+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.avistar+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.balsamiq.bmml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["bmml"] + }, + "application/vnd.balsamiq.bmpr": { + "source": "iana" + }, + "application/vnd.banana-accounting": { + "source": "iana" + }, + "application/vnd.bbf.usp.error": { + "source": "iana" + }, + "application/vnd.bbf.usp.msg": { + "source": "iana" + }, + "application/vnd.bbf.usp.msg+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.bekitzur-stech+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.bint.med-content": { + "source": "iana" + }, + "application/vnd.biopax.rdf+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.blink-idb-value-wrapper": { + "source": "iana" + }, + "application/vnd.blueice.multipass": { + "source": "iana", + "extensions": ["mpm"] + }, + "application/vnd.bluetooth.ep.oob": { + "source": "iana" + }, + "application/vnd.bluetooth.le.oob": { + "source": "iana" + }, + "application/vnd.bmi": { + "source": "iana", + "extensions": ["bmi"] + }, + "application/vnd.bpf": { + "source": "iana" + }, + "application/vnd.bpf3": { + "source": "iana" + }, + "application/vnd.businessobjects": { + "source": "iana", + "extensions": ["rep"] + }, + "application/vnd.byu.uapi+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.cab-jscript": { + "source": "iana" + }, + "application/vnd.canon-cpdl": { + "source": "iana" + }, + "application/vnd.canon-lips": { + "source": "iana" + }, + "application/vnd.capasystems-pg+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.cendio.thinlinc.clientconf": { + "source": "iana" + }, + "application/vnd.century-systems.tcp_stream": { + "source": "iana" + }, + "application/vnd.chemdraw+xml": { + "source": "iana", + "compressible": true, + "extensions": ["cdxml"] + }, + "application/vnd.chess-pgn": { + "source": "iana" + }, + "application/vnd.chipnuts.karaoke-mmd": { + "source": "iana", + "extensions": ["mmd"] + }, + "application/vnd.ciedi": { + "source": "iana" + }, + "application/vnd.cinderella": { + "source": "iana", + "extensions": ["cdy"] + }, + "application/vnd.cirpack.isdn-ext": { + "source": "iana" + }, + "application/vnd.citationstyles.style+xml": { + "source": "iana", + "compressible": true, + "extensions": ["csl"] + }, + "application/vnd.claymore": { + "source": "iana", + "extensions": ["cla"] + }, + "application/vnd.cloanto.rp9": { + "source": "iana", + "extensions": ["rp9"] + }, + "application/vnd.clonk.c4group": { + "source": "iana", + "extensions": ["c4g","c4d","c4f","c4p","c4u"] + }, + "application/vnd.cluetrust.cartomobile-config": { + "source": "iana", + "extensions": ["c11amc"] + }, + "application/vnd.cluetrust.cartomobile-config-pkg": { + "source": "iana", + "extensions": ["c11amz"] + }, + "application/vnd.coffeescript": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.document": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.document-template": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.presentation": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.presentation-template": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.spreadsheet": { + "source": "iana" + }, + "application/vnd.collabio.xodocuments.spreadsheet-template": { + "source": "iana" + }, + "application/vnd.collection+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.collection.doc+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.collection.next+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.comicbook+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.comicbook-rar": { + "source": "iana" + }, + "application/vnd.commerce-battelle": { + "source": "iana" + }, + "application/vnd.commonspace": { + "source": "iana", + "extensions": ["csp"] + }, + "application/vnd.contact.cmsg": { + "source": "iana", + "extensions": ["cdbcmsg"] + }, + "application/vnd.coreos.ignition+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.cosmocaller": { + "source": "iana", + "extensions": ["cmc"] + }, + "application/vnd.crick.clicker": { + "source": "iana", + "extensions": ["clkx"] + }, + "application/vnd.crick.clicker.keyboard": { + "source": "iana", + "extensions": ["clkk"] + }, + "application/vnd.crick.clicker.palette": { + "source": "iana", + "extensions": ["clkp"] + }, + "application/vnd.crick.clicker.template": { + "source": "iana", + "extensions": ["clkt"] + }, + "application/vnd.crick.clicker.wordbank": { + "source": "iana", + "extensions": ["clkw"] + }, + "application/vnd.criticaltools.wbs+xml": { + "source": "iana", + "compressible": true, + "extensions": ["wbs"] + }, + "application/vnd.cryptii.pipe+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.crypto-shade-file": { + "source": "iana" + }, + "application/vnd.cryptomator.encrypted": { + "source": "iana" + }, + "application/vnd.ctc-posml": { + "source": "iana", + "extensions": ["pml"] + }, + "application/vnd.ctct.ws+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.cups-pdf": { + "source": "iana" + }, + "application/vnd.cups-postscript": { + "source": "iana" + }, + "application/vnd.cups-ppd": { + "source": "iana", + "extensions": ["ppd"] + }, + "application/vnd.cups-raster": { + "source": "iana" + }, + "application/vnd.cups-raw": { + "source": "iana" + }, + "application/vnd.curl": { + "source": "iana" + }, + "application/vnd.curl.car": { + "source": "apache", + "extensions": ["car"] + }, + "application/vnd.curl.pcurl": { + "source": "apache", + "extensions": ["pcurl"] + }, + "application/vnd.cyan.dean.root+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.cybank": { + "source": "iana" + }, + "application/vnd.cyclonedx+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.cyclonedx+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.d2l.coursepackage1p0+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.d3m-dataset": { + "source": "iana" + }, + "application/vnd.d3m-problem": { + "source": "iana" + }, + "application/vnd.dart": { + "source": "iana", + "compressible": true, + "extensions": ["dart"] + }, + "application/vnd.data-vision.rdz": { + "source": "iana", + "extensions": ["rdz"] + }, + "application/vnd.datapackage+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.dataresource+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.dbf": { + "source": "iana", + "extensions": ["dbf"] + }, + "application/vnd.debian.binary-package": { + "source": "iana" + }, + "application/vnd.dece.data": { + "source": "iana", + "extensions": ["uvf","uvvf","uvd","uvvd"] + }, + "application/vnd.dece.ttml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["uvt","uvvt"] + }, + "application/vnd.dece.unspecified": { + "source": "iana", + "extensions": ["uvx","uvvx"] + }, + "application/vnd.dece.zip": { + "source": "iana", + "extensions": ["uvz","uvvz"] + }, + "application/vnd.denovo.fcselayout-link": { + "source": "iana", + "extensions": ["fe_launch"] + }, + "application/vnd.desmume.movie": { + "source": "iana" + }, + "application/vnd.dir-bi.plate-dl-nosuffix": { + "source": "iana" + }, + "application/vnd.dm.delegation+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dna": { + "source": "iana", + "extensions": ["dna"] + }, + "application/vnd.document+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.dolby.mlp": { + "source": "apache", + "extensions": ["mlp"] + }, + "application/vnd.dolby.mobile.1": { + "source": "iana" + }, + "application/vnd.dolby.mobile.2": { + "source": "iana" + }, + "application/vnd.doremir.scorecloud-binary-document": { + "source": "iana" + }, + "application/vnd.dpgraph": { + "source": "iana", + "extensions": ["dpg"] + }, + "application/vnd.dreamfactory": { + "source": "iana", + "extensions": ["dfac"] + }, + "application/vnd.drive+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ds-keypoint": { + "source": "apache", + "extensions": ["kpxx"] + }, + "application/vnd.dtg.local": { + "source": "iana" + }, + "application/vnd.dtg.local.flash": { + "source": "iana" + }, + "application/vnd.dtg.local.html": { + "source": "iana" + }, + "application/vnd.dvb.ait": { + "source": "iana", + "extensions": ["ait"] + }, + "application/vnd.dvb.dvbisl+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.dvbj": { + "source": "iana" + }, + "application/vnd.dvb.esgcontainer": { + "source": "iana" + }, + "application/vnd.dvb.ipdcdftnotifaccess": { + "source": "iana" + }, + "application/vnd.dvb.ipdcesgaccess": { + "source": "iana" + }, + "application/vnd.dvb.ipdcesgaccess2": { + "source": "iana" + }, + "application/vnd.dvb.ipdcesgpdd": { + "source": "iana" + }, + "application/vnd.dvb.ipdcroaming": { + "source": "iana" + }, + "application/vnd.dvb.iptv.alfec-base": { + "source": "iana" + }, + "application/vnd.dvb.iptv.alfec-enhancement": { + "source": "iana" + }, + "application/vnd.dvb.notif-aggregate-root+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-container+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-generic+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-ia-msglist+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-ia-registration-request+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-ia-registration-response+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.notif-init+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.dvb.pfr": { + "source": "iana" + }, + "application/vnd.dvb.service": { + "source": "iana", + "extensions": ["svc"] + }, + "application/vnd.dxr": { + "source": "iana" + }, + "application/vnd.dynageo": { + "source": "iana", + "extensions": ["geo"] + }, + "application/vnd.dzr": { + "source": "iana" + }, + "application/vnd.easykaraoke.cdgdownload": { + "source": "iana" + }, + "application/vnd.ecdis-update": { + "source": "iana" + }, + "application/vnd.ecip.rlp": { + "source": "iana" + }, + "application/vnd.ecowin.chart": { + "source": "iana", + "extensions": ["mag"] + }, + "application/vnd.ecowin.filerequest": { + "source": "iana" + }, + "application/vnd.ecowin.fileupdate": { + "source": "iana" + }, + "application/vnd.ecowin.series": { + "source": "iana" + }, + "application/vnd.ecowin.seriesrequest": { + "source": "iana" + }, + "application/vnd.ecowin.seriesupdate": { + "source": "iana" + }, + "application/vnd.efi.img": { + "source": "iana" + }, + "application/vnd.efi.iso": { + "source": "iana" + }, + "application/vnd.emclient.accessrequest+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.enliven": { + "source": "iana", + "extensions": ["nml"] + }, + "application/vnd.enphase.envoy": { + "source": "iana" + }, + "application/vnd.eprints.data+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.epson.esf": { + "source": "iana", + "extensions": ["esf"] + }, + "application/vnd.epson.msf": { + "source": "iana", + "extensions": ["msf"] + }, + "application/vnd.epson.quickanime": { + "source": "iana", + "extensions": ["qam"] + }, + "application/vnd.epson.salt": { + "source": "iana", + "extensions": ["slt"] + }, + "application/vnd.epson.ssf": { + "source": "iana", + "extensions": ["ssf"] + }, + "application/vnd.ericsson.quickcall": { + "source": "iana" + }, + "application/vnd.espass-espass+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.eszigno3+xml": { + "source": "iana", + "compressible": true, + "extensions": ["es3","et3"] + }, + "application/vnd.etsi.aoc+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.asic-e+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.etsi.asic-s+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.etsi.cug+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvcommand+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvdiscovery+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvprofile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvsad-bc+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvsad-cod+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvsad-npvr+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvservice+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvsync+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.iptvueprofile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.mcid+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.mheg5": { + "source": "iana" + }, + "application/vnd.etsi.overload-control-policy-dataset+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.pstn+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.sci+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.simservs+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.timestamp-token": { + "source": "iana" + }, + "application/vnd.etsi.tsl+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.etsi.tsl.der": { + "source": "iana" + }, + "application/vnd.eudora.data": { + "source": "iana" + }, + "application/vnd.evolv.ecig.profile": { + "source": "iana" + }, + "application/vnd.evolv.ecig.settings": { + "source": "iana" + }, + "application/vnd.evolv.ecig.theme": { + "source": "iana" + }, + "application/vnd.exstream-empower+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.exstream-package": { + "source": "iana" + }, + "application/vnd.ezpix-album": { + "source": "iana", + "extensions": ["ez2"] + }, + "application/vnd.ezpix-package": { + "source": "iana", + "extensions": ["ez3"] + }, + "application/vnd.f-secure.mobile": { + "source": "iana" + }, + "application/vnd.fastcopy-disk-image": { + "source": "iana" + }, + "application/vnd.fdf": { + "source": "iana", + "extensions": ["fdf"] + }, + "application/vnd.fdsn.mseed": { + "source": "iana", + "extensions": ["mseed"] + }, + "application/vnd.fdsn.seed": { + "source": "iana", + "extensions": ["seed","dataless"] + }, + "application/vnd.ffsns": { + "source": "iana" + }, + "application/vnd.ficlab.flb+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.filmit.zfc": { + "source": "iana" + }, + "application/vnd.fints": { + "source": "iana" + }, + "application/vnd.firemonkeys.cloudcell": { + "source": "iana" + }, + "application/vnd.flographit": { + "source": "iana", + "extensions": ["gph"] + }, + "application/vnd.fluxtime.clip": { + "source": "iana", + "extensions": ["ftc"] + }, + "application/vnd.font-fontforge-sfd": { + "source": "iana" + }, + "application/vnd.framemaker": { + "source": "iana", + "extensions": ["fm","frame","maker","book"] + }, + "application/vnd.frogans.fnc": { + "source": "iana", + "extensions": ["fnc"] + }, + "application/vnd.frogans.ltf": { + "source": "iana", + "extensions": ["ltf"] + }, + "application/vnd.fsc.weblaunch": { + "source": "iana", + "extensions": ["fsc"] + }, + "application/vnd.fujitsu.oasys": { + "source": "iana", + "extensions": ["oas"] + }, + "application/vnd.fujitsu.oasys2": { + "source": "iana", + "extensions": ["oa2"] + }, + "application/vnd.fujitsu.oasys3": { + "source": "iana", + "extensions": ["oa3"] + }, + "application/vnd.fujitsu.oasysgp": { + "source": "iana", + "extensions": ["fg5"] + }, + "application/vnd.fujitsu.oasysprs": { + "source": "iana", + "extensions": ["bh2"] + }, + "application/vnd.fujixerox.art-ex": { + "source": "iana" + }, + "application/vnd.fujixerox.art4": { + "source": "iana" + }, + "application/vnd.fujixerox.ddd": { + "source": "iana", + "extensions": ["ddd"] + }, + "application/vnd.fujixerox.docuworks": { + "source": "iana", + "extensions": ["xdw"] + }, + "application/vnd.fujixerox.docuworks.binder": { + "source": "iana", + "extensions": ["xbd"] + }, + "application/vnd.fujixerox.docuworks.container": { + "source": "iana" + }, + "application/vnd.fujixerox.hbpl": { + "source": "iana" + }, + "application/vnd.fut-misnet": { + "source": "iana" + }, + "application/vnd.futoin+cbor": { + "source": "iana" + }, + "application/vnd.futoin+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.fuzzysheet": { + "source": "iana", + "extensions": ["fzs"] + }, + "application/vnd.genomatix.tuxedo": { + "source": "iana", + "extensions": ["txd"] + }, + "application/vnd.gentics.grd+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.geo+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.geocube+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.geogebra.file": { + "source": "iana", + "extensions": ["ggb"] + }, + "application/vnd.geogebra.slides": { + "source": "iana" + }, + "application/vnd.geogebra.tool": { + "source": "iana", + "extensions": ["ggt"] + }, + "application/vnd.geometry-explorer": { + "source": "iana", + "extensions": ["gex","gre"] + }, + "application/vnd.geonext": { + "source": "iana", + "extensions": ["gxt"] + }, + "application/vnd.geoplan": { + "source": "iana", + "extensions": ["g2w"] + }, + "application/vnd.geospace": { + "source": "iana", + "extensions": ["g3w"] + }, + "application/vnd.gerber": { + "source": "iana" + }, + "application/vnd.globalplatform.card-content-mgt": { + "source": "iana" + }, + "application/vnd.globalplatform.card-content-mgt-response": { + "source": "iana" + }, + "application/vnd.gmx": { + "source": "iana", + "extensions": ["gmx"] + }, + "application/vnd.google-apps.document": { + "compressible": false, + "extensions": ["gdoc"] + }, + "application/vnd.google-apps.presentation": { + "compressible": false, + "extensions": ["gslides"] + }, + "application/vnd.google-apps.spreadsheet": { + "compressible": false, + "extensions": ["gsheet"] + }, + "application/vnd.google-earth.kml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["kml"] + }, + "application/vnd.google-earth.kmz": { + "source": "iana", + "compressible": false, + "extensions": ["kmz"] + }, + "application/vnd.gov.sk.e-form+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.gov.sk.e-form+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.gov.sk.xmldatacontainer+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.grafeq": { + "source": "iana", + "extensions": ["gqf","gqs"] + }, + "application/vnd.gridmp": { + "source": "iana" + }, + "application/vnd.groove-account": { + "source": "iana", + "extensions": ["gac"] + }, + "application/vnd.groove-help": { + "source": "iana", + "extensions": ["ghf"] + }, + "application/vnd.groove-identity-message": { + "source": "iana", + "extensions": ["gim"] + }, + "application/vnd.groove-injector": { + "source": "iana", + "extensions": ["grv"] + }, + "application/vnd.groove-tool-message": { + "source": "iana", + "extensions": ["gtm"] + }, + "application/vnd.groove-tool-template": { + "source": "iana", + "extensions": ["tpl"] + }, + "application/vnd.groove-vcard": { + "source": "iana", + "extensions": ["vcg"] + }, + "application/vnd.hal+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hal+xml": { + "source": "iana", + "compressible": true, + "extensions": ["hal"] + }, + "application/vnd.handheld-entertainment+xml": { + "source": "iana", + "compressible": true, + "extensions": ["zmm"] + }, + "application/vnd.hbci": { + "source": "iana", + "extensions": ["hbci"] + }, + "application/vnd.hc+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hcl-bireports": { + "source": "iana" + }, + "application/vnd.hdt": { + "source": "iana" + }, + "application/vnd.heroku+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hhe.lesson-player": { + "source": "iana", + "extensions": ["les"] + }, + "application/vnd.hp-hpgl": { + "source": "iana", + "extensions": ["hpgl"] + }, + "application/vnd.hp-hpid": { + "source": "iana", + "extensions": ["hpid"] + }, + "application/vnd.hp-hps": { + "source": "iana", + "extensions": ["hps"] + }, + "application/vnd.hp-jlyt": { + "source": "iana", + "extensions": ["jlt"] + }, + "application/vnd.hp-pcl": { + "source": "iana", + "extensions": ["pcl"] + }, + "application/vnd.hp-pclxl": { + "source": "iana", + "extensions": ["pclxl"] + }, + "application/vnd.httphone": { + "source": "iana" + }, + "application/vnd.hydrostatix.sof-data": { + "source": "iana", + "extensions": ["sfd-hdstx"] + }, + "application/vnd.hyper+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hyper-item+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hyperdrive+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.hzn-3d-crossword": { + "source": "iana" + }, + "application/vnd.ibm.afplinedata": { + "source": "iana" + }, + "application/vnd.ibm.electronic-media": { + "source": "iana" + }, + "application/vnd.ibm.minipay": { + "source": "iana", + "extensions": ["mpy"] + }, + "application/vnd.ibm.modcap": { + "source": "iana", + "extensions": ["afp","listafp","list3820"] + }, + "application/vnd.ibm.rights-management": { + "source": "iana", + "extensions": ["irm"] + }, + "application/vnd.ibm.secure-container": { + "source": "iana", + "extensions": ["sc"] + }, + "application/vnd.iccprofile": { + "source": "iana", + "extensions": ["icc","icm"] + }, + "application/vnd.ieee.1905": { + "source": "iana" + }, + "application/vnd.igloader": { + "source": "iana", + "extensions": ["igl"] + }, + "application/vnd.imagemeter.folder+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.imagemeter.image+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.immervision-ivp": { + "source": "iana", + "extensions": ["ivp"] + }, + "application/vnd.immervision-ivu": { + "source": "iana", + "extensions": ["ivu"] + }, + "application/vnd.ims.imsccv1p1": { + "source": "iana" + }, + "application/vnd.ims.imsccv1p2": { + "source": "iana" + }, + "application/vnd.ims.imsccv1p3": { + "source": "iana" + }, + "application/vnd.ims.lis.v2.result+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ims.lti.v2.toolconsumerprofile+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ims.lti.v2.toolproxy+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ims.lti.v2.toolproxy.id+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ims.lti.v2.toolsettings+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.ims.lti.v2.toolsettings.simple+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.informedcontrol.rms+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.informix-visionary": { + "source": "iana" + }, + "application/vnd.infotech.project": { + "source": "iana" + }, + "application/vnd.infotech.project+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.innopath.wamp.notification": { + "source": "iana" + }, + "application/vnd.insors.igm": { + "source": "iana", + "extensions": ["igm"] + }, + "application/vnd.intercon.formnet": { + "source": "iana", + "extensions": ["xpw","xpx"] + }, + "application/vnd.intergeo": { + "source": "iana", + "extensions": ["i2g"] + }, + "application/vnd.intertrust.digibox": { + "source": "iana" + }, + "application/vnd.intertrust.nncp": { + "source": "iana" + }, + "application/vnd.intu.qbo": { + "source": "iana", + "extensions": ["qbo"] + }, + "application/vnd.intu.qfx": { + "source": "iana", + "extensions": ["qfx"] + }, + "application/vnd.iptc.g2.catalogitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.conceptitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.knowledgeitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.newsitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.newsmessage+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.packageitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.iptc.g2.planningitem+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.ipunplugged.rcprofile": { + "source": "iana", + "extensions": ["rcprofile"] + }, + "application/vnd.irepository.package+xml": { + "source": "iana", + "compressible": true, + "extensions": ["irp"] + }, + "application/vnd.is-xpr": { + "source": "iana", + "extensions": ["xpr"] + }, + "application/vnd.isac.fcs": { + "source": "iana", + "extensions": ["fcs"] + }, + "application/vnd.iso11783-10+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.jam": { + "source": "iana", + "extensions": ["jam"] + }, + "application/vnd.japannet-directory-service": { + "source": "iana" + }, + "application/vnd.japannet-jpnstore-wakeup": { + "source": "iana" + }, + "application/vnd.japannet-payment-wakeup": { + "source": "iana" + }, + "application/vnd.japannet-registration": { + "source": "iana" + }, + "application/vnd.japannet-registration-wakeup": { + "source": "iana" + }, + "application/vnd.japannet-setstore-wakeup": { + "source": "iana" + }, + "application/vnd.japannet-verification": { + "source": "iana" + }, + "application/vnd.japannet-verification-wakeup": { + "source": "iana" + }, + "application/vnd.jcp.javame.midlet-rms": { + "source": "iana", + "extensions": ["rms"] + }, + "application/vnd.jisp": { + "source": "iana", + "extensions": ["jisp"] + }, + "application/vnd.joost.joda-archive": { + "source": "iana", + "extensions": ["joda"] + }, + "application/vnd.jsk.isdn-ngn": { + "source": "iana" + }, + "application/vnd.kahootz": { + "source": "iana", + "extensions": ["ktz","ktr"] + }, + "application/vnd.kde.karbon": { + "source": "iana", + "extensions": ["karbon"] + }, + "application/vnd.kde.kchart": { + "source": "iana", + "extensions": ["chrt"] + }, + "application/vnd.kde.kformula": { + "source": "iana", + "extensions": ["kfo"] + }, + "application/vnd.kde.kivio": { + "source": "iana", + "extensions": ["flw"] + }, + "application/vnd.kde.kontour": { + "source": "iana", + "extensions": ["kon"] + }, + "application/vnd.kde.kpresenter": { + "source": "iana", + "extensions": ["kpr","kpt"] + }, + "application/vnd.kde.kspread": { + "source": "iana", + "extensions": ["ksp"] + }, + "application/vnd.kde.kword": { + "source": "iana", + "extensions": ["kwd","kwt"] + }, + "application/vnd.kenameaapp": { + "source": "iana", + "extensions": ["htke"] + }, + "application/vnd.kidspiration": { + "source": "iana", + "extensions": ["kia"] + }, + "application/vnd.kinar": { + "source": "iana", + "extensions": ["kne","knp"] + }, + "application/vnd.koan": { + "source": "iana", + "extensions": ["skp","skd","skt","skm"] + }, + "application/vnd.kodak-descriptor": { + "source": "iana", + "extensions": ["sse"] + }, + "application/vnd.las": { + "source": "iana" + }, + "application/vnd.las.las+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.las.las+xml": { + "source": "iana", + "compressible": true, + "extensions": ["lasxml"] + }, + "application/vnd.laszip": { + "source": "iana" + }, + "application/vnd.leap+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.liberty-request+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.llamagraphics.life-balance.desktop": { + "source": "iana", + "extensions": ["lbd"] + }, + "application/vnd.llamagraphics.life-balance.exchange+xml": { + "source": "iana", + "compressible": true, + "extensions": ["lbe"] + }, + "application/vnd.logipipe.circuit+zip": { + "source": "iana", + "compressible": false + }, + "application/vnd.loom": { + "source": "iana" + }, + "application/vnd.lotus-1-2-3": { + "source": "iana", + "extensions": ["123"] + }, + "application/vnd.lotus-approach": { + "source": "iana", + "extensions": ["apr"] + }, + "application/vnd.lotus-freelance": { + "source": "iana", + "extensions": ["pre"] + }, + "application/vnd.lotus-notes": { + "source": "iana", + "extensions": ["nsf"] + }, + "application/vnd.lotus-organizer": { + "source": "iana", + "extensions": ["org"] + }, + "application/vnd.lotus-screencam": { + "source": "iana", + "extensions": ["scm"] + }, + "application/vnd.lotus-wordpro": { + "source": "iana", + "extensions": ["lwp"] + }, + "application/vnd.macports.portpkg": { + "source": "iana", + "extensions": ["portpkg"] + }, + "application/vnd.mapbox-vector-tile": { + "source": "iana" + }, + "application/vnd.marlin.drm.actiontoken+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.marlin.drm.conftoken+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.marlin.drm.license+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.marlin.drm.mdcf": { + "source": "iana" + }, + "application/vnd.mason+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.maxmind.maxmind-db": { + "source": "iana" + }, + "application/vnd.mcd": { + "source": "iana", + "extensions": ["mcd"] + }, + "application/vnd.medcalcdata": { + "source": "iana", + "extensions": ["mc1"] + }, + "application/vnd.mediastation.cdkey": { + "source": "iana", + "extensions": ["cdkey"] + }, + "application/vnd.meridian-slingshot": { + "source": "iana" + }, + "application/vnd.mfer": { + "source": "iana", + "extensions": ["mwf"] + }, + "application/vnd.mfmp": { + "source": "iana", + "extensions": ["mfm"] + }, + "application/vnd.micro+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.micrografx.flo": { + "source": "iana", + "extensions": ["flo"] + }, + "application/vnd.micrografx.igx": { + "source": "iana", + "extensions": ["igx"] + }, + "application/vnd.microsoft.portable-executable": { + "source": "iana" + }, + "application/vnd.microsoft.windows.thumbnail-cache": { + "source": "iana" + }, + "application/vnd.miele+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.mif": { + "source": "iana", + "extensions": ["mif"] + }, + "application/vnd.minisoft-hp3000-save": { + "source": "iana" + }, + "application/vnd.mitsubishi.misty-guard.trustweb": { + "source": "iana" + }, + "application/vnd.mobius.daf": { + "source": "iana", + "extensions": ["daf"] + }, + "application/vnd.mobius.dis": { + "source": "iana", + "extensions": ["dis"] + }, + "application/vnd.mobius.mbk": { + "source": "iana", + "extensions": ["mbk"] + }, + "application/vnd.mobius.mqy": { + "source": "iana", + "extensions": ["mqy"] + }, + "application/vnd.mobius.msl": { + "source": "iana", + "extensions": ["msl"] + }, + "application/vnd.mobius.plc": { + "source": "iana", + "extensions": ["plc"] + }, + "application/vnd.mobius.txf": { + "source": "iana", + "extensions": ["txf"] + }, + "application/vnd.mophun.application": { + "source": "iana", + "extensions": ["mpn"] + }, + "application/vnd.mophun.certificate": { + "source": "iana", + "extensions": ["mpc"] + }, + "application/vnd.motorola.flexsuite": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.adsi": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.fis": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.gotap": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.kmr": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.ttc": { + "source": "iana" + }, + "application/vnd.motorola.flexsuite.wem": { + "source": "iana" + }, + "application/vnd.motorola.iprm": { + "source": "iana" + }, + "application/vnd.mozilla.xul+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xul"] + }, + "application/vnd.ms-3mfdocument": { + "source": "iana" + }, + "application/vnd.ms-artgalry": { + "source": "iana", + "extensions": ["cil"] + }, + "application/vnd.ms-asf": { + "source": "iana" + }, + "application/vnd.ms-cab-compressed": { + "source": "iana", + "extensions": ["cab"] + }, + "application/vnd.ms-color.iccprofile": { + "source": "apache" + }, + "application/vnd.ms-excel": { + "source": "iana", + "compressible": false, + "extensions": ["xls","xlm","xla","xlc","xlt","xlw"] + }, + "application/vnd.ms-excel.addin.macroenabled.12": { + "source": "iana", + "extensions": ["xlam"] + }, + "application/vnd.ms-excel.sheet.binary.macroenabled.12": { + "source": "iana", + "extensions": ["xlsb"] + }, + "application/vnd.ms-excel.sheet.macroenabled.12": { + "source": "iana", + "extensions": ["xlsm"] + }, + "application/vnd.ms-excel.template.macroenabled.12": { + "source": "iana", + "extensions": ["xltm"] + }, + "application/vnd.ms-fontobject": { + "source": "iana", + "compressible": true, + "extensions": ["eot"] + }, + "application/vnd.ms-htmlhelp": { + "source": "iana", + "extensions": ["chm"] + }, + "application/vnd.ms-ims": { + "source": "iana", + "extensions": ["ims"] + }, + "application/vnd.ms-lrm": { + "source": "iana", + "extensions": ["lrm"] + }, + "application/vnd.ms-office.activex+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.ms-officetheme": { + "source": "iana", + "extensions": ["thmx"] + }, + "application/vnd.ms-opentype": { + "source": "apache", + "compressible": true + }, + "application/vnd.ms-outlook": { + "compressible": false, + "extensions": ["msg"] + }, + "application/vnd.ms-package.obfuscated-opentype": { + "source": "apache" + }, + "application/vnd.ms-pki.seccat": { + "source": "apache", + "extensions": ["cat"] + }, + "application/vnd.ms-pki.stl": { + "source": "apache", + "extensions": ["stl"] + }, + "application/vnd.ms-playready.initiator+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.ms-powerpoint": { + "source": "iana", + "compressible": false, + "extensions": ["ppt","pps","pot"] + }, + "application/vnd.ms-powerpoint.addin.macroenabled.12": { + "source": "iana", + "extensions": ["ppam"] + }, + "application/vnd.ms-powerpoint.presentation.macroenabled.12": { + "source": "iana", + "extensions": ["pptm"] + }, + "application/vnd.ms-powerpoint.slide.macroenabled.12": { + "source": "iana", + "extensions": ["sldm"] + }, + "application/vnd.ms-powerpoint.slideshow.macroenabled.12": { + "source": "iana", + "extensions": ["ppsm"] + }, + "application/vnd.ms-powerpoint.template.macroenabled.12": { + "source": "iana", + "extensions": ["potm"] + }, + "application/vnd.ms-printdevicecapabilities+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.ms-printing.printticket+xml": { + "source": "apache", + "compressible": true + }, + "application/vnd.ms-printschematicket+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.ms-project": { + "source": "iana", + "extensions": ["mpp","mpt"] + }, + "application/vnd.ms-tnef": { + "source": "iana" + }, + "application/vnd.ms-windows.devicepairing": { + "source": "iana" + }, + "application/vnd.ms-windows.nwprinting.oob": { + "source": "iana" + }, + "application/vnd.ms-windows.printerpairing": { + "source": "iana" + }, + "application/vnd.ms-windows.wsd.oob": { + "source": "iana" + }, + "application/vnd.ms-wmdrm.lic-chlg-req": { + "source": "iana" + }, + "application/vnd.ms-wmdrm.lic-resp": { + "source": "iana" + }, + "application/vnd.ms-wmdrm.meter-chlg-req": { + "source": "iana" + }, + "application/vnd.ms-wmdrm.meter-resp": { + "source": "iana" + }, + "application/vnd.ms-word.document.macroenabled.12": { + "source": "iana", + "extensions": ["docm"] + }, + "application/vnd.ms-word.template.macroenabled.12": { + "source": "iana", + "extensions": ["dotm"] + }, + "application/vnd.ms-works": { + "source": "iana", + "extensions": ["wps","wks","wcm","wdb"] + }, + "application/vnd.ms-wpl": { + "source": "iana", + "extensions": ["wpl"] + }, + "application/vnd.ms-xpsdocument": { + "source": "iana", + "compressible": false, + "extensions": ["xps"] + }, + "application/vnd.msa-disk-image": { + "source": "iana" + }, + "application/vnd.mseq": { + "source": "iana", + "extensions": ["mseq"] + }, + "application/vnd.msign": { + "source": "iana" + }, + "application/vnd.multiad.creator": { + "source": "iana" + }, + "application/vnd.multiad.creator.cif": { + "source": "iana" + }, + "application/vnd.music-niff": { + "source": "iana" + }, + "application/vnd.musician": { + "source": "iana", + "extensions": ["mus"] + }, + "application/vnd.muvee.style": { + "source": "iana", + "extensions": ["msty"] + }, + "application/vnd.mynfc": { + "source": "iana", + "extensions": ["taglet"] + }, + "application/vnd.ncd.control": { + "source": "iana" + }, + "application/vnd.ncd.reference": { + "source": "iana" + }, + "application/vnd.nearst.inv+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.nebumind.line": { + "source": "iana" + }, + "application/vnd.nervana": { + "source": "iana" + }, + "application/vnd.netfpx": { + "source": "iana" + }, + "application/vnd.neurolanguage.nlu": { + "source": "iana", + "extensions": ["nlu"] + }, + "application/vnd.nimn": { + "source": "iana" + }, + "application/vnd.nintendo.nitro.rom": { + "source": "iana" + }, + "application/vnd.nintendo.snes.rom": { + "source": "iana" + }, + "application/vnd.nitf": { + "source": "iana", + "extensions": ["ntf","nitf"] + }, + "application/vnd.noblenet-directory": { + "source": "iana", + "extensions": ["nnd"] + }, + "application/vnd.noblenet-sealer": { + "source": "iana", + "extensions": ["nns"] + }, + "application/vnd.noblenet-web": { + "source": "iana", + "extensions": ["nnw"] + }, + "application/vnd.nokia.catalogs": { + "source": "iana" + }, + "application/vnd.nokia.conml+wbxml": { + "source": "iana" + }, + "application/vnd.nokia.conml+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.nokia.iptv.config+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.nokia.isds-radio-presets": { + "source": "iana" + }, + "application/vnd.nokia.landmark+wbxml": { + "source": "iana" + }, + "application/vnd.nokia.landmark+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.nokia.landmarkcollection+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.nokia.n-gage.ac+xml": { + "source": "iana", + "compressible": true, + "extensions": ["ac"] + }, + "application/vnd.nokia.n-gage.data": { + "source": "iana", + "extensions": ["ngdat"] + }, + "application/vnd.nokia.n-gage.symbian.install": { + "source": "iana", + "extensions": ["n-gage"] + }, + "application/vnd.nokia.ncd": { + "source": "iana" + }, + "application/vnd.nokia.pcd+wbxml": { + "source": "iana" + }, + "application/vnd.nokia.pcd+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.nokia.radio-preset": { + "source": "iana", + "extensions": ["rpst"] + }, + "application/vnd.nokia.radio-presets": { + "source": "iana", + "extensions": ["rpss"] + }, + "application/vnd.novadigm.edm": { + "source": "iana", + "extensions": ["edm"] + }, + "application/vnd.novadigm.edx": { + "source": "iana", + "extensions": ["edx"] + }, + "application/vnd.novadigm.ext": { + "source": "iana", + "extensions": ["ext"] + }, + "application/vnd.ntt-local.content-share": { + "source": "iana" + }, + "application/vnd.ntt-local.file-transfer": { + "source": "iana" + }, + "application/vnd.ntt-local.ogw_remote-access": { + "source": "iana" + }, + "application/vnd.ntt-local.sip-ta_remote": { + "source": "iana" + }, + "application/vnd.ntt-local.sip-ta_tcp_stream": { + "source": "iana" + }, + "application/vnd.oasis.opendocument.chart": { + "source": "iana", + "extensions": ["odc"] + }, + "application/vnd.oasis.opendocument.chart-template": { + "source": "iana", + "extensions": ["otc"] + }, + "application/vnd.oasis.opendocument.database": { + "source": "iana", + "extensions": ["odb"] + }, + "application/vnd.oasis.opendocument.formula": { + "source": "iana", + "extensions": ["odf"] + }, + "application/vnd.oasis.opendocument.formula-template": { + "source": "iana", + "extensions": ["odft"] + }, + "application/vnd.oasis.opendocument.graphics": { + "source": "iana", + "compressible": false, + "extensions": ["odg"] + }, + "application/vnd.oasis.opendocument.graphics-template": { + "source": "iana", + "extensions": ["otg"] + }, + "application/vnd.oasis.opendocument.image": { + "source": "iana", + "extensions": ["odi"] + }, + "application/vnd.oasis.opendocument.image-template": { + "source": "iana", + "extensions": ["oti"] + }, + "application/vnd.oasis.opendocument.presentation": { + "source": "iana", + "compressible": false, + "extensions": ["odp"] + }, + "application/vnd.oasis.opendocument.presentation-template": { + "source": "iana", + "extensions": ["otp"] + }, + "application/vnd.oasis.opendocument.spreadsheet": { + "source": "iana", + "compressible": false, + "extensions": ["ods"] + }, + "application/vnd.oasis.opendocument.spreadsheet-template": { + "source": "iana", + "extensions": ["ots"] + }, + "application/vnd.oasis.opendocument.text": { + "source": "iana", + "compressible": false, + "extensions": ["odt"] + }, + "application/vnd.oasis.opendocument.text-master": { + "source": "iana", + "extensions": ["odm"] + }, + "application/vnd.oasis.opendocument.text-template": { + "source": "iana", + "extensions": ["ott"] + }, + "application/vnd.oasis.opendocument.text-web": { + "source": "iana", + "extensions": ["oth"] + }, + "application/vnd.obn": { + "source": "iana" + }, + "application/vnd.ocf+cbor": { + "source": "iana" + }, + "application/vnd.oci.image.manifest.v1+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.oftn.l10n+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.contentaccessdownload+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.contentaccessstreaming+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.cspg-hexbinary": { + "source": "iana" + }, + "application/vnd.oipf.dae.svg+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.dae.xhtml+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.mippvcontrolmessage+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.pae.gem": { + "source": "iana" + }, + "application/vnd.oipf.spdiscovery+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.spdlist+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.ueprofile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oipf.userprofile+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.olpc-sugar": { + "source": "iana", + "extensions": ["xo"] + }, + "application/vnd.oma-scws-config": { + "source": "iana" + }, + "application/vnd.oma-scws-http-request": { + "source": "iana" + }, + "application/vnd.oma-scws-http-response": { + "source": "iana" + }, + "application/vnd.oma.bcast.associated-procedure-parameter+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.drm-trigger+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.imd+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.ltkm": { + "source": "iana" + }, + "application/vnd.oma.bcast.notification+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.provisioningtrigger": { + "source": "iana" + }, + "application/vnd.oma.bcast.sgboot": { + "source": "iana" + }, + "application/vnd.oma.bcast.sgdd+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.sgdu": { + "source": "iana" + }, + "application/vnd.oma.bcast.simple-symbol-container": { + "source": "iana" + }, + "application/vnd.oma.bcast.smartcard-trigger+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.sprov+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.bcast.stkm": { + "source": "iana" + }, + "application/vnd.oma.cab-address-book+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.cab-feature-handler+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.cab-pcc+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.cab-subs-invite+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.cab-user-prefs+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.dcd": { + "source": "iana" + }, + "application/vnd.oma.dcdc": { + "source": "iana" + }, + "application/vnd.oma.dd2+xml": { + "source": "iana", + "compressible": true, + "extensions": ["dd2"] + }, + "application/vnd.oma.drm.risd+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.group-usage-list+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.lwm2m+cbor": { + "source": "iana" + }, + "application/vnd.oma.lwm2m+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.lwm2m+tlv": { + "source": "iana" + }, + "application/vnd.oma.pal+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.poc.detailed-progress-report+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.poc.final-report+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.poc.groups+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.poc.invocation-descriptor+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.poc.optimized-progress-report+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.push": { + "source": "iana" + }, + "application/vnd.oma.scidm.messages+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oma.xcap-directory+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.omads-email+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/vnd.omads-file+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/vnd.omads-folder+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/vnd.omaloc-supl-init": { + "source": "iana" + }, + "application/vnd.onepager": { + "source": "iana" + }, + "application/vnd.onepagertamp": { + "source": "iana" + }, + "application/vnd.onepagertamx": { + "source": "iana" + }, + "application/vnd.onepagertat": { + "source": "iana" + }, + "application/vnd.onepagertatp": { + "source": "iana" + }, + "application/vnd.onepagertatx": { + "source": "iana" + }, + "application/vnd.openblox.game+xml": { + "source": "iana", + "compressible": true, + "extensions": ["obgx"] + }, + "application/vnd.openblox.game-binary": { + "source": "iana" + }, + "application/vnd.openeye.oeb": { + "source": "iana" + }, + "application/vnd.openofficeorg.extension": { + "source": "apache", + "extensions": ["oxt"] + }, + "application/vnd.openstreetmap.data+xml": { + "source": "iana", + "compressible": true, + "extensions": ["osm"] + }, + "application/vnd.openxmlformats-officedocument.custom-properties+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.customxmlproperties+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawing+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.extended-properties+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.comments+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.presentation": { + "source": "iana", + "compressible": false, + "extensions": ["pptx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.presprops+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slide": { + "source": "iana", + "extensions": ["sldx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.slide+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideshow": { + "source": "iana", + "extensions": ["ppsx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.tags+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.template": { + "source": "iana", + "extensions": ["potx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { + "source": "iana", + "compressible": false, + "extensions": ["xlsx"] + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.template": { + "source": "iana", + "extensions": ["xltx"] + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.theme+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.themeoverride+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.vmldrawing": { + "source": "iana" + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": { + "source": "iana", + "compressible": false, + "extensions": ["docx"] + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.template": { + "source": "iana", + "extensions": ["dotx"] + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-package.core-properties+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.openxmlformats-package.relationships+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oracle.resource+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.orange.indata": { + "source": "iana" + }, + "application/vnd.osa.netdeploy": { + "source": "iana" + }, + "application/vnd.osgeo.mapguide.package": { + "source": "iana", + "extensions": ["mgp"] + }, + "application/vnd.osgi.bundle": { + "source": "iana" + }, + "application/vnd.osgi.dp": { + "source": "iana", + "extensions": ["dp"] + }, + "application/vnd.osgi.subsystem": { + "source": "iana", + "extensions": ["esa"] + }, + "application/vnd.otps.ct-kip+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.oxli.countgraph": { + "source": "iana" + }, + "application/vnd.pagerduty+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.palm": { + "source": "iana", + "extensions": ["pdb","pqa","oprc"] + }, + "application/vnd.panoply": { + "source": "iana" + }, + "application/vnd.paos.xml": { + "source": "iana" + }, + "application/vnd.patentdive": { + "source": "iana" + }, + "application/vnd.patientecommsdoc": { + "source": "iana" + }, + "application/vnd.pawaafile": { + "source": "iana", + "extensions": ["paw"] + }, + "application/vnd.pcos": { + "source": "iana" + }, + "application/vnd.pg.format": { + "source": "iana", + "extensions": ["str"] + }, + "application/vnd.pg.osasli": { + "source": "iana", + "extensions": ["ei6"] + }, + "application/vnd.piaccess.application-licence": { + "source": "iana" + }, + "application/vnd.picsel": { + "source": "iana", + "extensions": ["efif"] + }, + "application/vnd.pmi.widget": { + "source": "iana", + "extensions": ["wg"] + }, + "application/vnd.poc.group-advertisement+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.pocketlearn": { + "source": "iana", + "extensions": ["plf"] + }, + "application/vnd.powerbuilder6": { + "source": "iana", + "extensions": ["pbd"] + }, + "application/vnd.powerbuilder6-s": { + "source": "iana" + }, + "application/vnd.powerbuilder7": { + "source": "iana" + }, + "application/vnd.powerbuilder7-s": { + "source": "iana" + }, + "application/vnd.powerbuilder75": { + "source": "iana" + }, + "application/vnd.powerbuilder75-s": { + "source": "iana" + }, + "application/vnd.preminet": { + "source": "iana" + }, + "application/vnd.previewsystems.box": { + "source": "iana", + "extensions": ["box"] + }, + "application/vnd.proteus.magazine": { + "source": "iana", + "extensions": ["mgz"] + }, + "application/vnd.psfs": { + "source": "iana" + }, + "application/vnd.publishare-delta-tree": { + "source": "iana", + "extensions": ["qps"] + }, + "application/vnd.pvi.ptid1": { + "source": "iana", + "extensions": ["ptid"] + }, + "application/vnd.pwg-multiplexed": { + "source": "iana" + }, + "application/vnd.pwg-xhtml-print+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.qualcomm.brew-app-res": { + "source": "iana" + }, + "application/vnd.quarantainenet": { + "source": "iana" + }, + "application/vnd.quark.quarkxpress": { + "source": "iana", + "extensions": ["qxd","qxt","qwd","qwt","qxl","qxb"] + }, + "application/vnd.quobject-quoxdocument": { + "source": "iana" + }, + "application/vnd.radisys.moml+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-audit+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-audit-conf+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-audit-conn+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-audit-dialog+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-audit-stream+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-conf+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-base+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-fax-detect+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-fax-sendrecv+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-group+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-speech+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.radisys.msml-dialog-transform+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.rainstor.data": { + "source": "iana" + }, + "application/vnd.rapid": { + "source": "iana" + }, + "application/vnd.rar": { + "source": "iana", + "extensions": ["rar"] + }, + "application/vnd.realvnc.bed": { + "source": "iana", + "extensions": ["bed"] + }, + "application/vnd.recordare.musicxml": { + "source": "iana", + "extensions": ["mxl"] + }, + "application/vnd.recordare.musicxml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["musicxml"] + }, + "application/vnd.renlearn.rlprint": { + "source": "iana" + }, + "application/vnd.restful+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.rig.cryptonote": { + "source": "iana", + "extensions": ["cryptonote"] + }, + "application/vnd.rim.cod": { + "source": "apache", + "extensions": ["cod"] + }, + "application/vnd.rn-realmedia": { + "source": "apache", + "extensions": ["rm"] + }, + "application/vnd.rn-realmedia-vbr": { + "source": "apache", + "extensions": ["rmvb"] + }, + "application/vnd.route66.link66+xml": { + "source": "iana", + "compressible": true, + "extensions": ["link66"] + }, + "application/vnd.rs-274x": { + "source": "iana" + }, + "application/vnd.ruckus.download": { + "source": "iana" + }, + "application/vnd.s3sms": { + "source": "iana" + }, + "application/vnd.sailingtracker.track": { + "source": "iana", + "extensions": ["st"] + }, + "application/vnd.sar": { + "source": "iana" + }, + "application/vnd.sbm.cid": { + "source": "iana" + }, + "application/vnd.sbm.mid2": { + "source": "iana" + }, + "application/vnd.scribus": { + "source": "iana" + }, + "application/vnd.sealed.3df": { + "source": "iana" + }, + "application/vnd.sealed.csf": { + "source": "iana" + }, + "application/vnd.sealed.doc": { + "source": "iana" + }, + "application/vnd.sealed.eml": { + "source": "iana" + }, + "application/vnd.sealed.mht": { + "source": "iana" + }, + "application/vnd.sealed.net": { + "source": "iana" + }, + "application/vnd.sealed.ppt": { + "source": "iana" + }, + "application/vnd.sealed.tiff": { + "source": "iana" + }, + "application/vnd.sealed.xls": { + "source": "iana" + }, + "application/vnd.sealedmedia.softseal.html": { + "source": "iana" + }, + "application/vnd.sealedmedia.softseal.pdf": { + "source": "iana" + }, + "application/vnd.seemail": { + "source": "iana", + "extensions": ["see"] + }, + "application/vnd.seis+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.sema": { + "source": "iana", + "extensions": ["sema"] + }, + "application/vnd.semd": { + "source": "iana", + "extensions": ["semd"] + }, + "application/vnd.semf": { + "source": "iana", + "extensions": ["semf"] + }, + "application/vnd.shade-save-file": { + "source": "iana" + }, + "application/vnd.shana.informed.formdata": { + "source": "iana", + "extensions": ["ifm"] + }, + "application/vnd.shana.informed.formtemplate": { + "source": "iana", + "extensions": ["itp"] + }, + "application/vnd.shana.informed.interchange": { + "source": "iana", + "extensions": ["iif"] + }, + "application/vnd.shana.informed.package": { + "source": "iana", + "extensions": ["ipk"] + }, + "application/vnd.shootproof+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.shopkick+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.shp": { + "source": "iana" + }, + "application/vnd.shx": { + "source": "iana" + }, + "application/vnd.sigrok.session": { + "source": "iana" + }, + "application/vnd.simtech-mindmapper": { + "source": "iana", + "extensions": ["twd","twds"] + }, + "application/vnd.siren+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.smaf": { + "source": "iana", + "extensions": ["mmf"] + }, + "application/vnd.smart.notebook": { + "source": "iana" + }, + "application/vnd.smart.teacher": { + "source": "iana", + "extensions": ["teacher"] + }, + "application/vnd.snesdev-page-table": { + "source": "iana" + }, + "application/vnd.software602.filler.form+xml": { + "source": "iana", + "compressible": true, + "extensions": ["fo"] + }, + "application/vnd.software602.filler.form-xml-zip": { + "source": "iana" + }, + "application/vnd.solent.sdkm+xml": { + "source": "iana", + "compressible": true, + "extensions": ["sdkm","sdkd"] + }, + "application/vnd.spotfire.dxp": { + "source": "iana", + "extensions": ["dxp"] + }, + "application/vnd.spotfire.sfs": { + "source": "iana", + "extensions": ["sfs"] + }, + "application/vnd.sqlite3": { + "source": "iana" + }, + "application/vnd.sss-cod": { + "source": "iana" + }, + "application/vnd.sss-dtf": { + "source": "iana" + }, + "application/vnd.sss-ntf": { + "source": "iana" + }, + "application/vnd.stardivision.calc": { + "source": "apache", + "extensions": ["sdc"] + }, + "application/vnd.stardivision.draw": { + "source": "apache", + "extensions": ["sda"] + }, + "application/vnd.stardivision.impress": { + "source": "apache", + "extensions": ["sdd"] + }, + "application/vnd.stardivision.math": { + "source": "apache", + "extensions": ["smf"] + }, + "application/vnd.stardivision.writer": { + "source": "apache", + "extensions": ["sdw","vor"] + }, + "application/vnd.stardivision.writer-global": { + "source": "apache", + "extensions": ["sgl"] + }, + "application/vnd.stepmania.package": { + "source": "iana", + "extensions": ["smzip"] + }, + "application/vnd.stepmania.stepchart": { + "source": "iana", + "extensions": ["sm"] + }, + "application/vnd.street-stream": { + "source": "iana" + }, + "application/vnd.sun.wadl+xml": { + "source": "iana", + "compressible": true, + "extensions": ["wadl"] + }, + "application/vnd.sun.xml.calc": { + "source": "apache", + "extensions": ["sxc"] + }, + "application/vnd.sun.xml.calc.template": { + "source": "apache", + "extensions": ["stc"] + }, + "application/vnd.sun.xml.draw": { + "source": "apache", + "extensions": ["sxd"] + }, + "application/vnd.sun.xml.draw.template": { + "source": "apache", + "extensions": ["std"] + }, + "application/vnd.sun.xml.impress": { + "source": "apache", + "extensions": ["sxi"] + }, + "application/vnd.sun.xml.impress.template": { + "source": "apache", + "extensions": ["sti"] + }, + "application/vnd.sun.xml.math": { + "source": "apache", + "extensions": ["sxm"] + }, + "application/vnd.sun.xml.writer": { + "source": "apache", + "extensions": ["sxw"] + }, + "application/vnd.sun.xml.writer.global": { + "source": "apache", + "extensions": ["sxg"] + }, + "application/vnd.sun.xml.writer.template": { + "source": "apache", + "extensions": ["stw"] + }, + "application/vnd.sus-calendar": { + "source": "iana", + "extensions": ["sus","susp"] + }, + "application/vnd.svd": { + "source": "iana", + "extensions": ["svd"] + }, + "application/vnd.swiftview-ics": { + "source": "iana" + }, + "application/vnd.sycle+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.symbian.install": { + "source": "apache", + "extensions": ["sis","sisx"] + }, + "application/vnd.syncml+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["xsm"] + }, + "application/vnd.syncml.dm+wbxml": { + "source": "iana", + "charset": "UTF-8", + "extensions": ["bdm"] + }, + "application/vnd.syncml.dm+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["xdm"] + }, + "application/vnd.syncml.dm.notification": { + "source": "iana" + }, + "application/vnd.syncml.dmddf+wbxml": { + "source": "iana" + }, + "application/vnd.syncml.dmddf+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["ddf"] + }, + "application/vnd.syncml.dmtnds+wbxml": { + "source": "iana" + }, + "application/vnd.syncml.dmtnds+xml": { + "source": "iana", + "charset": "UTF-8", + "compressible": true + }, + "application/vnd.syncml.ds.notification": { + "source": "iana" + }, + "application/vnd.tableschema+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.tao.intent-module-archive": { + "source": "iana", + "extensions": ["tao"] + }, + "application/vnd.tcpdump.pcap": { + "source": "iana", + "extensions": ["pcap","cap","dmp"] + }, + "application/vnd.think-cell.ppttc+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.tmd.mediaflex.api+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.tml": { + "source": "iana" + }, + "application/vnd.tmobile-livetv": { + "source": "iana", + "extensions": ["tmo"] + }, + "application/vnd.tri.onesource": { + "source": "iana" + }, + "application/vnd.trid.tpt": { + "source": "iana", + "extensions": ["tpt"] + }, + "application/vnd.triscape.mxs": { + "source": "iana", + "extensions": ["mxs"] + }, + "application/vnd.trueapp": { + "source": "iana", + "extensions": ["tra"] + }, + "application/vnd.truedoc": { + "source": "iana" + }, + "application/vnd.ubisoft.webplayer": { + "source": "iana" + }, + "application/vnd.ufdl": { + "source": "iana", + "extensions": ["ufd","ufdl"] + }, + "application/vnd.uiq.theme": { + "source": "iana", + "extensions": ["utz"] + }, + "application/vnd.umajin": { + "source": "iana", + "extensions": ["umj"] + }, + "application/vnd.unity": { + "source": "iana", + "extensions": ["unityweb"] + }, + "application/vnd.uoml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["uoml"] + }, + "application/vnd.uplanet.alert": { + "source": "iana" + }, + "application/vnd.uplanet.alert-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.bearer-choice": { + "source": "iana" + }, + "application/vnd.uplanet.bearer-choice-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.cacheop": { + "source": "iana" + }, + "application/vnd.uplanet.cacheop-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.channel": { + "source": "iana" + }, + "application/vnd.uplanet.channel-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.list": { + "source": "iana" + }, + "application/vnd.uplanet.list-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.listcmd": { + "source": "iana" + }, + "application/vnd.uplanet.listcmd-wbxml": { + "source": "iana" + }, + "application/vnd.uplanet.signal": { + "source": "iana" + }, + "application/vnd.uri-map": { + "source": "iana" + }, + "application/vnd.valve.source.material": { + "source": "iana" + }, + "application/vnd.vcx": { + "source": "iana", + "extensions": ["vcx"] + }, + "application/vnd.vd-study": { + "source": "iana" + }, + "application/vnd.vectorworks": { + "source": "iana" + }, + "application/vnd.vel+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.verimatrix.vcas": { + "source": "iana" + }, + "application/vnd.veryant.thin": { + "source": "iana" + }, + "application/vnd.ves.encrypted": { + "source": "iana" + }, + "application/vnd.vidsoft.vidconference": { + "source": "iana" + }, + "application/vnd.visio": { + "source": "iana", + "extensions": ["vsd","vst","vss","vsw"] + }, + "application/vnd.visionary": { + "source": "iana", + "extensions": ["vis"] + }, + "application/vnd.vividence.scriptfile": { + "source": "iana" + }, + "application/vnd.vsf": { + "source": "iana", + "extensions": ["vsf"] + }, + "application/vnd.wap.sic": { + "source": "iana" + }, + "application/vnd.wap.slc": { + "source": "iana" + }, + "application/vnd.wap.wbxml": { + "source": "iana", + "charset": "UTF-8", + "extensions": ["wbxml"] + }, + "application/vnd.wap.wmlc": { + "source": "iana", + "extensions": ["wmlc"] + }, + "application/vnd.wap.wmlscriptc": { + "source": "iana", + "extensions": ["wmlsc"] + }, + "application/vnd.webturbo": { + "source": "iana", + "extensions": ["wtb"] + }, + "application/vnd.wfa.dpp": { + "source": "iana" + }, + "application/vnd.wfa.p2p": { + "source": "iana" + }, + "application/vnd.wfa.wsc": { + "source": "iana" + }, + "application/vnd.windows.devicepairing": { + "source": "iana" + }, + "application/vnd.wmc": { + "source": "iana" + }, + "application/vnd.wmf.bootstrap": { + "source": "iana" + }, + "application/vnd.wolfram.mathematica": { + "source": "iana" + }, + "application/vnd.wolfram.mathematica.package": { + "source": "iana" + }, + "application/vnd.wolfram.player": { + "source": "iana", + "extensions": ["nbp"] + }, + "application/vnd.wordperfect": { + "source": "iana", + "extensions": ["wpd"] + }, + "application/vnd.wqd": { + "source": "iana", + "extensions": ["wqd"] + }, + "application/vnd.wrq-hp3000-labelled": { + "source": "iana" + }, + "application/vnd.wt.stf": { + "source": "iana", + "extensions": ["stf"] + }, + "application/vnd.wv.csp+wbxml": { + "source": "iana" + }, + "application/vnd.wv.csp+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.wv.ssp+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.xacml+json": { + "source": "iana", + "compressible": true + }, + "application/vnd.xara": { + "source": "iana", + "extensions": ["xar"] + }, + "application/vnd.xfdl": { + "source": "iana", + "extensions": ["xfdl"] + }, + "application/vnd.xfdl.webform": { + "source": "iana" + }, + "application/vnd.xmi+xml": { + "source": "iana", + "compressible": true + }, + "application/vnd.xmpie.cpkg": { + "source": "iana" + }, + "application/vnd.xmpie.dpkg": { + "source": "iana" + }, + "application/vnd.xmpie.plan": { + "source": "iana" + }, + "application/vnd.xmpie.ppkg": { + "source": "iana" + }, + "application/vnd.xmpie.xlim": { + "source": "iana" + }, + "application/vnd.yamaha.hv-dic": { + "source": "iana", + "extensions": ["hvd"] + }, + "application/vnd.yamaha.hv-script": { + "source": "iana", + "extensions": ["hvs"] + }, + "application/vnd.yamaha.hv-voice": { + "source": "iana", + "extensions": ["hvp"] + }, + "application/vnd.yamaha.openscoreformat": { + "source": "iana", + "extensions": ["osf"] + }, + "application/vnd.yamaha.openscoreformat.osfpvg+xml": { + "source": "iana", + "compressible": true, + "extensions": ["osfpvg"] + }, + "application/vnd.yamaha.remote-setup": { + "source": "iana" + }, + "application/vnd.yamaha.smaf-audio": { + "source": "iana", + "extensions": ["saf"] + }, + "application/vnd.yamaha.smaf-phrase": { + "source": "iana", + "extensions": ["spf"] + }, + "application/vnd.yamaha.through-ngn": { + "source": "iana" + }, + "application/vnd.yamaha.tunnel-udpencap": { + "source": "iana" + }, + "application/vnd.yaoweme": { + "source": "iana" + }, + "application/vnd.yellowriver-custom-menu": { + "source": "iana", + "extensions": ["cmp"] + }, + "application/vnd.youtube.yt": { + "source": "iana" + }, + "application/vnd.zul": { + "source": "iana", + "extensions": ["zir","zirz"] + }, + "application/vnd.zzazz.deck+xml": { + "source": "iana", + "compressible": true, + "extensions": ["zaz"] + }, + "application/voicexml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["vxml"] + }, + "application/voucher-cms+json": { + "source": "iana", + "compressible": true + }, + "application/vq-rtcpxr": { + "source": "iana" + }, + "application/wasm": { + "compressible": true, + "extensions": ["wasm"] + }, + "application/watcherinfo+xml": { + "source": "iana", + "compressible": true + }, + "application/webpush-options+json": { + "source": "iana", + "compressible": true + }, + "application/whoispp-query": { + "source": "iana" + }, + "application/whoispp-response": { + "source": "iana" + }, + "application/widget": { + "source": "iana", + "extensions": ["wgt"] + }, + "application/winhlp": { + "source": "apache", + "extensions": ["hlp"] + }, + "application/wita": { + "source": "iana" + }, + "application/wordperfect5.1": { + "source": "iana" + }, + "application/wsdl+xml": { + "source": "iana", + "compressible": true, + "extensions": ["wsdl"] + }, + "application/wspolicy+xml": { + "source": "iana", + "compressible": true, + "extensions": ["wspolicy"] + }, + "application/x-7z-compressed": { + "source": "apache", + "compressible": false, + "extensions": ["7z"] + }, + "application/x-abiword": { + "source": "apache", + "extensions": ["abw"] + }, + "application/x-ace-compressed": { + "source": "apache", + "extensions": ["ace"] + }, + "application/x-amf": { + "source": "apache" + }, + "application/x-apple-diskimage": { + "source": "apache", + "extensions": ["dmg"] + }, + "application/x-arj": { + "compressible": false, + "extensions": ["arj"] + }, + "application/x-authorware-bin": { + "source": "apache", + "extensions": ["aab","x32","u32","vox"] + }, + "application/x-authorware-map": { + "source": "apache", + "extensions": ["aam"] + }, + "application/x-authorware-seg": { + "source": "apache", + "extensions": ["aas"] + }, + "application/x-bcpio": { + "source": "apache", + "extensions": ["bcpio"] + }, + "application/x-bdoc": { + "compressible": false, + "extensions": ["bdoc"] + }, + "application/x-bittorrent": { + "source": "apache", + "extensions": ["torrent"] + }, + "application/x-blorb": { + "source": "apache", + "extensions": ["blb","blorb"] + }, + "application/x-bzip": { + "source": "apache", + "compressible": false, + "extensions": ["bz"] + }, + "application/x-bzip2": { + "source": "apache", + "compressible": false, + "extensions": ["bz2","boz"] + }, + "application/x-cbr": { + "source": "apache", + "extensions": ["cbr","cba","cbt","cbz","cb7"] + }, + "application/x-cdlink": { + "source": "apache", + "extensions": ["vcd"] + }, + "application/x-cfs-compressed": { + "source": "apache", + "extensions": ["cfs"] + }, + "application/x-chat": { + "source": "apache", + "extensions": ["chat"] + }, + "application/x-chess-pgn": { + "source": "apache", + "extensions": ["pgn"] + }, + "application/x-chrome-extension": { + "extensions": ["crx"] + }, + "application/x-cocoa": { + "source": "nginx", + "extensions": ["cco"] + }, + "application/x-compress": { + "source": "apache" + }, + "application/x-conference": { + "source": "apache", + "extensions": ["nsc"] + }, + "application/x-cpio": { + "source": "apache", + "extensions": ["cpio"] + }, + "application/x-csh": { + "source": "apache", + "extensions": ["csh"] + }, + "application/x-deb": { + "compressible": false + }, + "application/x-debian-package": { + "source": "apache", + "extensions": ["deb","udeb"] + }, + "application/x-dgc-compressed": { + "source": "apache", + "extensions": ["dgc"] + }, + "application/x-director": { + "source": "apache", + "extensions": ["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"] + }, + "application/x-doom": { + "source": "apache", + "extensions": ["wad"] + }, + "application/x-dtbncx+xml": { + "source": "apache", + "compressible": true, + "extensions": ["ncx"] + }, + "application/x-dtbook+xml": { + "source": "apache", + "compressible": true, + "extensions": ["dtb"] + }, + "application/x-dtbresource+xml": { + "source": "apache", + "compressible": true, + "extensions": ["res"] + }, + "application/x-dvi": { + "source": "apache", + "compressible": false, + "extensions": ["dvi"] + }, + "application/x-envoy": { + "source": "apache", + "extensions": ["evy"] + }, + "application/x-eva": { + "source": "apache", + "extensions": ["eva"] + }, + "application/x-font-bdf": { + "source": "apache", + "extensions": ["bdf"] + }, + "application/x-font-dos": { + "source": "apache" + }, + "application/x-font-framemaker": { + "source": "apache" + }, + "application/x-font-ghostscript": { + "source": "apache", + "extensions": ["gsf"] + }, + "application/x-font-libgrx": { + "source": "apache" + }, + "application/x-font-linux-psf": { + "source": "apache", + "extensions": ["psf"] + }, + "application/x-font-pcf": { + "source": "apache", + "extensions": ["pcf"] + }, + "application/x-font-snf": { + "source": "apache", + "extensions": ["snf"] + }, + "application/x-font-speedo": { + "source": "apache" + }, + "application/x-font-sunos-news": { + "source": "apache" + }, + "application/x-font-type1": { + "source": "apache", + "extensions": ["pfa","pfb","pfm","afm"] + }, + "application/x-font-vfont": { + "source": "apache" + }, + "application/x-freearc": { + "source": "apache", + "extensions": ["arc"] + }, + "application/x-futuresplash": { + "source": "apache", + "extensions": ["spl"] + }, + "application/x-gca-compressed": { + "source": "apache", + "extensions": ["gca"] + }, + "application/x-glulx": { + "source": "apache", + "extensions": ["ulx"] + }, + "application/x-gnumeric": { + "source": "apache", + "extensions": ["gnumeric"] + }, + "application/x-gramps-xml": { + "source": "apache", + "extensions": ["gramps"] + }, + "application/x-gtar": { + "source": "apache", + "extensions": ["gtar"] + }, + "application/x-gzip": { + "source": "apache" + }, + "application/x-hdf": { + "source": "apache", + "extensions": ["hdf"] + }, + "application/x-httpd-php": { + "compressible": true, + "extensions": ["php"] + }, + "application/x-install-instructions": { + "source": "apache", + "extensions": ["install"] + }, + "application/x-iso9660-image": { + "source": "apache", + "extensions": ["iso"] + }, + "application/x-java-archive-diff": { + "source": "nginx", + "extensions": ["jardiff"] + }, + "application/x-java-jnlp-file": { + "source": "apache", + "compressible": false, + "extensions": ["jnlp"] + }, + "application/x-javascript": { + "compressible": true + }, + "application/x-keepass2": { + "extensions": ["kdbx"] + }, + "application/x-latex": { + "source": "apache", + "compressible": false, + "extensions": ["latex"] + }, + "application/x-lua-bytecode": { + "extensions": ["luac"] + }, + "application/x-lzh-compressed": { + "source": "apache", + "extensions": ["lzh","lha"] + }, + "application/x-makeself": { + "source": "nginx", + "extensions": ["run"] + }, + "application/x-mie": { + "source": "apache", + "extensions": ["mie"] + }, + "application/x-mobipocket-ebook": { + "source": "apache", + "extensions": ["prc","mobi"] + }, + "application/x-mpegurl": { + "compressible": false + }, + "application/x-ms-application": { + "source": "apache", + "extensions": ["application"] + }, + "application/x-ms-shortcut": { + "source": "apache", + "extensions": ["lnk"] + }, + "application/x-ms-wmd": { + "source": "apache", + "extensions": ["wmd"] + }, + "application/x-ms-wmz": { + "source": "apache", + "extensions": ["wmz"] + }, + "application/x-ms-xbap": { + "source": "apache", + "extensions": ["xbap"] + }, + "application/x-msaccess": { + "source": "apache", + "extensions": ["mdb"] + }, + "application/x-msbinder": { + "source": "apache", + "extensions": ["obd"] + }, + "application/x-mscardfile": { + "source": "apache", + "extensions": ["crd"] + }, + "application/x-msclip": { + "source": "apache", + "extensions": ["clp"] + }, + "application/x-msdos-program": { + "extensions": ["exe"] + }, + "application/x-msdownload": { + "source": "apache", + "extensions": ["exe","dll","com","bat","msi"] + }, + "application/x-msmediaview": { + "source": "apache", + "extensions": ["mvb","m13","m14"] + }, + "application/x-msmetafile": { + "source": "apache", + "extensions": ["wmf","wmz","emf","emz"] + }, + "application/x-msmoney": { + "source": "apache", + "extensions": ["mny"] + }, + "application/x-mspublisher": { + "source": "apache", + "extensions": ["pub"] + }, + "application/x-msschedule": { + "source": "apache", + "extensions": ["scd"] + }, + "application/x-msterminal": { + "source": "apache", + "extensions": ["trm"] + }, + "application/x-mswrite": { + "source": "apache", + "extensions": ["wri"] + }, + "application/x-netcdf": { + "source": "apache", + "extensions": ["nc","cdf"] + }, + "application/x-ns-proxy-autoconfig": { + "compressible": true, + "extensions": ["pac"] + }, + "application/x-nzb": { + "source": "apache", + "extensions": ["nzb"] + }, + "application/x-perl": { + "source": "nginx", + "extensions": ["pl","pm"] + }, + "application/x-pilot": { + "source": "nginx", + "extensions": ["prc","pdb"] + }, + "application/x-pkcs12": { + "source": "apache", + "compressible": false, + "extensions": ["p12","pfx"] + }, + "application/x-pkcs7-certificates": { + "source": "apache", + "extensions": ["p7b","spc"] + }, + "application/x-pkcs7-certreqresp": { + "source": "apache", + "extensions": ["p7r"] + }, + "application/x-pki-message": { + "source": "iana" + }, + "application/x-rar-compressed": { + "source": "apache", + "compressible": false, + "extensions": ["rar"] + }, + "application/x-redhat-package-manager": { + "source": "nginx", + "extensions": ["rpm"] + }, + "application/x-research-info-systems": { + "source": "apache", + "extensions": ["ris"] + }, + "application/x-sea": { + "source": "nginx", + "extensions": ["sea"] + }, + "application/x-sh": { + "source": "apache", + "compressible": true, + "extensions": ["sh"] + }, + "application/x-shar": { + "source": "apache", + "extensions": ["shar"] + }, + "application/x-shockwave-flash": { + "source": "apache", + "compressible": false, + "extensions": ["swf"] + }, + "application/x-silverlight-app": { + "source": "apache", + "extensions": ["xap"] + }, + "application/x-sql": { + "source": "apache", + "extensions": ["sql"] + }, + "application/x-stuffit": { + "source": "apache", + "compressible": false, + "extensions": ["sit"] + }, + "application/x-stuffitx": { + "source": "apache", + "extensions": ["sitx"] + }, + "application/x-subrip": { + "source": "apache", + "extensions": ["srt"] + }, + "application/x-sv4cpio": { + "source": "apache", + "extensions": ["sv4cpio"] + }, + "application/x-sv4crc": { + "source": "apache", + "extensions": ["sv4crc"] + }, + "application/x-t3vm-image": { + "source": "apache", + "extensions": ["t3"] + }, + "application/x-tads": { + "source": "apache", + "extensions": ["gam"] + }, + "application/x-tar": { + "source": "apache", + "compressible": true, + "extensions": ["tar"] + }, + "application/x-tcl": { + "source": "apache", + "extensions": ["tcl","tk"] + }, + "application/x-tex": { + "source": "apache", + "extensions": ["tex"] + }, + "application/x-tex-tfm": { + "source": "apache", + "extensions": ["tfm"] + }, + "application/x-texinfo": { + "source": "apache", + "extensions": ["texinfo","texi"] + }, + "application/x-tgif": { + "source": "apache", + "extensions": ["obj"] + }, + "application/x-ustar": { + "source": "apache", + "extensions": ["ustar"] + }, + "application/x-virtualbox-hdd": { + "compressible": true, + "extensions": ["hdd"] + }, + "application/x-virtualbox-ova": { + "compressible": true, + "extensions": ["ova"] + }, + "application/x-virtualbox-ovf": { + "compressible": true, + "extensions": ["ovf"] + }, + "application/x-virtualbox-vbox": { + "compressible": true, + "extensions": ["vbox"] + }, + "application/x-virtualbox-vbox-extpack": { + "compressible": false, + "extensions": ["vbox-extpack"] + }, + "application/x-virtualbox-vdi": { + "compressible": true, + "extensions": ["vdi"] + }, + "application/x-virtualbox-vhd": { + "compressible": true, + "extensions": ["vhd"] + }, + "application/x-virtualbox-vmdk": { + "compressible": true, + "extensions": ["vmdk"] + }, + "application/x-wais-source": { + "source": "apache", + "extensions": ["src"] + }, + "application/x-web-app-manifest+json": { + "compressible": true, + "extensions": ["webapp"] + }, + "application/x-www-form-urlencoded": { + "source": "iana", + "compressible": true + }, + "application/x-x509-ca-cert": { + "source": "iana", + "extensions": ["der","crt","pem"] + }, + "application/x-x509-ca-ra-cert": { + "source": "iana" + }, + "application/x-x509-next-ca-cert": { + "source": "iana" + }, + "application/x-xfig": { + "source": "apache", + "extensions": ["fig"] + }, + "application/x-xliff+xml": { + "source": "apache", + "compressible": true, + "extensions": ["xlf"] + }, + "application/x-xpinstall": { + "source": "apache", + "compressible": false, + "extensions": ["xpi"] + }, + "application/x-xz": { + "source": "apache", + "extensions": ["xz"] + }, + "application/x-zmachine": { + "source": "apache", + "extensions": ["z1","z2","z3","z4","z5","z6","z7","z8"] + }, + "application/x400-bp": { + "source": "iana" + }, + "application/xacml+xml": { + "source": "iana", + "compressible": true + }, + "application/xaml+xml": { + "source": "apache", + "compressible": true, + "extensions": ["xaml"] + }, + "application/xcap-att+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xav"] + }, + "application/xcap-caps+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xca"] + }, + "application/xcap-diff+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xdf"] + }, + "application/xcap-el+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xel"] + }, + "application/xcap-error+xml": { + "source": "iana", + "compressible": true + }, + "application/xcap-ns+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xns"] + }, + "application/xcon-conference-info+xml": { + "source": "iana", + "compressible": true + }, + "application/xcon-conference-info-diff+xml": { + "source": "iana", + "compressible": true + }, + "application/xenc+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xenc"] + }, + "application/xhtml+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xhtml","xht"] + }, + "application/xhtml-voice+xml": { + "source": "apache", + "compressible": true + }, + "application/xliff+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xlf"] + }, + "application/xml": { + "source": "iana", + "compressible": true, + "extensions": ["xml","xsl","xsd","rng"] + }, + "application/xml-dtd": { + "source": "iana", + "compressible": true, + "extensions": ["dtd"] + }, + "application/xml-external-parsed-entity": { + "source": "iana" + }, + "application/xml-patch+xml": { + "source": "iana", + "compressible": true + }, + "application/xmpp+xml": { + "source": "iana", + "compressible": true + }, + "application/xop+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xop"] + }, + "application/xproc+xml": { + "source": "apache", + "compressible": true, + "extensions": ["xpl"] + }, + "application/xslt+xml": { + "source": "iana", + "compressible": true, + "extensions": ["xsl","xslt"] + }, + "application/xspf+xml": { + "source": "apache", + "compressible": true, + "extensions": ["xspf"] + }, + "application/xv+xml": { + "source": "iana", + "compressible": true, + "extensions": ["mxml","xhvml","xvml","xvm"] + }, + "application/yang": { + "source": "iana", + "extensions": ["yang"] + }, + "application/yang-data+json": { + "source": "iana", + "compressible": true + }, + "application/yang-data+xml": { + "source": "iana", + "compressible": true + }, + "application/yang-patch+json": { + "source": "iana", + "compressible": true + }, + "application/yang-patch+xml": { + "source": "iana", + "compressible": true + }, + "application/yin+xml": { + "source": "iana", + "compressible": true, + "extensions": ["yin"] + }, + "application/zip": { + "source": "iana", + "compressible": false, + "extensions": ["zip"] + }, + "application/zlib": { + "source": "iana" + }, + "application/zstd": { + "source": "iana" + }, + "audio/1d-interleaved-parityfec": { + "source": "iana" + }, + "audio/32kadpcm": { + "source": "iana" + }, + "audio/3gpp": { + "source": "iana", + "compressible": false, + "extensions": ["3gpp"] + }, + "audio/3gpp2": { + "source": "iana" + }, + "audio/aac": { + "source": "iana" + }, + "audio/ac3": { + "source": "iana" + }, + "audio/adpcm": { + "source": "apache", + "extensions": ["adp"] + }, + "audio/amr": { + "source": "iana", + "extensions": ["amr"] + }, + "audio/amr-wb": { + "source": "iana" + }, + "audio/amr-wb+": { + "source": "iana" + }, + "audio/aptx": { + "source": "iana" + }, + "audio/asc": { + "source": "iana" + }, + "audio/atrac-advanced-lossless": { + "source": "iana" + }, + "audio/atrac-x": { + "source": "iana" + }, + "audio/atrac3": { + "source": "iana" + }, + "audio/basic": { + "source": "iana", + "compressible": false, + "extensions": ["au","snd"] + }, + "audio/bv16": { + "source": "iana" + }, + "audio/bv32": { + "source": "iana" + }, + "audio/clearmode": { + "source": "iana" + }, + "audio/cn": { + "source": "iana" + }, + "audio/dat12": { + "source": "iana" + }, + "audio/dls": { + "source": "iana" + }, + "audio/dsr-es201108": { + "source": "iana" + }, + "audio/dsr-es202050": { + "source": "iana" + }, + "audio/dsr-es202211": { + "source": "iana" + }, + "audio/dsr-es202212": { + "source": "iana" + }, + "audio/dv": { + "source": "iana" + }, + "audio/dvi4": { + "source": "iana" + }, + "audio/eac3": { + "source": "iana" + }, + "audio/encaprtp": { + "source": "iana" + }, + "audio/evrc": { + "source": "iana" + }, + "audio/evrc-qcp": { + "source": "iana" + }, + "audio/evrc0": { + "source": "iana" + }, + "audio/evrc1": { + "source": "iana" + }, + "audio/evrcb": { + "source": "iana" + }, + "audio/evrcb0": { + "source": "iana" + }, + "audio/evrcb1": { + "source": "iana" + }, + "audio/evrcnw": { + "source": "iana" + }, + "audio/evrcnw0": { + "source": "iana" + }, + "audio/evrcnw1": { + "source": "iana" + }, + "audio/evrcwb": { + "source": "iana" + }, + "audio/evrcwb0": { + "source": "iana" + }, + "audio/evrcwb1": { + "source": "iana" + }, + "audio/evs": { + "source": "iana" + }, + "audio/flexfec": { + "source": "iana" + }, + "audio/fwdred": { + "source": "iana" + }, + "audio/g711-0": { + "source": "iana" + }, + "audio/g719": { + "source": "iana" + }, + "audio/g722": { + "source": "iana" + }, + "audio/g7221": { + "source": "iana" + }, + "audio/g723": { + "source": "iana" + }, + "audio/g726-16": { + "source": "iana" + }, + "audio/g726-24": { + "source": "iana" + }, + "audio/g726-32": { + "source": "iana" + }, + "audio/g726-40": { + "source": "iana" + }, + "audio/g728": { + "source": "iana" + }, + "audio/g729": { + "source": "iana" + }, + "audio/g7291": { + "source": "iana" + }, + "audio/g729d": { + "source": "iana" + }, + "audio/g729e": { + "source": "iana" + }, + "audio/gsm": { + "source": "iana" + }, + "audio/gsm-efr": { + "source": "iana" + }, + "audio/gsm-hr-08": { + "source": "iana" + }, + "audio/ilbc": { + "source": "iana" + }, + "audio/ip-mr_v2.5": { + "source": "iana" + }, + "audio/isac": { + "source": "apache" + }, + "audio/l16": { + "source": "iana" + }, + "audio/l20": { + "source": "iana" + }, + "audio/l24": { + "source": "iana", + "compressible": false + }, + "audio/l8": { + "source": "iana" + }, + "audio/lpc": { + "source": "iana" + }, + "audio/melp": { + "source": "iana" + }, + "audio/melp1200": { + "source": "iana" + }, + "audio/melp2400": { + "source": "iana" + }, + "audio/melp600": { + "source": "iana" + }, + "audio/mhas": { + "source": "iana" + }, + "audio/midi": { + "source": "apache", + "extensions": ["mid","midi","kar","rmi"] + }, + "audio/mobile-xmf": { + "source": "iana", + "extensions": ["mxmf"] + }, + "audio/mp3": { + "compressible": false, + "extensions": ["mp3"] + }, + "audio/mp4": { + "source": "iana", + "compressible": false, + "extensions": ["m4a","mp4a"] + }, + "audio/mp4a-latm": { + "source": "iana" + }, + "audio/mpa": { + "source": "iana" + }, + "audio/mpa-robust": { + "source": "iana" + }, + "audio/mpeg": { + "source": "iana", + "compressible": false, + "extensions": ["mpga","mp2","mp2a","mp3","m2a","m3a"] + }, + "audio/mpeg4-generic": { + "source": "iana" + }, + "audio/musepack": { + "source": "apache" + }, + "audio/ogg": { + "source": "iana", + "compressible": false, + "extensions": ["oga","ogg","spx","opus"] + }, + "audio/opus": { + "source": "iana" + }, + "audio/parityfec": { + "source": "iana" + }, + "audio/pcma": { + "source": "iana" + }, + "audio/pcma-wb": { + "source": "iana" + }, + "audio/pcmu": { + "source": "iana" + }, + "audio/pcmu-wb": { + "source": "iana" + }, + "audio/prs.sid": { + "source": "iana" + }, + "audio/qcelp": { + "source": "iana" + }, + "audio/raptorfec": { + "source": "iana" + }, + "audio/red": { + "source": "iana" + }, + "audio/rtp-enc-aescm128": { + "source": "iana" + }, + "audio/rtp-midi": { + "source": "iana" + }, + "audio/rtploopback": { + "source": "iana" + }, + "audio/rtx": { + "source": "iana" + }, + "audio/s3m": { + "source": "apache", + "extensions": ["s3m"] + }, + "audio/scip": { + "source": "iana" + }, + "audio/silk": { + "source": "apache", + "extensions": ["sil"] + }, + "audio/smv": { + "source": "iana" + }, + "audio/smv-qcp": { + "source": "iana" + }, + "audio/smv0": { + "source": "iana" + }, + "audio/sofa": { + "source": "iana" + }, + "audio/sp-midi": { + "source": "iana" + }, + "audio/speex": { + "source": "iana" + }, + "audio/t140c": { + "source": "iana" + }, + "audio/t38": { + "source": "iana" + }, + "audio/telephone-event": { + "source": "iana" + }, + "audio/tetra_acelp": { + "source": "iana" + }, + "audio/tetra_acelp_bb": { + "source": "iana" + }, + "audio/tone": { + "source": "iana" + }, + "audio/tsvcis": { + "source": "iana" + }, + "audio/uemclip": { + "source": "iana" + }, + "audio/ulpfec": { + "source": "iana" + }, + "audio/usac": { + "source": "iana" + }, + "audio/vdvi": { + "source": "iana" + }, + "audio/vmr-wb": { + "source": "iana" + }, + "audio/vnd.3gpp.iufp": { + "source": "iana" + }, + "audio/vnd.4sb": { + "source": "iana" + }, + "audio/vnd.audiokoz": { + "source": "iana" + }, + "audio/vnd.celp": { + "source": "iana" + }, + "audio/vnd.cisco.nse": { + "source": "iana" + }, + "audio/vnd.cmles.radio-events": { + "source": "iana" + }, + "audio/vnd.cns.anp1": { + "source": "iana" + }, + "audio/vnd.cns.inf1": { + "source": "iana" + }, + "audio/vnd.dece.audio": { + "source": "iana", + "extensions": ["uva","uvva"] + }, + "audio/vnd.digital-winds": { + "source": "iana", + "extensions": ["eol"] + }, + "audio/vnd.dlna.adts": { + "source": "iana" + }, + "audio/vnd.dolby.heaac.1": { + "source": "iana" + }, + "audio/vnd.dolby.heaac.2": { + "source": "iana" + }, + "audio/vnd.dolby.mlp": { + "source": "iana" + }, + "audio/vnd.dolby.mps": { + "source": "iana" + }, + "audio/vnd.dolby.pl2": { + "source": "iana" + }, + "audio/vnd.dolby.pl2x": { + "source": "iana" + }, + "audio/vnd.dolby.pl2z": { + "source": "iana" + }, + "audio/vnd.dolby.pulse.1": { + "source": "iana" + }, + "audio/vnd.dra": { + "source": "iana", + "extensions": ["dra"] + }, + "audio/vnd.dts": { + "source": "iana", + "extensions": ["dts"] + }, + "audio/vnd.dts.hd": { + "source": "iana", + "extensions": ["dtshd"] + }, + "audio/vnd.dts.uhd": { + "source": "iana" + }, + "audio/vnd.dvb.file": { + "source": "iana" + }, + "audio/vnd.everad.plj": { + "source": "iana" + }, + "audio/vnd.hns.audio": { + "source": "iana" + }, + "audio/vnd.lucent.voice": { + "source": "iana", + "extensions": ["lvp"] + }, + "audio/vnd.ms-playready.media.pya": { + "source": "iana", + "extensions": ["pya"] + }, + "audio/vnd.nokia.mobile-xmf": { + "source": "iana" + }, + "audio/vnd.nortel.vbk": { + "source": "iana" + }, + "audio/vnd.nuera.ecelp4800": { + "source": "iana", + "extensions": ["ecelp4800"] + }, + "audio/vnd.nuera.ecelp7470": { + "source": "iana", + "extensions": ["ecelp7470"] + }, + "audio/vnd.nuera.ecelp9600": { + "source": "iana", + "extensions": ["ecelp9600"] + }, + "audio/vnd.octel.sbc": { + "source": "iana" + }, + "audio/vnd.presonus.multitrack": { + "source": "iana" + }, + "audio/vnd.qcelp": { + "source": "iana" + }, + "audio/vnd.rhetorex.32kadpcm": { + "source": "iana" + }, + "audio/vnd.rip": { + "source": "iana", + "extensions": ["rip"] + }, + "audio/vnd.rn-realaudio": { + "compressible": false + }, + "audio/vnd.sealedmedia.softseal.mpeg": { + "source": "iana" + }, + "audio/vnd.vmx.cvsd": { + "source": "iana" + }, + "audio/vnd.wave": { + "compressible": false + }, + "audio/vorbis": { + "source": "iana", + "compressible": false + }, + "audio/vorbis-config": { + "source": "iana" + }, + "audio/wav": { + "compressible": false, + "extensions": ["wav"] + }, + "audio/wave": { + "compressible": false, + "extensions": ["wav"] + }, + "audio/webm": { + "source": "apache", + "compressible": false, + "extensions": ["weba"] + }, + "audio/x-aac": { + "source": "apache", + "compressible": false, + "extensions": ["aac"] + }, + "audio/x-aiff": { + "source": "apache", + "extensions": ["aif","aiff","aifc"] + }, + "audio/x-caf": { + "source": "apache", + "compressible": false, + "extensions": ["caf"] + }, + "audio/x-flac": { + "source": "apache", + "extensions": ["flac"] + }, + "audio/x-m4a": { + "source": "nginx", + "extensions": ["m4a"] + }, + "audio/x-matroska": { + "source": "apache", + "extensions": ["mka"] + }, + "audio/x-mpegurl": { + "source": "apache", + "extensions": ["m3u"] + }, + "audio/x-ms-wax": { + "source": "apache", + "extensions": ["wax"] + }, + "audio/x-ms-wma": { + "source": "apache", + "extensions": ["wma"] + }, + "audio/x-pn-realaudio": { + "source": "apache", + "extensions": ["ram","ra"] + }, + "audio/x-pn-realaudio-plugin": { + "source": "apache", + "extensions": ["rmp"] + }, + "audio/x-realaudio": { + "source": "nginx", + "extensions": ["ra"] + }, + "audio/x-tta": { + "source": "apache" + }, + "audio/x-wav": { + "source": "apache", + "extensions": ["wav"] + }, + "audio/xm": { + "source": "apache", + "extensions": ["xm"] + }, + "chemical/x-cdx": { + "source": "apache", + "extensions": ["cdx"] + }, + "chemical/x-cif": { + "source": "apache", + "extensions": ["cif"] + }, + "chemical/x-cmdf": { + "source": "apache", + "extensions": ["cmdf"] + }, + "chemical/x-cml": { + "source": "apache", + "extensions": ["cml"] + }, + "chemical/x-csml": { + "source": "apache", + "extensions": ["csml"] + }, + "chemical/x-pdb": { + "source": "apache" + }, + "chemical/x-xyz": { + "source": "apache", + "extensions": ["xyz"] + }, + "font/collection": { + "source": "iana", + "extensions": ["ttc"] + }, + "font/otf": { + "source": "iana", + "compressible": true, + "extensions": ["otf"] + }, + "font/sfnt": { + "source": "iana" + }, + "font/ttf": { + "source": "iana", + "compressible": true, + "extensions": ["ttf"] + }, + "font/woff": { + "source": "iana", + "extensions": ["woff"] + }, + "font/woff2": { + "source": "iana", + "extensions": ["woff2"] + }, + "image/aces": { + "source": "iana", + "extensions": ["exr"] + }, + "image/apng": { + "compressible": false, + "extensions": ["apng"] + }, + "image/avci": { + "source": "iana" + }, + "image/avcs": { + "source": "iana" + }, + "image/avif": { + "source": "iana", + "compressible": false, + "extensions": ["avif"] + }, + "image/bmp": { + "source": "iana", + "compressible": true, + "extensions": ["bmp"] + }, + "image/cgm": { + "source": "iana", + "extensions": ["cgm"] + }, + "image/dicom-rle": { + "source": "iana", + "extensions": ["drle"] + }, + "image/emf": { + "source": "iana", + "extensions": ["emf"] + }, + "image/fits": { + "source": "iana", + "extensions": ["fits"] + }, + "image/g3fax": { + "source": "iana", + "extensions": ["g3"] + }, + "image/gif": { + "source": "iana", + "compressible": false, + "extensions": ["gif"] + }, + "image/heic": { + "source": "iana", + "extensions": ["heic"] + }, + "image/heic-sequence": { + "source": "iana", + "extensions": ["heics"] + }, + "image/heif": { + "source": "iana", + "extensions": ["heif"] + }, + "image/heif-sequence": { + "source": "iana", + "extensions": ["heifs"] + }, + "image/hej2k": { + "source": "iana", + "extensions": ["hej2"] + }, + "image/hsj2": { + "source": "iana", + "extensions": ["hsj2"] + }, + "image/ief": { + "source": "iana", + "extensions": ["ief"] + }, + "image/jls": { + "source": "iana", + "extensions": ["jls"] + }, + "image/jp2": { + "source": "iana", + "compressible": false, + "extensions": ["jp2","jpg2"] + }, + "image/jpeg": { + "source": "iana", + "compressible": false, + "extensions": ["jpeg","jpg","jpe"] + }, + "image/jph": { + "source": "iana", + "extensions": ["jph"] + }, + "image/jphc": { + "source": "iana", + "extensions": ["jhc"] + }, + "image/jpm": { + "source": "iana", + "compressible": false, + "extensions": ["jpm"] + }, + "image/jpx": { + "source": "iana", + "compressible": false, + "extensions": ["jpx","jpf"] + }, + "image/jxr": { + "source": "iana", + "extensions": ["jxr"] + }, + "image/jxra": { + "source": "iana", + "extensions": ["jxra"] + }, + "image/jxrs": { + "source": "iana", + "extensions": ["jxrs"] + }, + "image/jxs": { + "source": "iana", + "extensions": ["jxs"] + }, + "image/jxsc": { + "source": "iana", + "extensions": ["jxsc"] + }, + "image/jxsi": { + "source": "iana", + "extensions": ["jxsi"] + }, + "image/jxss": { + "source": "iana", + "extensions": ["jxss"] + }, + "image/ktx": { + "source": "iana", + "extensions": ["ktx"] + }, + "image/ktx2": { + "source": "iana", + "extensions": ["ktx2"] + }, + "image/naplps": { + "source": "iana" + }, + "image/pjpeg": { + "compressible": false + }, + "image/png": { + "source": "iana", + "compressible": false, + "extensions": ["png"] + }, + "image/prs.btif": { + "source": "iana", + "extensions": ["btif"] + }, + "image/prs.pti": { + "source": "iana", + "extensions": ["pti"] + }, + "image/pwg-raster": { + "source": "iana" + }, + "image/sgi": { + "source": "apache", + "extensions": ["sgi"] + }, + "image/svg+xml": { + "source": "iana", + "compressible": true, + "extensions": ["svg","svgz"] + }, + "image/t38": { + "source": "iana", + "extensions": ["t38"] + }, + "image/tiff": { + "source": "iana", + "compressible": false, + "extensions": ["tif","tiff"] + }, + "image/tiff-fx": { + "source": "iana", + "extensions": ["tfx"] + }, + "image/vnd.adobe.photoshop": { + "source": "iana", + "compressible": true, + "extensions": ["psd"] + }, + "image/vnd.airzip.accelerator.azv": { + "source": "iana", + "extensions": ["azv"] + }, + "image/vnd.cns.inf2": { + "source": "iana" + }, + "image/vnd.dece.graphic": { + "source": "iana", + "extensions": ["uvi","uvvi","uvg","uvvg"] + }, + "image/vnd.djvu": { + "source": "iana", + "extensions": ["djvu","djv"] + }, + "image/vnd.dvb.subtitle": { + "source": "iana", + "extensions": ["sub"] + }, + "image/vnd.dwg": { + "source": "iana", + "extensions": ["dwg"] + }, + "image/vnd.dxf": { + "source": "iana", + "extensions": ["dxf"] + }, + "image/vnd.fastbidsheet": { + "source": "iana", + "extensions": ["fbs"] + }, + "image/vnd.fpx": { + "source": "iana", + "extensions": ["fpx"] + }, + "image/vnd.fst": { + "source": "iana", + "extensions": ["fst"] + }, + "image/vnd.fujixerox.edmics-mmr": { + "source": "iana", + "extensions": ["mmr"] + }, + "image/vnd.fujixerox.edmics-rlc": { + "source": "iana", + "extensions": ["rlc"] + }, + "image/vnd.globalgraphics.pgb": { + "source": "iana" + }, + "image/vnd.microsoft.icon": { + "source": "iana", + "extensions": ["ico"] + }, + "image/vnd.mix": { + "source": "iana" + }, + "image/vnd.mozilla.apng": { + "source": "iana" + }, + "image/vnd.ms-dds": { + "extensions": ["dds"] + }, + "image/vnd.ms-modi": { + "source": "iana", + "extensions": ["mdi"] + }, + "image/vnd.ms-photo": { + "source": "apache", + "extensions": ["wdp"] + }, + "image/vnd.net-fpx": { + "source": "iana", + "extensions": ["npx"] + }, + "image/vnd.pco.b16": { + "source": "iana", + "extensions": ["b16"] + }, + "image/vnd.radiance": { + "source": "iana" + }, + "image/vnd.sealed.png": { + "source": "iana" + }, + "image/vnd.sealedmedia.softseal.gif": { + "source": "iana" + }, + "image/vnd.sealedmedia.softseal.jpg": { + "source": "iana" + }, + "image/vnd.svf": { + "source": "iana" + }, + "image/vnd.tencent.tap": { + "source": "iana", + "extensions": ["tap"] + }, + "image/vnd.valve.source.texture": { + "source": "iana", + "extensions": ["vtf"] + }, + "image/vnd.wap.wbmp": { + "source": "iana", + "extensions": ["wbmp"] + }, + "image/vnd.xiff": { + "source": "iana", + "extensions": ["xif"] + }, + "image/vnd.zbrush.pcx": { + "source": "iana", + "extensions": ["pcx"] + }, + "image/webp": { + "source": "apache", + "extensions": ["webp"] + }, + "image/wmf": { + "source": "iana", + "extensions": ["wmf"] + }, + "image/x-3ds": { + "source": "apache", + "extensions": ["3ds"] + }, + "image/x-cmu-raster": { + "source": "apache", + "extensions": ["ras"] + }, + "image/x-cmx": { + "source": "apache", + "extensions": ["cmx"] + }, + "image/x-freehand": { + "source": "apache", + "extensions": ["fh","fhc","fh4","fh5","fh7"] + }, + "image/x-icon": { + "source": "apache", + "compressible": true, + "extensions": ["ico"] + }, + "image/x-jng": { + "source": "nginx", + "extensions": ["jng"] + }, + "image/x-mrsid-image": { + "source": "apache", + "extensions": ["sid"] + }, + "image/x-ms-bmp": { + "source": "nginx", + "compressible": true, + "extensions": ["bmp"] + }, + "image/x-pcx": { + "source": "apache", + "extensions": ["pcx"] + }, + "image/x-pict": { + "source": "apache", + "extensions": ["pic","pct"] + }, + "image/x-portable-anymap": { + "source": "apache", + "extensions": ["pnm"] + }, + "image/x-portable-bitmap": { + "source": "apache", + "extensions": ["pbm"] + }, + "image/x-portable-graymap": { + "source": "apache", + "extensions": ["pgm"] + }, + "image/x-portable-pixmap": { + "source": "apache", + "extensions": ["ppm"] + }, + "image/x-rgb": { + "source": "apache", + "extensions": ["rgb"] + }, + "image/x-tga": { + "source": "apache", + "extensions": ["tga"] + }, + "image/x-xbitmap": { + "source": "apache", + "extensions": ["xbm"] + }, + "image/x-xcf": { + "compressible": false + }, + "image/x-xpixmap": { + "source": "apache", + "extensions": ["xpm"] + }, + "image/x-xwindowdump": { + "source": "apache", + "extensions": ["xwd"] + }, + "message/cpim": { + "source": "iana" + }, + "message/delivery-status": { + "source": "iana" + }, + "message/disposition-notification": { + "source": "iana", + "extensions": [ + "disposition-notification" + ] + }, + "message/external-body": { + "source": "iana" + }, + "message/feedback-report": { + "source": "iana" + }, + "message/global": { + "source": "iana", + "extensions": ["u8msg"] + }, + "message/global-delivery-status": { + "source": "iana", + "extensions": ["u8dsn"] + }, + "message/global-disposition-notification": { + "source": "iana", + "extensions": ["u8mdn"] + }, + "message/global-headers": { + "source": "iana", + "extensions": ["u8hdr"] + }, + "message/http": { + "source": "iana", + "compressible": false + }, + "message/imdn+xml": { + "source": "iana", + "compressible": true + }, + "message/news": { + "source": "iana" + }, + "message/partial": { + "source": "iana", + "compressible": false + }, + "message/rfc822": { + "source": "iana", + "compressible": true, + "extensions": ["eml","mime"] + }, + "message/s-http": { + "source": "iana" + }, + "message/sip": { + "source": "iana" + }, + "message/sipfrag": { + "source": "iana" + }, + "message/tracking-status": { + "source": "iana" + }, + "message/vnd.si.simp": { + "source": "iana" + }, + "message/vnd.wfa.wsc": { + "source": "iana", + "extensions": ["wsc"] + }, + "model/3mf": { + "source": "iana", + "extensions": ["3mf"] + }, + "model/e57": { + "source": "iana" + }, + "model/gltf+json": { + "source": "iana", + "compressible": true, + "extensions": ["gltf"] + }, + "model/gltf-binary": { + "source": "iana", + "compressible": true, + "extensions": ["glb"] + }, + "model/iges": { + "source": "iana", + "compressible": false, + "extensions": ["igs","iges"] + }, + "model/mesh": { + "source": "iana", + "compressible": false, + "extensions": ["msh","mesh","silo"] + }, + "model/mtl": { + "source": "iana", + "extensions": ["mtl"] + }, + "model/obj": { + "source": "iana", + "extensions": ["obj"] + }, + "model/stl": { + "source": "iana", + "extensions": ["stl"] + }, + "model/vnd.collada+xml": { + "source": "iana", + "compressible": true, + "extensions": ["dae"] + }, + "model/vnd.dwf": { + "source": "iana", + "extensions": ["dwf"] + }, + "model/vnd.flatland.3dml": { + "source": "iana" + }, + "model/vnd.gdl": { + "source": "iana", + "extensions": ["gdl"] + }, + "model/vnd.gs-gdl": { + "source": "apache" + }, + "model/vnd.gs.gdl": { + "source": "iana" + }, + "model/vnd.gtw": { + "source": "iana", + "extensions": ["gtw"] + }, + "model/vnd.moml+xml": { + "source": "iana", + "compressible": true + }, + "model/vnd.mts": { + "source": "iana", + "extensions": ["mts"] + }, + "model/vnd.opengex": { + "source": "iana", + "extensions": ["ogex"] + }, + "model/vnd.parasolid.transmit.binary": { + "source": "iana", + "extensions": ["x_b"] + }, + "model/vnd.parasolid.transmit.text": { + "source": "iana", + "extensions": ["x_t"] + }, + "model/vnd.rosette.annotated-data-model": { + "source": "iana" + }, + "model/vnd.sap.vds": { + "source": "iana", + "extensions": ["vds"] + }, + "model/vnd.usdz+zip": { + "source": "iana", + "compressible": false, + "extensions": ["usdz"] + }, + "model/vnd.valve.source.compiled-map": { + "source": "iana", + "extensions": ["bsp"] + }, + "model/vnd.vtu": { + "source": "iana", + "extensions": ["vtu"] + }, + "model/vrml": { + "source": "iana", + "compressible": false, + "extensions": ["wrl","vrml"] + }, + "model/x3d+binary": { + "source": "apache", + "compressible": false, + "extensions": ["x3db","x3dbz"] + }, + "model/x3d+fastinfoset": { + "source": "iana", + "extensions": ["x3db"] + }, + "model/x3d+vrml": { + "source": "apache", + "compressible": false, + "extensions": ["x3dv","x3dvz"] + }, + "model/x3d+xml": { + "source": "iana", + "compressible": true, + "extensions": ["x3d","x3dz"] + }, + "model/x3d-vrml": { + "source": "iana", + "extensions": ["x3dv"] + }, + "multipart/alternative": { + "source": "iana", + "compressible": false + }, + "multipart/appledouble": { + "source": "iana" + }, + "multipart/byteranges": { + "source": "iana" + }, + "multipart/digest": { + "source": "iana" + }, + "multipart/encrypted": { + "source": "iana", + "compressible": false + }, + "multipart/form-data": { + "source": "iana", + "compressible": false + }, + "multipart/header-set": { + "source": "iana" + }, + "multipart/mixed": { + "source": "iana" + }, + "multipart/multilingual": { + "source": "iana" + }, + "multipart/parallel": { + "source": "iana" + }, + "multipart/related": { + "source": "iana", + "compressible": false + }, + "multipart/report": { + "source": "iana" + }, + "multipart/signed": { + "source": "iana", + "compressible": false + }, + "multipart/vnd.bint.med-plus": { + "source": "iana" + }, + "multipart/voice-message": { + "source": "iana" + }, + "multipart/x-mixed-replace": { + "source": "iana" + }, + "text/1d-interleaved-parityfec": { + "source": "iana" + }, + "text/cache-manifest": { + "source": "iana", + "compressible": true, + "extensions": ["appcache","manifest"] + }, + "text/calendar": { + "source": "iana", + "extensions": ["ics","ifb"] + }, + "text/calender": { + "compressible": true + }, + "text/cmd": { + "compressible": true + }, + "text/coffeescript": { + "extensions": ["coffee","litcoffee"] + }, + "text/cql": { + "source": "iana" + }, + "text/cql-expression": { + "source": "iana" + }, + "text/cql-identifier": { + "source": "iana" + }, + "text/css": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["css"] + }, + "text/csv": { + "source": "iana", + "compressible": true, + "extensions": ["csv"] + }, + "text/csv-schema": { + "source": "iana" + }, + "text/directory": { + "source": "iana" + }, + "text/dns": { + "source": "iana" + }, + "text/ecmascript": { + "source": "iana" + }, + "text/encaprtp": { + "source": "iana" + }, + "text/enriched": { + "source": "iana" + }, + "text/fhirpath": { + "source": "iana" + }, + "text/flexfec": { + "source": "iana" + }, + "text/fwdred": { + "source": "iana" + }, + "text/gff3": { + "source": "iana" + }, + "text/grammar-ref-list": { + "source": "iana" + }, + "text/html": { + "source": "iana", + "compressible": true, + "extensions": ["html","htm","shtml"] + }, + "text/jade": { + "extensions": ["jade"] + }, + "text/javascript": { + "source": "iana", + "compressible": true + }, + "text/jcr-cnd": { + "source": "iana" + }, + "text/jsx": { + "compressible": true, + "extensions": ["jsx"] + }, + "text/less": { + "compressible": true, + "extensions": ["less"] + }, + "text/markdown": { + "source": "iana", + "compressible": true, + "extensions": ["markdown","md"] + }, + "text/mathml": { + "source": "nginx", + "extensions": ["mml"] + }, + "text/mdx": { + "compressible": true, + "extensions": ["mdx"] + }, + "text/mizar": { + "source": "iana" + }, + "text/n3": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["n3"] + }, + "text/parameters": { + "source": "iana", + "charset": "UTF-8" + }, + "text/parityfec": { + "source": "iana" + }, + "text/plain": { + "source": "iana", + "compressible": true, + "extensions": ["txt","text","conf","def","list","log","in","ini"] + }, + "text/provenance-notation": { + "source": "iana", + "charset": "UTF-8" + }, + "text/prs.fallenstein.rst": { + "source": "iana" + }, + "text/prs.lines.tag": { + "source": "iana", + "extensions": ["dsc"] + }, + "text/prs.prop.logic": { + "source": "iana" + }, + "text/raptorfec": { + "source": "iana" + }, + "text/red": { + "source": "iana" + }, + "text/rfc822-headers": { + "source": "iana" + }, + "text/richtext": { + "source": "iana", + "compressible": true, + "extensions": ["rtx"] + }, + "text/rtf": { + "source": "iana", + "compressible": true, + "extensions": ["rtf"] + }, + "text/rtp-enc-aescm128": { + "source": "iana" + }, + "text/rtploopback": { + "source": "iana" + }, + "text/rtx": { + "source": "iana" + }, + "text/sgml": { + "source": "iana", + "extensions": ["sgml","sgm"] + }, + "text/shaclc": { + "source": "iana" + }, + "text/shex": { + "extensions": ["shex"] + }, + "text/slim": { + "extensions": ["slim","slm"] + }, + "text/spdx": { + "source": "iana", + "extensions": ["spdx"] + }, + "text/strings": { + "source": "iana" + }, + "text/stylus": { + "extensions": ["stylus","styl"] + }, + "text/t140": { + "source": "iana" + }, + "text/tab-separated-values": { + "source": "iana", + "compressible": true, + "extensions": ["tsv"] + }, + "text/troff": { + "source": "iana", + "extensions": ["t","tr","roff","man","me","ms"] + }, + "text/turtle": { + "source": "iana", + "charset": "UTF-8", + "extensions": ["ttl"] + }, + "text/ulpfec": { + "source": "iana" + }, + "text/uri-list": { + "source": "iana", + "compressible": true, + "extensions": ["uri","uris","urls"] + }, + "text/vcard": { + "source": "iana", + "compressible": true, + "extensions": ["vcard"] + }, + "text/vnd.a": { + "source": "iana" + }, + "text/vnd.abc": { + "source": "iana" + }, + "text/vnd.ascii-art": { + "source": "iana" + }, + "text/vnd.curl": { + "source": "iana", + "extensions": ["curl"] + }, + "text/vnd.curl.dcurl": { + "source": "apache", + "extensions": ["dcurl"] + }, + "text/vnd.curl.mcurl": { + "source": "apache", + "extensions": ["mcurl"] + }, + "text/vnd.curl.scurl": { + "source": "apache", + "extensions": ["scurl"] + }, + "text/vnd.debian.copyright": { + "source": "iana", + "charset": "UTF-8" + }, + "text/vnd.dmclientscript": { + "source": "iana" + }, + "text/vnd.dvb.subtitle": { + "source": "iana", + "extensions": ["sub"] + }, + "text/vnd.esmertec.theme-descriptor": { + "source": "iana", + "charset": "UTF-8" + }, + "text/vnd.ficlab.flt": { + "source": "iana" + }, + "text/vnd.fly": { + "source": "iana", + "extensions": ["fly"] + }, + "text/vnd.fmi.flexstor": { + "source": "iana", + "extensions": ["flx"] + }, + "text/vnd.gml": { + "source": "iana" + }, + "text/vnd.graphviz": { + "source": "iana", + "extensions": ["gv"] + }, + "text/vnd.hans": { + "source": "iana" + }, + "text/vnd.hgl": { + "source": "iana" + }, + "text/vnd.in3d.3dml": { + "source": "iana", + "extensions": ["3dml"] + }, + "text/vnd.in3d.spot": { + "source": "iana", + "extensions": ["spot"] + }, + "text/vnd.iptc.newsml": { + "source": "iana" + }, + "text/vnd.iptc.nitf": { + "source": "iana" + }, + "text/vnd.latex-z": { + "source": "iana" + }, + "text/vnd.motorola.reflex": { + "source": "iana" + }, + "text/vnd.ms-mediapackage": { + "source": "iana" + }, + "text/vnd.net2phone.commcenter.command": { + "source": "iana" + }, + "text/vnd.radisys.msml-basic-layout": { + "source": "iana" + }, + "text/vnd.senx.warpscript": { + "source": "iana" + }, + "text/vnd.si.uricatalogue": { + "source": "iana" + }, + "text/vnd.sosi": { + "source": "iana" + }, + "text/vnd.sun.j2me.app-descriptor": { + "source": "iana", + "charset": "UTF-8", + "extensions": ["jad"] + }, + "text/vnd.trolltech.linguist": { + "source": "iana", + "charset": "UTF-8" + }, + "text/vnd.wap.si": { + "source": "iana" + }, + "text/vnd.wap.sl": { + "source": "iana" + }, + "text/vnd.wap.wml": { + "source": "iana", + "extensions": ["wml"] + }, + "text/vnd.wap.wmlscript": { + "source": "iana", + "extensions": ["wmls"] + }, + "text/vtt": { + "source": "iana", + "charset": "UTF-8", + "compressible": true, + "extensions": ["vtt"] + }, + "text/x-asm": { + "source": "apache", + "extensions": ["s","asm"] + }, + "text/x-c": { + "source": "apache", + "extensions": ["c","cc","cxx","cpp","h","hh","dic"] + }, + "text/x-component": { + "source": "nginx", + "extensions": ["htc"] + }, + "text/x-fortran": { + "source": "apache", + "extensions": ["f","for","f77","f90"] + }, + "text/x-gwt-rpc": { + "compressible": true + }, + "text/x-handlebars-template": { + "extensions": ["hbs"] + }, + "text/x-java-source": { + "source": "apache", + "extensions": ["java"] + }, + "text/x-jquery-tmpl": { + "compressible": true + }, + "text/x-lua": { + "extensions": ["lua"] + }, + "text/x-markdown": { + "compressible": true, + "extensions": ["mkd"] + }, + "text/x-nfo": { + "source": "apache", + "extensions": ["nfo"] + }, + "text/x-opml": { + "source": "apache", + "extensions": ["opml"] + }, + "text/x-org": { + "compressible": true, + "extensions": ["org"] + }, + "text/x-pascal": { + "source": "apache", + "extensions": ["p","pas"] + }, + "text/x-processing": { + "compressible": true, + "extensions": ["pde"] + }, + "text/x-sass": { + "extensions": ["sass"] + }, + "text/x-scss": { + "extensions": ["scss"] + }, + "text/x-setext": { + "source": "apache", + "extensions": ["etx"] + }, + "text/x-sfv": { + "source": "apache", + "extensions": ["sfv"] + }, + "text/x-suse-ymp": { + "compressible": true, + "extensions": ["ymp"] + }, + "text/x-uuencode": { + "source": "apache", + "extensions": ["uu"] + }, + "text/x-vcalendar": { + "source": "apache", + "extensions": ["vcs"] + }, + "text/x-vcard": { + "source": "apache", + "extensions": ["vcf"] + }, + "text/xml": { + "source": "iana", + "compressible": true, + "extensions": ["xml"] + }, + "text/xml-external-parsed-entity": { + "source": "iana" + }, + "text/yaml": { + "extensions": ["yaml","yml"] + }, + "video/1d-interleaved-parityfec": { + "source": "iana" + }, + "video/3gpp": { + "source": "iana", + "extensions": ["3gp","3gpp"] + }, + "video/3gpp-tt": { + "source": "iana" + }, + "video/3gpp2": { + "source": "iana", + "extensions": ["3g2"] + }, + "video/av1": { + "source": "iana" + }, + "video/bmpeg": { + "source": "iana" + }, + "video/bt656": { + "source": "iana" + }, + "video/celb": { + "source": "iana" + }, + "video/dv": { + "source": "iana" + }, + "video/encaprtp": { + "source": "iana" + }, + "video/ffv1": { + "source": "iana" + }, + "video/flexfec": { + "source": "iana" + }, + "video/h261": { + "source": "iana", + "extensions": ["h261"] + }, + "video/h263": { + "source": "iana", + "extensions": ["h263"] + }, + "video/h263-1998": { + "source": "iana" + }, + "video/h263-2000": { + "source": "iana" + }, + "video/h264": { + "source": "iana", + "extensions": ["h264"] + }, + "video/h264-rcdo": { + "source": "iana" + }, + "video/h264-svc": { + "source": "iana" + }, + "video/h265": { + "source": "iana" + }, + "video/iso.segment": { + "source": "iana", + "extensions": ["m4s"] + }, + "video/jpeg": { + "source": "iana", + "extensions": ["jpgv"] + }, + "video/jpeg2000": { + "source": "iana" + }, + "video/jpm": { + "source": "apache", + "extensions": ["jpm","jpgm"] + }, + "video/mj2": { + "source": "iana", + "extensions": ["mj2","mjp2"] + }, + "video/mp1s": { + "source": "iana" + }, + "video/mp2p": { + "source": "iana" + }, + "video/mp2t": { + "source": "iana", + "extensions": ["ts"] + }, + "video/mp4": { + "source": "iana", + "compressible": false, + "extensions": ["mp4","mp4v","mpg4"] + }, + "video/mp4v-es": { + "source": "iana" + }, + "video/mpeg": { + "source": "iana", + "compressible": false, + "extensions": ["mpeg","mpg","mpe","m1v","m2v"] + }, + "video/mpeg4-generic": { + "source": "iana" + }, + "video/mpv": { + "source": "iana" + }, + "video/nv": { + "source": "iana" + }, + "video/ogg": { + "source": "iana", + "compressible": false, + "extensions": ["ogv"] + }, + "video/parityfec": { + "source": "iana" + }, + "video/pointer": { + "source": "iana" + }, + "video/quicktime": { + "source": "iana", + "compressible": false, + "extensions": ["qt","mov"] + }, + "video/raptorfec": { + "source": "iana" + }, + "video/raw": { + "source": "iana" + }, + "video/rtp-enc-aescm128": { + "source": "iana" + }, + "video/rtploopback": { + "source": "iana" + }, + "video/rtx": { + "source": "iana" + }, + "video/scip": { + "source": "iana" + }, + "video/smpte291": { + "source": "iana" + }, + "video/smpte292m": { + "source": "iana" + }, + "video/ulpfec": { + "source": "iana" + }, + "video/vc1": { + "source": "iana" + }, + "video/vc2": { + "source": "iana" + }, + "video/vnd.cctv": { + "source": "iana" + }, + "video/vnd.dece.hd": { + "source": "iana", + "extensions": ["uvh","uvvh"] + }, + "video/vnd.dece.mobile": { + "source": "iana", + "extensions": ["uvm","uvvm"] + }, + "video/vnd.dece.mp4": { + "source": "iana" + }, + "video/vnd.dece.pd": { + "source": "iana", + "extensions": ["uvp","uvvp"] + }, + "video/vnd.dece.sd": { + "source": "iana", + "extensions": ["uvs","uvvs"] + }, + "video/vnd.dece.video": { + "source": "iana", + "extensions": ["uvv","uvvv"] + }, + "video/vnd.directv.mpeg": { + "source": "iana" + }, + "video/vnd.directv.mpeg-tts": { + "source": "iana" + }, + "video/vnd.dlna.mpeg-tts": { + "source": "iana" + }, + "video/vnd.dvb.file": { + "source": "iana", + "extensions": ["dvb"] + }, + "video/vnd.fvt": { + "source": "iana", + "extensions": ["fvt"] + }, + "video/vnd.hns.video": { + "source": "iana" + }, + "video/vnd.iptvforum.1dparityfec-1010": { + "source": "iana" + }, + "video/vnd.iptvforum.1dparityfec-2005": { + "source": "iana" + }, + "video/vnd.iptvforum.2dparityfec-1010": { + "source": "iana" + }, + "video/vnd.iptvforum.2dparityfec-2005": { + "source": "iana" + }, + "video/vnd.iptvforum.ttsavc": { + "source": "iana" + }, + "video/vnd.iptvforum.ttsmpeg2": { + "source": "iana" + }, + "video/vnd.motorola.video": { + "source": "iana" + }, + "video/vnd.motorola.videop": { + "source": "iana" + }, + "video/vnd.mpegurl": { + "source": "iana", + "extensions": ["mxu","m4u"] + }, + "video/vnd.ms-playready.media.pyv": { + "source": "iana", + "extensions": ["pyv"] + }, + "video/vnd.nokia.interleaved-multimedia": { + "source": "iana" + }, + "video/vnd.nokia.mp4vr": { + "source": "iana" + }, + "video/vnd.nokia.videovoip": { + "source": "iana" + }, + "video/vnd.objectvideo": { + "source": "iana" + }, + "video/vnd.radgamettools.bink": { + "source": "iana" + }, + "video/vnd.radgamettools.smacker": { + "source": "iana" + }, + "video/vnd.sealed.mpeg1": { + "source": "iana" + }, + "video/vnd.sealed.mpeg4": { + "source": "iana" + }, + "video/vnd.sealed.swf": { + "source": "iana" + }, + "video/vnd.sealedmedia.softseal.mov": { + "source": "iana" + }, + "video/vnd.uvvu.mp4": { + "source": "iana", + "extensions": ["uvu","uvvu"] + }, + "video/vnd.vivo": { + "source": "iana", + "extensions": ["viv"] + }, + "video/vnd.youtube.yt": { + "source": "iana" + }, + "video/vp8": { + "source": "iana" + }, + "video/webm": { + "source": "apache", + "compressible": false, + "extensions": ["webm"] + }, + "video/x-f4v": { + "source": "apache", + "extensions": ["f4v"] + }, + "video/x-fli": { + "source": "apache", + "extensions": ["fli"] + }, + "video/x-flv": { + "source": "apache", + "compressible": false, + "extensions": ["flv"] + }, + "video/x-m4v": { + "source": "apache", + "extensions": ["m4v"] + }, + "video/x-matroska": { + "source": "apache", + "compressible": false, + "extensions": ["mkv","mk3d","mks"] + }, + "video/x-mng": { + "source": "apache", + "extensions": ["mng"] + }, + "video/x-ms-asf": { + "source": "apache", + "extensions": ["asf","asx"] + }, + "video/x-ms-vob": { + "source": "apache", + "extensions": ["vob"] + }, + "video/x-ms-wm": { + "source": "apache", + "extensions": ["wm"] + }, + "video/x-ms-wmv": { + "source": "apache", + "compressible": false, + "extensions": ["wmv"] + }, + "video/x-ms-wmx": { + "source": "apache", + "extensions": ["wmx"] + }, + "video/x-ms-wvx": { + "source": "apache", + "extensions": ["wvx"] + }, + "video/x-msvideo": { + "source": "apache", + "extensions": ["avi"] + }, + "video/x-sgi-movie": { + "source": "apache", + "extensions": ["movie"] + }, + "video/x-smv": { + "source": "apache", + "extensions": ["smv"] + }, + "x-conference/x-cooltalk": { + "source": "apache", + "extensions": ["ice"] + }, + "x-shader/x-fragment": { + "compressible": true + }, + "x-shader/x-vertex": { + "compressible": true + } +} diff --git a/node_modules/mime-db/index.js b/node_modules/mime-db/index.js new file mode 100644 index 0000000..551031f --- /dev/null +++ b/node_modules/mime-db/index.js @@ -0,0 +1,11 @@ +/*! + * mime-db + * Copyright(c) 2014 Jonathan Ong + * MIT Licensed + */ + +/** + * Module exports. + */ + +module.exports = require('./db.json') diff --git a/node_modules/mime-db/package.json b/node_modules/mime-db/package.json new file mode 100644 index 0000000..bd6403f --- /dev/null +++ b/node_modules/mime-db/package.json @@ -0,0 +1,59 @@ +{ + "name": "mime-db", + "description": "Media Type Database", + "version": "1.47.0", + "contributors": [ + "Douglas Christopher Wilson ", + "Jonathan Ong (http://jongleberry.com)", + "Robert Kieffer (http://github.com/broofa)" + ], + "license": "MIT", + "keywords": [ + "mime", + "db", + "type", + "types", + "database", + "charset", + "charsets" + ], + "repository": "jshttp/mime-db", + "devDependencies": { + "bluebird": "3.7.2", + "co": "4.6.0", + "cogent": "1.0.1", + "csv-parse": "4.15.3", + "eslint": "7.23.0", + "eslint-config-standard": "15.0.1", + "eslint-plugin-import": "2.22.1", + "eslint-plugin-markdown": "2.0.0", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "4.3.1", + "eslint-plugin-standard": "4.1.0", + "gnode": "0.1.2", + "mocha": "8.3.2", + "nyc": "15.1.0", + "raw-body": "2.4.1", + "stream-to-array": "2.3.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "db.json", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "build": "node scripts/build", + "fetch": "node scripts/fetch-apache && gnode scripts/fetch-iana && node scripts/fetch-nginx", + "lint": "eslint .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "update": "npm run fetch && npm run build", + "version": "node scripts/version-history.js && git add HISTORY.md" + } +} diff --git a/node_modules/mime-types/HISTORY.md b/node_modules/mime-types/HISTORY.md new file mode 100644 index 0000000..38472be --- /dev/null +++ b/node_modules/mime-types/HISTORY.md @@ -0,0 +1,363 @@ +2.1.30 / 2021-04-02 +=================== + + * deps: mime-db@1.47.0 + - Add extension `.amr` to `audio/amr` + - Remove ambigious extensions from IANA for `application/*+xml` types + - Update primary extension to `.es` for `application/ecmascript` + +2.1.29 / 2021-02-17 +=================== + + * deps: mime-db@1.46.0 + - Add extension `.amr` to `audio/amr` + - Add extension `.m4s` to `video/iso.segment` + - Add extension `.opus` to `audio/ogg` + - Add new upstream MIME types + +2.1.28 / 2021-01-01 +=================== + + * deps: mime-db@1.45.0 + - Add `application/ubjson` with extension `.ubj` + - Add `image/avif` with extension `.avif` + - Add `image/ktx2` with extension `.ktx2` + - Add extension `.dbf` to `application/vnd.dbf` + - Add extension `.rar` to `application/vnd.rar` + - Add extension `.td` to `application/urc-targetdesc+xml` + - Add new upstream MIME types + - Fix extension of `application/vnd.apple.keynote` to be `.key` + +2.1.27 / 2020-04-23 +=================== + + * deps: mime-db@1.44.0 + - Add charsets from IANA + - Add extension `.cjs` to `application/node` + - Add new upstream MIME types + +2.1.26 / 2020-01-05 +=================== + + * deps: mime-db@1.43.0 + - Add `application/x-keepass2` with extension `.kdbx` + - Add extension `.mxmf` to `audio/mobile-xmf` + - Add extensions from IANA for `application/*+xml` types + - Add new upstream MIME types + +2.1.25 / 2019-11-12 +=================== + + * deps: mime-db@1.42.0 + - Add new upstream MIME types + - Add `application/toml` with extension `.toml` + - Add `image/vnd.ms-dds` with extension `.dds` + +2.1.24 / 2019-04-20 +=================== + + * deps: mime-db@1.40.0 + - Add extensions from IANA for `model/*` types + - Add `text/mdx` with extension `.mdx` + +2.1.23 / 2019-04-17 +=================== + + * deps: mime-db@~1.39.0 + - Add extensions `.siv` and `.sieve` to `application/sieve` + - Add new upstream MIME types + +2.1.22 / 2019-02-14 +=================== + + * deps: mime-db@~1.38.0 + - Add extension `.nq` to `application/n-quads` + - Add extension `.nt` to `application/n-triples` + - Add new upstream MIME types + - Mark `text/less` as compressible + +2.1.21 / 2018-10-19 +=================== + + * deps: mime-db@~1.37.0 + - Add extensions to HEIC image types + - Add new upstream MIME types + +2.1.20 / 2018-08-26 +=================== + + * deps: mime-db@~1.36.0 + - Add Apple file extensions from IANA + - Add extensions from IANA for `image/*` types + - Add new upstream MIME types + +2.1.19 / 2018-07-17 +=================== + + * deps: mime-db@~1.35.0 + - Add extension `.csl` to `application/vnd.citationstyles.style+xml` + - Add extension `.es` to `application/ecmascript` + - Add extension `.owl` to `application/rdf+xml` + - Add new upstream MIME types + - Add UTF-8 as default charset for `text/turtle` + +2.1.18 / 2018-02-16 +=================== + + * deps: mime-db@~1.33.0 + - Add `application/raml+yaml` with extension `.raml` + - Add `application/wasm` with extension `.wasm` + - Add `text/shex` with extension `.shex` + - Add extensions for JPEG-2000 images + - Add extensions from IANA for `message/*` types + - Add new upstream MIME types + - Update font MIME types + - Update `text/hjson` to registered `application/hjson` + +2.1.17 / 2017-09-01 +=================== + + * deps: mime-db@~1.30.0 + - Add `application/vnd.ms-outlook` + - Add `application/x-arj` + - Add extension `.mjs` to `application/javascript` + - Add glTF types and extensions + - Add new upstream MIME types + - Add `text/x-org` + - Add VirtualBox MIME types + - Fix `source` records for `video/*` types that are IANA + - Update `font/opentype` to registered `font/otf` + +2.1.16 / 2017-07-24 +=================== + + * deps: mime-db@~1.29.0 + - Add `application/fido.trusted-apps+json` + - Add extension `.wadl` to `application/vnd.sun.wadl+xml` + - Add extension `.gz` to `application/gzip` + - Add new upstream MIME types + - Update extensions `.md` and `.markdown` to be `text/markdown` + +2.1.15 / 2017-03-23 +=================== + + * deps: mime-db@~1.27.0 + - Add new mime types + - Add `image/apng` + +2.1.14 / 2017-01-14 +=================== + + * deps: mime-db@~1.26.0 + - Add new mime types + +2.1.13 / 2016-11-18 +=================== + + * deps: mime-db@~1.25.0 + - Add new mime types + +2.1.12 / 2016-09-18 +=================== + + * deps: mime-db@~1.24.0 + - Add new mime types + - Add `audio/mp3` + +2.1.11 / 2016-05-01 +=================== + + * deps: mime-db@~1.23.0 + - Add new mime types + +2.1.10 / 2016-02-15 +=================== + + * deps: mime-db@~1.22.0 + - Add new mime types + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + +2.1.9 / 2016-01-06 +================== + + * deps: mime-db@~1.21.0 + - Add new mime types + +2.1.8 / 2015-11-30 +================== + + * deps: mime-db@~1.20.0 + - Add new mime types + +2.1.7 / 2015-09-20 +================== + + * deps: mime-db@~1.19.0 + - Add new mime types + +2.1.6 / 2015-09-03 +================== + + * deps: mime-db@~1.18.0 + - Add new mime types + +2.1.5 / 2015-08-20 +================== + + * deps: mime-db@~1.17.0 + - Add new mime types + +2.1.4 / 2015-07-30 +================== + + * deps: mime-db@~1.16.0 + - Add new mime types + +2.1.3 / 2015-07-13 +================== + + * deps: mime-db@~1.15.0 + - Add new mime types + +2.1.2 / 2015-06-25 +================== + + * deps: mime-db@~1.14.0 + - Add new mime types + +2.1.1 / 2015-06-08 +================== + + * perf: fix deopt during mapping + +2.1.0 / 2015-06-07 +================== + + * Fix incorrectly treating extension-less file name as extension + - i.e. `'path/to/json'` will no longer return `application/json` + * Fix `.charset(type)` to accept parameters + * Fix `.charset(type)` to match case-insensitive + * Improve generation of extension to MIME mapping + * Refactor internals for readability and no argument reassignment + * Prefer `application/*` MIME types from the same source + * Prefer any type over `application/octet-stream` + * deps: mime-db@~1.13.0 + - Add nginx as a source + - Add new mime types + +2.0.14 / 2015-06-06 +=================== + + * deps: mime-db@~1.12.0 + - Add new mime types + +2.0.13 / 2015-05-31 +=================== + + * deps: mime-db@~1.11.0 + - Add new mime types + +2.0.12 / 2015-05-19 +=================== + + * deps: mime-db@~1.10.0 + - Add new mime types + +2.0.11 / 2015-05-05 +=================== + + * deps: mime-db@~1.9.1 + - Add new mime types + +2.0.10 / 2015-03-13 +=================== + + * deps: mime-db@~1.8.0 + - Add new mime types + +2.0.9 / 2015-02-09 +================== + + * deps: mime-db@~1.7.0 + - Add new mime types + - Community extensions ownership transferred from `node-mime` + +2.0.8 / 2015-01-29 +================== + + * deps: mime-db@~1.6.0 + - Add new mime types + +2.0.7 / 2014-12-30 +================== + + * deps: mime-db@~1.5.0 + - Add new mime types + - Fix various invalid MIME type entries + +2.0.6 / 2014-12-30 +================== + + * deps: mime-db@~1.4.0 + - Add new mime types + - Fix various invalid MIME type entries + - Remove example template MIME types + +2.0.5 / 2014-12-29 +================== + + * deps: mime-db@~1.3.1 + - Fix missing extensions + +2.0.4 / 2014-12-10 +================== + + * deps: mime-db@~1.3.0 + - Add new mime types + +2.0.3 / 2014-11-09 +================== + + * deps: mime-db@~1.2.0 + - Add new mime types + +2.0.2 / 2014-09-28 +================== + + * deps: mime-db@~1.1.0 + - Add new mime types + - Add additional compressible + - Update charsets + +2.0.1 / 2014-09-07 +================== + + * Support Node.js 0.6 + +2.0.0 / 2014-09-02 +================== + + * Use `mime-db` + * Remove `.define()` + +1.0.2 / 2014-08-04 +================== + + * Set charset=utf-8 for `text/javascript` + +1.0.1 / 2014-06-24 +================== + + * Add `text/jsx` type + +1.0.0 / 2014-05-12 +================== + + * Return `false` for unknown types + * Set charset=utf-8 for `application/json` + +0.1.0 / 2014-05-02 +================== + + * Initial release diff --git a/node_modules/mime-types/LICENSE b/node_modules/mime-types/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/node_modules/mime-types/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/mime-types/README.md b/node_modules/mime-types/README.md new file mode 100644 index 0000000..c978ac2 --- /dev/null +++ b/node_modules/mime-types/README.md @@ -0,0 +1,113 @@ +# mime-types + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][ci-image]][ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +The ultimate javascript content-type utility. + +Similar to [the `mime@1.x` module](https://www.npmjs.com/package/mime), except: + +- __No fallbacks.__ Instead of naively returning the first available type, + `mime-types` simply returns `false`, so do + `var type = mime.lookup('unrecognized') || 'application/octet-stream'`. +- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`. +- No `.define()` functionality +- Bug fixes for `.lookup(path)` + +Otherwise, the API is compatible with `mime` 1.x. + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install mime-types +``` + +## Adding Types + +All mime types are based on [mime-db](https://www.npmjs.com/package/mime-db), +so open a PR there if you'd like to add mime types. + +## API + +```js +var mime = require('mime-types') +``` + +All functions return `false` if input is invalid or not found. + +### mime.lookup(path) + +Lookup the content-type associated with a file. + +```js +mime.lookup('json') // 'application/json' +mime.lookup('.md') // 'text/markdown' +mime.lookup('file.html') // 'text/html' +mime.lookup('folder/file.js') // 'application/javascript' +mime.lookup('folder/.htaccess') // false + +mime.lookup('cats') // false +``` + +### mime.contentType(type) + +Create a full content-type header given a content-type or extension. +When given an extension, `mime.lookup` is used to get the matching +content-type, otherwise the given content-type is used. Then if the +content-type does not already have a `charset` parameter, `mime.charset` +is used to get the default charset and add to the returned content-type. + +```js +mime.contentType('markdown') // 'text/x-markdown; charset=utf-8' +mime.contentType('file.json') // 'application/json; charset=utf-8' +mime.contentType('text/html') // 'text/html; charset=utf-8' +mime.contentType('text/html; charset=iso-8859-1') // 'text/html; charset=iso-8859-1' + +// from a full path +mime.contentType(path.extname('/path/to/file.json')) // 'application/json; charset=utf-8' +``` + +### mime.extension(type) + +Get the default extension for a content-type. + +```js +mime.extension('application/octet-stream') // 'bin' +``` + +### mime.charset(type) + +Lookup the implied default charset of a content-type. + +```js +mime.charset('text/markdown') // 'UTF-8' +``` + +### var type = mime.types[extension] + +A map of content-types by extension. + +### [extensions...] = mime.extensions[type] + +A map of extensions by content-type. + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/jshttp/mime-types/master?label=ci +[ci-url]: https://github.com/jshttp/mime-types/actions?query=workflow%3Aci +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-types/master +[coveralls-url]: https://coveralls.io/r/jshttp/mime-types?branch=master +[node-version-image]: https://badgen.net/npm/node/mime-types +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/mime-types +[npm-url]: https://npmjs.org/package/mime-types +[npm-version-image]: https://badgen.net/npm/v/mime-types diff --git a/node_modules/mime-types/index.js b/node_modules/mime-types/index.js new file mode 100644 index 0000000..b9f34d5 --- /dev/null +++ b/node_modules/mime-types/index.js @@ -0,0 +1,188 @@ +/*! + * mime-types + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var db = require('mime-db') +var extname = require('path').extname + +/** + * Module variables. + * @private + */ + +var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/ +var TEXT_TYPE_REGEXP = /^text\//i + +/** + * Module exports. + * @public + */ + +exports.charset = charset +exports.charsets = { lookup: charset } +exports.contentType = contentType +exports.extension = extension +exports.extensions = Object.create(null) +exports.lookup = lookup +exports.types = Object.create(null) + +// Populate the extensions/types maps +populateMaps(exports.extensions, exports.types) + +/** + * Get the default charset for a MIME type. + * + * @param {string} type + * @return {boolean|string} + */ + +function charset (type) { + if (!type || typeof type !== 'string') { + return false + } + + // TODO: use media-typer + var match = EXTRACT_TYPE_REGEXP.exec(type) + var mime = match && db[match[1].toLowerCase()] + + if (mime && mime.charset) { + return mime.charset + } + + // default text/* to utf-8 + if (match && TEXT_TYPE_REGEXP.test(match[1])) { + return 'UTF-8' + } + + return false +} + +/** + * Create a full Content-Type header given a MIME type or extension. + * + * @param {string} str + * @return {boolean|string} + */ + +function contentType (str) { + // TODO: should this even be in this module? + if (!str || typeof str !== 'string') { + return false + } + + var mime = str.indexOf('/') === -1 + ? exports.lookup(str) + : str + + if (!mime) { + return false + } + + // TODO: use content-type or other module + if (mime.indexOf('charset') === -1) { + var charset = exports.charset(mime) + if (charset) mime += '; charset=' + charset.toLowerCase() + } + + return mime +} + +/** + * Get the default extension for a MIME type. + * + * @param {string} type + * @return {boolean|string} + */ + +function extension (type) { + if (!type || typeof type !== 'string') { + return false + } + + // TODO: use media-typer + var match = EXTRACT_TYPE_REGEXP.exec(type) + + // get extensions + var exts = match && exports.extensions[match[1].toLowerCase()] + + if (!exts || !exts.length) { + return false + } + + return exts[0] +} + +/** + * Lookup the MIME type for a file path/extension. + * + * @param {string} path + * @return {boolean|string} + */ + +function lookup (path) { + if (!path || typeof path !== 'string') { + return false + } + + // get the extension ("ext" or ".ext" or full path) + var extension = extname('x.' + path) + .toLowerCase() + .substr(1) + + if (!extension) { + return false + } + + return exports.types[extension] || false +} + +/** + * Populate the extensions and types maps. + * @private + */ + +function populateMaps (extensions, types) { + // source preference (least -> most) + var preference = ['nginx', 'apache', undefined, 'iana'] + + Object.keys(db).forEach(function forEachMimeType (type) { + var mime = db[type] + var exts = mime.extensions + + if (!exts || !exts.length) { + return + } + + // mime -> extensions + extensions[type] = exts + + // extension -> mime + for (var i = 0; i < exts.length; i++) { + var extension = exts[i] + + if (types[extension]) { + var from = preference.indexOf(db[types[extension]].source) + var to = preference.indexOf(mime.source) + + if (types[extension] !== 'application/octet-stream' && + (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) { + // skip the remapping + continue + } + } + + // set the extension -> mime + types[extension] = type + } + }) +} diff --git a/node_modules/mime-types/package.json b/node_modules/mime-types/package.json new file mode 100644 index 0000000..ea53dd2 --- /dev/null +++ b/node_modules/mime-types/package.json @@ -0,0 +1,44 @@ +{ + "name": "mime-types", + "description": "The ultimate javascript content-type utility.", + "version": "2.1.30", + "contributors": [ + "Douglas Christopher Wilson ", + "Jeremiah Senkpiel (https://searchbeam.jit.su)", + "Jonathan Ong (http://jongleberry.com)" + ], + "license": "MIT", + "keywords": [ + "mime", + "types" + ], + "repository": "jshttp/mime-types", + "dependencies": { + "mime-db": "1.47.0" + }, + "devDependencies": { + "eslint": "7.23.0", + "eslint-config-standard": "14.1.1", + "eslint-plugin-import": "2.22.1", + "eslint-plugin-markdown": "2.0.0", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "4.3.1", + "eslint-plugin-standard": "4.1.0", + "mocha": "8.3.2", + "nyc": "15.1.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec test/test.js", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + } +} diff --git a/node_modules/mimic-response/index.js b/node_modules/mimic-response/index.js new file mode 100644 index 0000000..d5e33be --- /dev/null +++ b/node_modules/mimic-response/index.js @@ -0,0 +1,32 @@ +'use strict'; + +// We define these manually to ensure they're always copied +// even if they would move up the prototype chain +// https://nodejs.org/api/http.html#http_class_http_incomingmessage +const knownProps = [ + 'destroy', + 'setTimeout', + 'socket', + 'headers', + 'trailers', + 'rawHeaders', + 'statusCode', + 'httpVersion', + 'httpVersionMinor', + 'httpVersionMajor', + 'rawTrailers', + 'statusMessage' +]; + +module.exports = (fromStream, toStream) => { + const fromProps = new Set(Object.keys(fromStream).concat(knownProps)); + + for (const prop of fromProps) { + // Don't overwrite existing properties + if (prop in toStream) { + continue; + } + + toStream[prop] = typeof fromStream[prop] === 'function' ? fromStream[prop].bind(fromStream) : fromStream[prop]; + } +}; diff --git a/node_modules/mimic-response/license b/node_modules/mimic-response/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/mimic-response/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/mimic-response/package.json b/node_modules/mimic-response/package.json new file mode 100644 index 0000000..689cb61 --- /dev/null +++ b/node_modules/mimic-response/package.json @@ -0,0 +1,37 @@ +{ + "name": "mimic-response", + "version": "1.0.1", + "description": "Mimic a Node.js HTTP response stream", + "license": "MIT", + "repository": "sindresorhus/mimic-response", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "xo && ava" + }, + "files": [ + "index.js" + ], + "keywords": [ + "mimic", + "response", + "stream", + "http", + "https", + "request", + "get", + "core" + ], + "devDependencies": { + "ava": "*", + "create-test-server": "^0.1.0", + "pify": "^3.0.0", + "xo": "*" + } +} diff --git a/node_modules/mimic-response/readme.md b/node_modules/mimic-response/readme.md new file mode 100644 index 0000000..e07ec66 --- /dev/null +++ b/node_modules/mimic-response/readme.md @@ -0,0 +1,54 @@ +# mimic-response [![Build Status](https://travis-ci.org/sindresorhus/mimic-response.svg?branch=master)](https://travis-ci.org/sindresorhus/mimic-response) + +> Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + + +## Install + +``` +$ npm install mimic-response +``` + + +## Usage + +```js +const stream = require('stream'); +const mimicResponse = require('mimic-response'); + +const responseStream = getHttpResponseStream(); +const myStream = new stream.PassThrough(); + +mimicResponse(responseStream, myStream); + +console.log(myStream.statusCode); +//=> 200 +``` + + +## API + +### mimicResponse(from, to) + +#### from + +Type: `Stream` + +[Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage) + +#### to + +Type: `Stream` + +Any stream. + + +## Related + +- [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one +- [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/node-fetch/CHANGELOG.md b/node_modules/node-fetch/CHANGELOG.md new file mode 100644 index 0000000..543d3d9 --- /dev/null +++ b/node_modules/node-fetch/CHANGELOG.md @@ -0,0 +1,272 @@ + +Changelog +========= + + +# 2.x release + +## v2.6.1 + +**This is an important security release. It is strongly recommended to update as soon as possible.** + +- Fix: honor the `size` option after following a redirect. + +## v2.6.0 + +- Enhance: `options.agent`, it now accepts a function that returns custom http(s).Agent instance based on current URL, see readme for more information. +- Fix: incorrect `Content-Length` was returned for stream body in 2.5.0 release; note that `node-fetch` doesn't calculate content length for stream body. +- Fix: `Response.url` should return empty string instead of `null` by default. + +## v2.5.0 + +- Enhance: `Response` object now includes `redirected` property. +- Enhance: `fetch()` now accepts third-party `Blob` implementation as body. +- Other: disable `package-lock.json` generation as we never commit them. +- Other: dev dependency update. +- Other: readme update. + +## v2.4.1 + +- Fix: `Blob` import rule for node < 10, as `Readable` isn't a named export. + +## v2.4.0 + +- Enhance: added `Brotli` compression support (using node's zlib). +- Enhance: updated `Blob` implementation per spec. +- Fix: set content type automatically for `URLSearchParams`. +- Fix: `Headers` now reject empty header names. +- Fix: test cases, as node 12+ no longer accepts invalid header response. + +## v2.3.0 + +- Enhance: added `AbortSignal` support, with README example. +- Enhance: handle invalid `Location` header during redirect by rejecting them explicitly with `FetchError`. +- Fix: update `browser.js` to support react-native environment, where `self` isn't available globally. + +## v2.2.1 + +- Fix: `compress` flag shouldn't overwrite existing `Accept-Encoding` header. +- Fix: multiple `import` rules, where `PassThrough` etc. doesn't have a named export when using node <10 and `--exerimental-modules` flag. +- Other: Better README. + +## v2.2.0 + +- Enhance: Support all `ArrayBuffer` view types +- Enhance: Support Web Workers +- Enhance: Support Node.js' `--experimental-modules` mode; deprecate `.es.js` file +- Fix: Add `__esModule` property to the exports object +- Other: Better example in README for writing response to a file +- Other: More tests for Agent + +## v2.1.2 + +- Fix: allow `Body` methods to work on `ArrayBuffer`-backed `Body` objects +- Fix: reject promise returned by `Body` methods when the accumulated `Buffer` exceeds the maximum size +- Fix: support custom `Host` headers with any casing +- Fix: support importing `fetch()` from TypeScript in `browser.js` +- Fix: handle the redirect response body properly + +## v2.1.1 + +Fix packaging errors in v2.1.0. + +## v2.1.0 + +- Enhance: allow using ArrayBuffer as the `body` of a `fetch()` or `Request` +- Fix: store HTTP headers of a `Headers` object internally with the given case, for compatibility with older servers that incorrectly treated header names in a case-sensitive manner +- Fix: silently ignore invalid HTTP headers +- Fix: handle HTTP redirect responses without a `Location` header just like non-redirect responses +- Fix: include bodies when following a redirection when appropriate + +## v2.0.0 + +This is a major release. Check [our upgrade guide](https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md) for an overview on some key differences between v1 and v2. + +### General changes + +- Major: Node.js 0.10.x and 0.12.x support is dropped +- Major: `require('node-fetch/lib/response')` etc. is now unsupported; use `require('node-fetch').Response` or ES6 module imports +- Enhance: start testing on Node.js v4.x, v6.x, v8.x LTS, as well as v9.x stable +- Enhance: use Rollup to produce a distributed bundle (less memory overhead and faster startup) +- Enhance: make `Object.prototype.toString()` on Headers, Requests, and Responses return correct class strings +- Other: rewrite in ES2015 using Babel +- Other: use Codecov for code coverage tracking +- Other: update package.json script for npm 5 +- Other: `encoding` module is now optional (alpha.7) +- Other: expose browser.js through package.json, avoid bundling mishaps (alpha.9) +- Other: allow TypeScript to `import` node-fetch by exposing default (alpha.9) + +### HTTP requests + +- Major: overwrite user's `Content-Length` if we can be sure our information is correct (per spec) +- Fix: errors in a response are caught before the body is accessed +- Fix: support WHATWG URL objects, created by `whatwg-url` package or `require('url').URL` in Node.js 7+ + +### Response and Request classes + +- Major: `response.text()` no longer attempts to detect encoding, instead always opting for UTF-8 (per spec); use `response.textConverted()` for the v1 behavior +- Major: make `response.json()` throw error instead of returning an empty object on 204 no-content respose (per spec; reverts behavior changed in v1.6.2) +- Major: internal methods are no longer exposed +- Major: throw error when a `GET` or `HEAD` Request is constructed with a non-null body (per spec) +- Enhance: add `response.arrayBuffer()` (also applies to Requests) +- Enhance: add experimental `response.blob()` (also applies to Requests) +- Enhance: `URLSearchParams` is now accepted as a body +- Enhance: wrap `response.json()` json parsing error as `FetchError` +- Fix: fix Request and Response with `null` body + +### Headers class + +- Major: remove `headers.getAll()`; make `get()` return all headers delimited by commas (per spec) +- Enhance: make Headers iterable +- Enhance: make Headers constructor accept an array of tuples +- Enhance: make sure header names and values are valid in HTTP +- Fix: coerce Headers prototype function parameters to strings, where applicable + +### Documentation + +- Enhance: more comprehensive API docs +- Enhance: add a list of default headers in README + + +# 1.x release + +## backport releases (v1.7.0 and beyond) + +See [changelog on 1.x branch](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) for details. + +## v1.6.3 + +- Enhance: error handling document to explain `FetchError` design +- Fix: support `form-data` 2.x releases (requires `form-data` >= 2.1.0) + +## v1.6.2 + +- Enhance: minor document update +- Fix: response.json() returns empty object on 204 no-content response instead of throwing a syntax error + +## v1.6.1 + +- Fix: if `res.body` is a non-stream non-formdata object, we will call `body.toString` and send it as a string +- Fix: `counter` value is incorrectly set to `follow` value when wrapping Request instance +- Fix: documentation update + +## v1.6.0 + +- Enhance: added `res.buffer()` api for convenience, it returns body as a Node.js buffer +- Enhance: better old server support by handling raw deflate response +- Enhance: skip encoding detection for non-HTML/XML response +- Enhance: minor document update +- Fix: HEAD request doesn't need decompression, as body is empty +- Fix: `req.body` now accepts a Node.js buffer + +## v1.5.3 + +- Fix: handle 204 and 304 responses when body is empty but content-encoding is gzip/deflate +- Fix: allow resolving response and cloned response in any order +- Fix: avoid setting `content-length` when `form-data` body use streams +- Fix: send DELETE request with content-length when body is present +- Fix: allow any url when calling new Request, but still reject non-http(s) url in fetch + +## v1.5.2 + +- Fix: allow node.js core to handle keep-alive connection pool when passing a custom agent + +## v1.5.1 + +- Fix: redirect mode `manual` should work even when there is no redirection or broken redirection + +## v1.5.0 + +- Enhance: rejected promise now use custom `Error` (thx to @pekeler) +- Enhance: `FetchError` contains `err.type` and `err.code`, allows for better error handling (thx to @pekeler) +- Enhance: basic support for redirect mode `manual` and `error`, allows for location header extraction (thx to @jimmywarting for the initial PR) + +## v1.4.1 + +- Fix: wrapping Request instance with FormData body again should preserve the body as-is + +## v1.4.0 + +- Enhance: Request and Response now have `clone` method (thx to @kirill-konshin for the initial PR) +- Enhance: Request and Response now have proper string and buffer body support (thx to @kirill-konshin) +- Enhance: Body constructor has been refactored out (thx to @kirill-konshin) +- Enhance: Headers now has `forEach` method (thx to @tricoder42) +- Enhance: back to 100% code coverage +- Fix: better form-data support (thx to @item4) +- Fix: better character encoding detection under chunked encoding (thx to @dsuket for the initial PR) + +## v1.3.3 + +- Fix: make sure `Content-Length` header is set when body is string for POST/PUT/PATCH requests +- Fix: handle body stream error, for cases such as incorrect `Content-Encoding` header +- Fix: when following certain redirects, use `GET` on subsequent request per Fetch Spec +- Fix: `Request` and `Response` constructors now parse headers input using `Headers` + +## v1.3.2 + +- Enhance: allow auto detect of form-data input (no `FormData` spec on node.js, this is form-data specific feature) + +## v1.3.1 + +- Enhance: allow custom host header to be set (server-side only feature, as it's a forbidden header on client-side) + +## v1.3.0 + +- Enhance: now `fetch.Request` is exposed as well + +## v1.2.1 + +- Enhance: `Headers` now normalized `Number` value to `String`, prevent common mistakes + +## v1.2.0 + +- Enhance: now fetch.Headers and fetch.Response are exposed, making testing easier + +## v1.1.2 + +- Fix: `Headers` should only support `String` and `Array` properties, and ignore others + +## v1.1.1 + +- Enhance: now req.headers accept both plain object and `Headers` instance + +## v1.1.0 + +- Enhance: timeout now also applies to response body (in case of slow response) +- Fix: timeout is now cleared properly when fetch is done/has failed + +## v1.0.6 + +- Fix: less greedy content-type charset matching + +## v1.0.5 + +- Fix: when `follow = 0`, fetch should not follow redirect +- Enhance: update tests for better coverage +- Enhance: code formatting +- Enhance: clean up doc + +## v1.0.4 + +- Enhance: test iojs support +- Enhance: timeout attached to socket event only fire once per redirect + +## v1.0.3 + +- Fix: response size limit should reject large chunk +- Enhance: added character encoding detection for xml, such as rss/atom feed (encoding in DTD) + +## v1.0.2 + +- Fix: added res.ok per spec change + +## v1.0.0 + +- Enhance: better test coverage and doc + + +# 0.x release + +## v0.1 + +- Major: initial public release diff --git a/node_modules/node-fetch/LICENSE.md b/node_modules/node-fetch/LICENSE.md new file mode 100644 index 0000000..660ffec --- /dev/null +++ b/node_modules/node-fetch/LICENSE.md @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 David Frank + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/node-fetch/README.md b/node_modules/node-fetch/README.md new file mode 100644 index 0000000..2dde742 --- /dev/null +++ b/node_modules/node-fetch/README.md @@ -0,0 +1,590 @@ +node-fetch +========== + +[![npm version][npm-image]][npm-url] +[![build status][travis-image]][travis-url] +[![coverage status][codecov-image]][codecov-url] +[![install size][install-size-image]][install-size-url] +[![Discord][discord-image]][discord-url] + +A light-weight module that brings `window.fetch` to Node.js + +(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567)) + +[![Backers][opencollective-image]][opencollective-url] + + + +- [Motivation](#motivation) +- [Features](#features) +- [Difference from client-side fetch](#difference-from-client-side-fetch) +- [Installation](#installation) +- [Loading and configuring the module](#loading-and-configuring-the-module) +- [Common Usage](#common-usage) + - [Plain text or HTML](#plain-text-or-html) + - [JSON](#json) + - [Simple Post](#simple-post) + - [Post with JSON](#post-with-json) + - [Post with form parameters](#post-with-form-parameters) + - [Handling exceptions](#handling-exceptions) + - [Handling client and server errors](#handling-client-and-server-errors) +- [Advanced Usage](#advanced-usage) + - [Streams](#streams) + - [Buffer](#buffer) + - [Accessing Headers and other Meta data](#accessing-headers-and-other-meta-data) + - [Extract Set-Cookie Header](#extract-set-cookie-header) + - [Post data using a file stream](#post-data-using-a-file-stream) + - [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart) + - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal) +- [API](#api) + - [fetch(url[, options])](#fetchurl-options) + - [Options](#options) + - [Class: Request](#class-request) + - [Class: Response](#class-response) + - [Class: Headers](#class-headers) + - [Interface: Body](#interface-body) + - [Class: FetchError](#class-fetcherror) +- [License](#license) +- [Acknowledgement](#acknowledgement) + + + +## Motivation + +Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime. + +See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side). + +## Features + +- Stay consistent with `window.fetch` API. +- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences. +- Use native promise but allow substituting it with [insert your favorite promise library]. +- Use native Node streams for body on both request and response. +- Decode content encoding (gzip/deflate) properly and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically. +- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](ERROR-HANDLING.md) for troubleshooting. + +## Difference from client-side fetch + +- See [Known Differences](LIMITS.md) for details. +- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue. +- Pull requests are welcomed too! + +## Installation + +Current stable release (`2.x`) + +```sh +$ npm install node-fetch +``` + +## Loading and configuring the module +We suggest you load the module via `require` until the stabilization of ES modules in node: +```js +const fetch = require('node-fetch'); +``` + +If you are using a Promise library other than native, set it through `fetch.Promise`: +```js +const Bluebird = require('bluebird'); + +fetch.Promise = Bluebird; +``` + +## Common Usage + +NOTE: The documentation below is up-to-date with `2.x` releases; see the [`1.x` readme](https://github.com/bitinn/node-fetch/blob/1.x/README.md), [changelog](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) and [2.x upgrade guide](UPGRADE-GUIDE.md) for the differences. + +#### Plain text or HTML +```js +fetch('https://github.com/') + .then(res => res.text()) + .then(body => console.log(body)); +``` + +#### JSON + +```js + +fetch('https://api.github.com/users/github') + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Simple Post +```js +fetch('https://httpbin.org/post', { method: 'POST', body: 'a=1' }) + .then(res => res.json()) // expecting a json response + .then(json => console.log(json)); +``` + +#### Post with JSON + +```js +const body = { a: 1 }; + +fetch('https://httpbin.org/post', { + method: 'post', + body: JSON.stringify(body), + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Post with form parameters +`URLSearchParams` is available in Node.js as of v7.5.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods. + +NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such: + +```js +const { URLSearchParams } = require('url'); + +const params = new URLSearchParams(); +params.append('a', 1); + +fetch('https://httpbin.org/post', { method: 'POST', body: params }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Handling exceptions +NOTE: 3xx-5xx responses are *NOT* exceptions and should be handled in `then()`; see the next section for more information. + +Adding a catch to the fetch promise chain will catch *all* exceptions, such as errors originating from node core libraries, network errors and operational errors, which are instances of FetchError. See the [error handling document](ERROR-HANDLING.md) for more details. + +```js +fetch('https://domain.invalid/') + .catch(err => console.error(err)); +``` + +#### Handling client and server errors +It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses: + +```js +function checkStatus(res) { + if (res.ok) { // res.status >= 200 && res.status < 300 + return res; + } else { + throw MyCustomError(res.statusText); + } +} + +fetch('https://httpbin.org/status/400') + .then(checkStatus) + .then(res => console.log('will not get here...')) +``` + +## Advanced Usage + +#### Streams +The "Node.js way" is to use streams when possible: + +```js +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') + .then(res => { + const dest = fs.createWriteStream('./octocat.png'); + res.body.pipe(dest); + }); +``` + +#### Buffer +If you prefer to cache binary data in full, use buffer(). (NOTE: `buffer()` is a `node-fetch`-only API) + +```js +const fileType = require('file-type'); + +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') + .then(res => res.buffer()) + .then(buffer => fileType(buffer)) + .then(type => { /* ... */ }); +``` + +#### Accessing Headers and other Meta data +```js +fetch('https://github.com/') + .then(res => { + console.log(res.ok); + console.log(res.status); + console.log(res.statusText); + console.log(res.headers.raw()); + console.log(res.headers.get('content-type')); + }); +``` + +#### Extract Set-Cookie Header + +Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API. + +```js +fetch(url).then(res => { + // returns an array of values, instead of a string of comma-separated values + console.log(res.headers.raw()['set-cookie']); +}); +``` + +#### Post data using a file stream + +```js +const { createReadStream } = require('fs'); + +const stream = createReadStream('input.txt'); + +fetch('https://httpbin.org/post', { method: 'POST', body: stream }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Post with form-data (detect multipart) + +```js +const FormData = require('form-data'); + +const form = new FormData(); +form.append('a', 1); + +fetch('https://httpbin.org/post', { method: 'POST', body: form }) + .then(res => res.json()) + .then(json => console.log(json)); + +// OR, using custom headers +// NOTE: getHeaders() is non-standard API + +const form = new FormData(); +form.append('a', 1); + +const options = { + method: 'POST', + body: form, + headers: form.getHeaders() +} + +fetch('https://httpbin.org/post', options) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Request cancellation with AbortSignal + +> NOTE: You may cancel streamed requests only on Node >= v8.0.0 + +You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller). + +An example of timing out a request after 150ms could be achieved as the following: + +```js +import AbortController from 'abort-controller'; + +const controller = new AbortController(); +const timeout = setTimeout( + () => { controller.abort(); }, + 150, +); + +fetch(url, { signal: controller.signal }) + .then(res => res.json()) + .then( + data => { + useData(data) + }, + err => { + if (err.name === 'AbortError') { + // request was aborted + } + }, + ) + .finally(() => { + clearTimeout(timeout); + }); +``` + +See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples. + + +## API + +### fetch(url[, options]) + +- `url` A string representing the URL for fetching +- `options` [Options](#fetch-options) for the HTTP(S) request +- Returns: Promise<[Response](#class-response)> + +Perform an HTTP(S) fetch. + +`url` should be an absolute url, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`. + + +### Options + +The default values are shown after each option key. + +```js +{ + // These properties are part of the Fetch Standard + method: 'GET', + headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below) + body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream + redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect + signal: null, // pass an instance of AbortSignal to optionally abort requests + + // The following properties are node-fetch extensions + follow: 20, // maximum redirect count. 0 to not follow redirect + timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead. + compress: true, // support gzip/deflate content encoding. false to disable + size: 0, // maximum response body size in bytes. 0 to disable + agent: null // http(s).Agent instance or function that returns an instance (see below) +} +``` + +##### Default Headers + +If no values are set, the following request headers will be sent automatically: + +Header | Value +------------------- | -------------------------------------------------------- +`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_ +`Accept` | `*/*` +`Connection` | `close` _(when no `options.agent` is present)_ +`Content-Length` | _(automatically calculated, if possible)_ +`Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ +`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)` + +Note: when `body` is a `Stream`, `Content-Length` is not set automatically. + +##### Custom Agent + +The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following: + +- Support self-signed certificate +- Use only IPv4 or IPv6 +- Custom DNS Lookup + +See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information. + +In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol. + +```js +const httpAgent = new http.Agent({ + keepAlive: true +}); +const httpsAgent = new https.Agent({ + keepAlive: true +}); + +const options = { + agent: function (_parsedURL) { + if (_parsedURL.protocol == 'http:') { + return httpAgent; + } else { + return httpsAgent; + } + } +} +``` + + +### Class: Request + +An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface. + +Due to the nature of Node.js, the following properties are not implemented at this moment: + +- `type` +- `destination` +- `referrer` +- `referrerPolicy` +- `mode` +- `credentials` +- `cache` +- `integrity` +- `keepalive` + +The following node-fetch extension properties are provided: + +- `follow` +- `compress` +- `counter` +- `agent` + +See [options](#fetch-options) for exact meaning of these extensions. + +#### new Request(input[, options]) + +*(spec-compliant)* + +- `input` A string representing a URL, or another `Request` (which will be cloned) +- `options` [Options][#fetch-options] for the HTTP(S) request + +Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request). + +In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object. + + +### Class: Response + +An HTTP(S) response. This class implements the [Body](#iface-body) interface. + +The following properties are not implemented in node-fetch at this moment: + +- `Response.error()` +- `Response.redirect()` +- `type` +- `trailer` + +#### new Response([body[, options]]) + +*(spec-compliant)* + +- `body` A `String` or [`Readable` stream][node-readable] +- `options` A [`ResponseInit`][response-init] options dictionary + +Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response). + +Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly. + +#### response.ok + +*(spec-compliant)* + +Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300. + +#### response.redirected + +*(spec-compliant)* + +Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0. + + +### Class: Headers + +This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented. + +#### new Headers([init]) + +*(spec-compliant)* + +- `init` Optional argument to pre-fill the `Headers` object + +Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object. + +```js +// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class + +const meta = { + 'Content-Type': 'text/xml', + 'Breaking-Bad': '<3' +}; +const headers = new Headers(meta); + +// The above is equivalent to +const meta = [ + [ 'Content-Type', 'text/xml' ], + [ 'Breaking-Bad', '<3' ] +]; +const headers = new Headers(meta); + +// You can in fact use any iterable objects, like a Map or even another Headers +const meta = new Map(); +meta.set('Content-Type', 'text/xml'); +meta.set('Breaking-Bad', '<3'); +const headers = new Headers(meta); +const copyOfHeaders = new Headers(headers); +``` + + +### Interface: Body + +`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes. + +The following methods are not yet implemented in node-fetch at this moment: + +- `formData()` + +#### body.body + +*(deviation from spec)* + +* Node.js [`Readable` stream][node-readable] + +Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable]. + +#### body.bodyUsed + +*(spec-compliant)* + +* `Boolean` + +A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again. + +#### body.arrayBuffer() +#### body.blob() +#### body.json() +#### body.text() + +*(spec-compliant)* + +* Returns: Promise + +Consume the body and return a promise that will resolve to one of these formats. + +#### body.buffer() + +*(node-fetch extension)* + +* Returns: Promise<Buffer> + +Consume the body and return a promise that will resolve to a Buffer. + +#### body.textConverted() + +*(node-fetch extension)* + +* Returns: Promise<String> + +Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8 if possible. + +(This API requires an optional dependency of the npm package [encoding](https://www.npmjs.com/package/encoding), which you need to install manually. `webpack` users may see [a warning message](https://github.com/bitinn/node-fetch/issues/412#issuecomment-379007792) due to this optional dependency.) + + +### Class: FetchError + +*(node-fetch extension)* + +An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info. + + +### Class: AbortError + +*(node-fetch extension)* + +An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info. + +## Acknowledgement + +Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference. + +`node-fetch` v1 was maintained by [@bitinn](https://github.com/bitinn); v2 was maintained by [@TimothyGu](https://github.com/timothygu), [@bitinn](https://github.com/bitinn) and [@jimmywarting](https://github.com/jimmywarting); v2 readme is written by [@jkantr](https://github.com/jkantr). + +## License + +MIT + +[npm-image]: https://flat.badgen.net/npm/v/node-fetch +[npm-url]: https://www.npmjs.com/package/node-fetch +[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch +[travis-url]: https://travis-ci.org/bitinn/node-fetch +[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master +[codecov-url]: https://codecov.io/gh/bitinn/node-fetch +[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch +[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch +[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square +[discord-url]: https://discord.gg/Zxbndcm +[opencollective-image]: https://opencollective.com/node-fetch/backers.svg +[opencollective-url]: https://opencollective.com/node-fetch +[whatwg-fetch]: https://fetch.spec.whatwg.org/ +[response-init]: https://fetch.spec.whatwg.org/#responseinit +[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams +[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers +[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md +[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md +[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md diff --git a/node_modules/node-fetch/browser.js b/node_modules/node-fetch/browser.js new file mode 100644 index 0000000..83c54c5 --- /dev/null +++ b/node_modules/node-fetch/browser.js @@ -0,0 +1,25 @@ +"use strict"; + +// ref: https://github.com/tc39/proposal-global +var getGlobal = function () { + // the only reliable means to get the global object is + // `Function('return this')()` + // However, this causes CSP violations in Chrome apps. + if (typeof self !== 'undefined') { return self; } + if (typeof window !== 'undefined') { return window; } + if (typeof global !== 'undefined') { return global; } + throw new Error('unable to locate global object'); +} + +var global = getGlobal(); + +module.exports = exports = global.fetch; + +// Needed for TypeScript and Webpack. +if (global.fetch) { + exports.default = global.fetch.bind(global); +} + +exports.Headers = global.Headers; +exports.Request = global.Request; +exports.Response = global.Response; \ No newline at end of file diff --git a/node_modules/node-fetch/lib/index.es.js b/node_modules/node-fetch/lib/index.es.js new file mode 100644 index 0000000..61906c9 --- /dev/null +++ b/node_modules/node-fetch/lib/index.es.js @@ -0,0 +1,1640 @@ +process.emitWarning("The .es.js file is deprecated. Use .mjs instead."); + +import Stream from 'stream'; +import http from 'http'; +import Url from 'url'; +import https from 'https'; +import zlib from 'zlib'; + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parse_url(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parse_url(`${input}`); + } + input = {}; + } else { + parsedURL = parse_url(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + if (!headers.has('Connection') && !agent) { + headers.set('Connection', 'close'); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; +const resolve_url = Url.resolve; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + request.body.destroy(error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + finalize(); + }); + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + const locationURL = location === null ? null : resolve_url(request.url, location); + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +export default fetch; +export { Headers, Request, Response, FetchError }; diff --git a/node_modules/node-fetch/lib/index.js b/node_modules/node-fetch/lib/index.js new file mode 100644 index 0000000..4b241bf --- /dev/null +++ b/node_modules/node-fetch/lib/index.js @@ -0,0 +1,1649 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(require('stream')); +var http = _interopDefault(require('http')); +var Url = _interopDefault(require('url')); +var https = _interopDefault(require('https')); +var zlib = _interopDefault(require('zlib')); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parse_url(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parse_url(`${input}`); + } + input = {}; + } else { + parsedURL = parse_url(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + if (!headers.has('Connection') && !agent) { + headers.set('Connection', 'close'); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; +const resolve_url = Url.resolve; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + request.body.destroy(error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + finalize(); + }); + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + const locationURL = location === null ? null : resolve_url(request.url, location); + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; diff --git a/node_modules/node-fetch/lib/index.mjs b/node_modules/node-fetch/lib/index.mjs new file mode 100644 index 0000000..ecf59af --- /dev/null +++ b/node_modules/node-fetch/lib/index.mjs @@ -0,0 +1,1638 @@ +import Stream from 'stream'; +import http from 'http'; +import Url from 'url'; +import https from 'https'; +import zlib from 'zlib'; + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parse_url(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parse_url(`${input}`); + } + input = {}; + } else { + parsedURL = parse_url(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + if (!headers.has('Connection') && !agent) { + headers.set('Connection', 'close'); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; +const resolve_url = Url.resolve; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + request.body.destroy(error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + finalize(); + }); + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + const locationURL = location === null ? null : resolve_url(request.url, location); + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +export default fetch; +export { Headers, Request, Response, FetchError }; diff --git a/node_modules/node-fetch/package.json b/node_modules/node-fetch/package.json new file mode 100644 index 0000000..2160469 --- /dev/null +++ b/node_modules/node-fetch/package.json @@ -0,0 +1,66 @@ +{ + "name": "node-fetch", + "version": "2.6.1", + "description": "A light-weight module that brings window.fetch to node.js", + "main": "lib/index", + "browser": "./browser.js", + "module": "lib/index.mjs", + "files": [ + "lib/index.js", + "lib/index.mjs", + "lib/index.es.js", + "browser.js" + ], + "engines": { + "node": "4.x || >=6.0.0" + }, + "scripts": { + "build": "cross-env BABEL_ENV=rollup rollup -c", + "prepare": "npm run build", + "test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js", + "report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js", + "coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/bitinn/node-fetch.git" + }, + "keywords": [ + "fetch", + "http", + "promise" + ], + "author": "David Frank", + "license": "MIT", + "bugs": { + "url": "https://github.com/bitinn/node-fetch/issues" + }, + "homepage": "https://github.com/bitinn/node-fetch", + "devDependencies": { + "@ungap/url-search-params": "^0.1.2", + "abort-controller": "^1.1.0", + "abortcontroller-polyfill": "^1.3.0", + "babel-core": "^6.26.3", + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-env": "^1.6.1", + "babel-register": "^6.16.3", + "chai": "^3.5.0", + "chai-as-promised": "^7.1.1", + "chai-iterator": "^1.1.1", + "chai-string": "~1.3.0", + "codecov": "^3.3.0", + "cross-env": "^5.2.0", + "form-data": "^2.3.3", + "is-builtin-module": "^1.0.0", + "mocha": "^5.0.0", + "nyc": "11.9.0", + "parted": "^0.1.1", + "promise": "^8.0.3", + "resumer": "0.0.0", + "rollup": "^0.63.4", + "rollup-plugin-babel": "^3.0.7", + "string-to-arraybuffer": "^1.0.2", + "whatwg-url": "^5.0.0" + }, + "dependencies": {} +} diff --git a/node_modules/normalize-url/index.d.ts b/node_modules/normalize-url/index.d.ts new file mode 100644 index 0000000..7e332f2 --- /dev/null +++ b/node_modules/normalize-url/index.d.ts @@ -0,0 +1,216 @@ +declare namespace normalizeUrl { + interface Options { + /** + @default 'http:' + */ + readonly defaultProtocol?: string; + + /** + Prepends `defaultProtocol` to the URL if it's protocol-relative. + + @default true + + @example + ``` + normalizeUrl('//sindresorhus.com:80/'); + //=> 'http://sindresorhus.com' + + normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false}); + //=> '//sindresorhus.com' + ``` + */ + readonly normalizeProtocol?: boolean; + + /** + Normalizes `https:` URLs to `http:`. + + @default false + + @example + ``` + normalizeUrl('https://sindresorhus.com:80/'); + //=> 'https://sindresorhus.com' + + normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true}); + //=> 'http://sindresorhus.com' + ``` + */ + readonly forceHttp?: boolean; + + /** + Normalizes `http:` URLs to `https:`. + + This option can't be used with the `forceHttp` option at the same time. + + @default false + + @example + ``` + normalizeUrl('https://sindresorhus.com:80/'); + //=> 'https://sindresorhus.com' + + normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true}); + //=> 'https://sindresorhus.com' + ``` + */ + readonly forceHttps?: boolean; + + /** + Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of a URL. + + @default true + + @example + ``` + normalizeUrl('user:password@sindresorhus.com'); + //=> 'https://sindresorhus.com' + + normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false}); + //=> 'https://user:password@sindresorhus.com' + ``` + */ + readonly stripAuthentication?: boolean; + + /** + Removes hash from the URL. + + @default false + + @example + ``` + normalizeUrl('sindresorhus.com/about.html#contact'); + //=> 'http://sindresorhus.com/about.html#contact' + + normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true}); + //=> 'http://sindresorhus.com/about.html' + ``` + */ + readonly stripHash?: boolean; + + /** + Removes HTTP(S) protocol from an URL `http://sindresorhus.com` → `sindresorhus.com`. + + @default false + + @example + ``` + normalizeUrl('https://sindresorhus.com'); + //=> 'https://sindresorhus.com' + + normalizeUrl('sindresorhus.com', {stripProtocol: true}); + //=> 'sindresorhus.com' + ``` + */ + readonly stripProtocol?: boolean; + + /** + Removes `www.` from the URL. + + @default true + + @example + ``` + normalizeUrl('http://www.sindresorhus.com'); + //=> 'http://sindresorhus.com' + + normalizeUrl('http://www.sindresorhus.com', {stripWWW: false}); + //=> 'http://www.sindresorhus.com' + ``` + */ + readonly stripWWW?: boolean; + + /** + Removes query parameters that matches any of the provided strings or regexes. + + @default [/^utm_\w+/i] + + @example + ``` + normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', { + removeQueryParameters: ['ref'] + }); + //=> 'http://sindresorhus.com/?foo=bar' + ``` + */ + readonly removeQueryParameters?: ReadonlyArray; + + /** + Removes trailing slash. + + __Note__: Trailing slash is always removed if the URL doesn't have a pathname. + + @default true + + @example + ``` + normalizeUrl('http://sindresorhus.com/redirect/'); + //=> 'http://sindresorhus.com/redirect' + + normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false}); + //=> 'http://sindresorhus.com/redirect/' + + normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false}); + //=> 'http://sindresorhus.com' + ``` + */ + readonly removeTrailingSlash?: boolean; + + /** + Removes the default directory index file from path that matches any of the provided strings or regexes. + When `true`, the regex `/^index\.[a-z]+$/` is used. + + @default false + + @example + ``` + normalizeUrl('www.sindresorhus.com/foo/default.php', { + removeDirectoryIndex: [/^default\.[a-z]+$/] + }); + //=> 'http://sindresorhus.com/foo' + ``` + */ + readonly removeDirectoryIndex?: ReadonlyArray; + + /** + Sorts the query parameters alphabetically by key. + + @default true + + @example + ``` + normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', { + sortQueryParameters: false + }); + //=> 'http://sindresorhus.com/?b=two&a=one&c=three' + ``` + */ + readonly sortQueryParameters?: boolean; + } +} + +declare const normalizeUrl: { + /** + [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL. + + @param url - URL to normalize, including [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs). + + @example + ``` + import normalizeUrl = require('normalize-url'); + + normalizeUrl('sindresorhus.com'); + //=> 'http://sindresorhus.com' + + normalizeUrl('HTTP://xn--xample-hva.com:80/?b=bar&a=foo'); + //=> 'http://êxample.com/?a=foo&b=bar' + ``` + */ + (url: string, options?: normalizeUrl.Options): string; + + // TODO: Remove this for the next major release, refactor the whole definition to: + // declare function normalizeUrl(url: string, options?: normalizeUrl.Options): string; + // export = normalizeUrl; + default: typeof normalizeUrl; +}; + +export = normalizeUrl; diff --git a/node_modules/normalize-url/index.js b/node_modules/normalize-url/index.js new file mode 100644 index 0000000..4eea255 --- /dev/null +++ b/node_modules/normalize-url/index.js @@ -0,0 +1,221 @@ +'use strict'; +// TODO: Use the `URL` global when targeting Node.js 10 +const URLParser = typeof URL === 'undefined' ? require('url').URL : URL; + +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs +const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain'; +const DATA_URL_DEFAULT_CHARSET = 'us-ascii'; + +const testParameter = (name, filters) => { + return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name); +}; + +const normalizeDataURL = (urlString, {stripHash}) => { + const parts = urlString.match(/^data:(.*?),(.*?)(?:#(.*))?$/); + + if (!parts) { + throw new Error(`Invalid URL: ${urlString}`); + } + + const mediaType = parts[1].split(';'); + const body = parts[2]; + const hash = stripHash ? '' : parts[3]; + + let base64 = false; + + if (mediaType[mediaType.length - 1] === 'base64') { + mediaType.pop(); + base64 = true; + } + + // Lowercase MIME type + const mimeType = (mediaType.shift() || '').toLowerCase(); + const attributes = mediaType + .map(attribute => { + let [key, value = ''] = attribute.split('=').map(string => string.trim()); + + // Lowercase `charset` + if (key === 'charset') { + value = value.toLowerCase(); + + if (value === DATA_URL_DEFAULT_CHARSET) { + return ''; + } + } + + return `${key}${value ? `=${value}` : ''}`; + }) + .filter(Boolean); + + const normalizedMediaType = [ + ...attributes + ]; + + if (base64) { + normalizedMediaType.push('base64'); + } + + if (normalizedMediaType.length !== 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) { + normalizedMediaType.unshift(mimeType); + } + + return `data:${normalizedMediaType.join(';')},${base64 ? body.trim() : body}${hash ? `#${hash}` : ''}`; +}; + +const normalizeUrl = (urlString, options) => { + options = { + defaultProtocol: 'http:', + normalizeProtocol: true, + forceHttp: false, + forceHttps: false, + stripAuthentication: true, + stripHash: false, + stripWWW: true, + removeQueryParameters: [/^utm_\w+/i], + removeTrailingSlash: true, + removeDirectoryIndex: false, + sortQueryParameters: true, + ...options + }; + + // TODO: Remove this at some point in the future + if (Reflect.has(options, 'normalizeHttps')) { + throw new Error('options.normalizeHttps is renamed to options.forceHttp'); + } + + if (Reflect.has(options, 'normalizeHttp')) { + throw new Error('options.normalizeHttp is renamed to options.forceHttps'); + } + + if (Reflect.has(options, 'stripFragment')) { + throw new Error('options.stripFragment is renamed to options.stripHash'); + } + + urlString = urlString.trim(); + + // Data URL + if (/^data:/i.test(urlString)) { + return normalizeDataURL(urlString, options); + } + + const hasRelativeProtocol = urlString.startsWith('//'); + const isRelativeUrl = !hasRelativeProtocol && /^\.*\//.test(urlString); + + // Prepend protocol + if (!isRelativeUrl) { + urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol); + } + + const urlObj = new URLParser(urlString); + + if (options.forceHttp && options.forceHttps) { + throw new Error('The `forceHttp` and `forceHttps` options cannot be used together'); + } + + if (options.forceHttp && urlObj.protocol === 'https:') { + urlObj.protocol = 'http:'; + } + + if (options.forceHttps && urlObj.protocol === 'http:') { + urlObj.protocol = 'https:'; + } + + // Remove auth + if (options.stripAuthentication) { + urlObj.username = ''; + urlObj.password = ''; + } + + // Remove hash + if (options.stripHash) { + urlObj.hash = ''; + } + + // Remove duplicate slashes if not preceded by a protocol + if (urlObj.pathname) { + // TODO: Use the following instead when targeting Node.js 10 + // `urlObj.pathname = urlObj.pathname.replace(/(? { + if (/^(?!\/)/g.test(p1)) { + return `${p1}/`; + } + + return '/'; + }); + } + + // Decode URI octets + if (urlObj.pathname) { + urlObj.pathname = decodeURI(urlObj.pathname); + } + + // Remove directory index + if (options.removeDirectoryIndex === true) { + options.removeDirectoryIndex = [/^index\.[a-z]+$/]; + } + + if (Array.isArray(options.removeDirectoryIndex) && options.removeDirectoryIndex.length > 0) { + let pathComponents = urlObj.pathname.split('/'); + const lastComponent = pathComponents[pathComponents.length - 1]; + + if (testParameter(lastComponent, options.removeDirectoryIndex)) { + pathComponents = pathComponents.slice(0, pathComponents.length - 1); + urlObj.pathname = pathComponents.slice(1).join('/') + '/'; + } + } + + if (urlObj.hostname) { + // Remove trailing dot + urlObj.hostname = urlObj.hostname.replace(/\.$/, ''); + + // Remove `www.` + if (options.stripWWW && /^www\.([a-z\-\d]{2,63})\.([a-z.]{2,5})$/.test(urlObj.hostname)) { + // Each label should be max 63 at length (min: 2). + // The extension should be max 5 at length (min: 2). + // Source: https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names + urlObj.hostname = urlObj.hostname.replace(/^www\./, ''); + } + } + + // Remove query unwanted parameters + if (Array.isArray(options.removeQueryParameters)) { + for (const key of [...urlObj.searchParams.keys()]) { + if (testParameter(key, options.removeQueryParameters)) { + urlObj.searchParams.delete(key); + } + } + } + + // Sort query parameters + if (options.sortQueryParameters) { + urlObj.searchParams.sort(); + } + + if (options.removeTrailingSlash) { + urlObj.pathname = urlObj.pathname.replace(/\/$/, ''); + } + + // Take advantage of many of the Node `url` normalizations + urlString = urlObj.toString(); + + // Remove ending `/` + if ((options.removeTrailingSlash || urlObj.pathname === '/') && urlObj.hash === '') { + urlString = urlString.replace(/\/$/, ''); + } + + // Restore relative protocol, if applicable + if (hasRelativeProtocol && !options.normalizeProtocol) { + urlString = urlString.replace(/^http:\/\//, '//'); + } + + // Remove http/https + if (options.stripProtocol) { + urlString = urlString.replace(/^(?:https?:)?\/\//, ''); + } + + return urlString; +}; + +module.exports = normalizeUrl; +// TODO: Remove this for the next major release +module.exports.default = normalizeUrl; diff --git a/node_modules/normalize-url/license b/node_modules/normalize-url/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/normalize-url/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/normalize-url/package.json b/node_modules/normalize-url/package.json new file mode 100644 index 0000000..062ad53 --- /dev/null +++ b/node_modules/normalize-url/package.json @@ -0,0 +1,44 @@ +{ + "name": "normalize-url", + "version": "4.5.0", + "description": "Normalize a URL", + "license": "MIT", + "repository": "sindresorhus/normalize-url", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && nyc ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "normalize", + "url", + "uri", + "address", + "string", + "normalization", + "normalisation", + "query", + "querystring", + "simplify", + "strip", + "trim", + "canonical" + ], + "devDependencies": { + "ava": "^2.4.0", + "coveralls": "^3.0.6", + "nyc": "^14.1.1", + "tsd": "^0.8.0", + "xo": "^0.24.0" + } +} diff --git a/node_modules/normalize-url/readme.md b/node_modules/normalize-url/readme.md new file mode 100644 index 0000000..a851fdd --- /dev/null +++ b/node_modules/normalize-url/readme.md @@ -0,0 +1,232 @@ +# normalize-url [![Build Status](https://travis-ci.org/sindresorhus/normalize-url.svg?branch=master)](https://travis-ci.org/sindresorhus/normalize-url) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/normalize-url/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/normalize-url?branch=master) + +> [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL + +Useful when you need to display, store, deduplicate, sort, compare, etc, URLs. + + +## Install + +``` +$ npm install normalize-url +``` + + +## Usage + +```js +const normalizeUrl = require('normalize-url'); + +normalizeUrl('sindresorhus.com'); +//=> 'http://sindresorhus.com' + +normalizeUrl('HTTP://xn--xample-hva.com:80/?b=bar&a=foo'); +//=> 'http://êxample.com/?a=foo&b=bar' +``` + + +## API + +### normalizeUrl(url, options?) + +#### url + +Type: `string` + +URL to normalize, including [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs). + +#### options + +Type: `object` + +##### defaultProtocol + +Type: `string`
+Default: `http:` + +##### normalizeProtocol + +Type: `boolean`
+Default: `true` + +Prepend `defaultProtocol` to the URL if it's protocol-relative. + +```js +normalizeUrl('//sindresorhus.com:80/'); +//=> 'http://sindresorhus.com' + +normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false}); +//=> '//sindresorhus.com' +``` + +##### forceHttp + +Type: `boolean`
+Default: `false` + +Normalize `https:` to `http:`. + +```js +normalizeUrl('https://sindresorhus.com:80/'); +//=> 'https://sindresorhus.com' + +normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true}); +//=> 'http://sindresorhus.com' +``` + +##### forceHttps + +Type: `boolean`
+Default: `false` + +Normalize `http:` to `https:`. + +```js +normalizeUrl('https://sindresorhus.com:80/'); +//=> 'https://sindresorhus.com' + +normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true}); +//=> 'https://sindresorhus.com' +``` + +This option can't be used with the `forceHttp` option at the same time. + +##### stripAuthentication + +Type: `boolean`
+Default: `true` + +Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of the URL. + +```js +normalizeUrl('user:password@sindresorhus.com'); +//=> 'https://sindresorhus.com' + +normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false}); +//=> 'https://user:password@sindresorhus.com' +``` + +##### stripHash + +Type: `boolean`
+Default: `false` + +Strip the hash part of the URL. + +```js +normalizeUrl('sindresorhus.com/about.html#contact'); +//=> 'http://sindresorhus.com/about.html#contact' + +normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true}); +//=> 'http://sindresorhus.com/about.html' +``` + +##### stripProtocol + +Type: `boolean`
+Default: `false` + +Remove HTTP(S) protocol from the URL: `http://sindresorhus.com` → `sindresorhus.com`. + +```js +normalizeUrl('https://sindresorhus.com'); +//=> 'https://sindresorhus.com' + +normalizeUrl('sindresorhus.com', {stripProtocol: true}); +//=> 'sindresorhus.com' +``` + +##### stripWWW + +Type: `boolean`
+Default: `true` + +Remove `www.` from the URL. + +```js +normalizeUrl('http://www.sindresorhus.com'); +//=> 'http://sindresorhus.com' + +normalizeUrl('http://www.sindresorhus.com', {stripWWW: false}); +//=> 'http://www.sindresorhus.com' +``` + +##### removeQueryParameters + +Type: `Array`
+Default: `[/^utm_\w+/i]` + +Remove query parameters that matches any of the provided strings or regexes. + +```js +normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', { + removeQueryParameters: ['ref'] +}); +//=> 'http://sindresorhus.com/?foo=bar' +``` + +##### removeTrailingSlash + +Type: `boolean`
+Default: `true` + +Remove trailing slash. + +**Note:** Trailing slash is always removed if the URL doesn't have a pathname. + +```js +normalizeUrl('http://sindresorhus.com/redirect/'); +//=> 'http://sindresorhus.com/redirect' + +normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false}); +//=> 'http://sindresorhus.com/redirect/' + +normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false}); +//=> 'http://sindresorhus.com' +``` + +##### removeDirectoryIndex + +Type: `boolean | Array`
+Default: `false` + +Removes the default directory index file from path that matches any of the provided strings or regexes. When `true`, the regex `/^index\.[a-z]+$/` is used. + +```js +normalizeUrl('www.sindresorhus.com/foo/default.php', { + removeDirectoryIndex: [/^default\.[a-z]+$/] +}); +//=> 'http://sindresorhus.com/foo' +``` + +##### sortQueryParameters + +Type: `boolean`
+Default: `true` + +Sorts the query parameters alphabetically by key. + +```js +normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', { + sortQueryParameters: false +}); +//=> 'http://sindresorhus.com/?b=two&a=one&c=three' +``` + + +## Related + +- [compare-urls](https://github.com/sindresorhus/compare-urls) - Compare URLs by first normalizing them + + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/once/LICENSE b/node_modules/once/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/node_modules/once/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/once/README.md b/node_modules/once/README.md new file mode 100644 index 0000000..1f1ffca --- /dev/null +++ b/node_modules/once/README.md @@ -0,0 +1,79 @@ +# once + +Only call a function once. + +## usage + +```javascript +var once = require('once') + +function load (file, cb) { + cb = once(cb) + loader.load('file') + loader.once('load', cb) + loader.once('error', cb) +} +``` + +Or add to the Function.prototype in a responsible way: + +```javascript +// only has to be done once +require('once').proto() + +function load (file, cb) { + cb = cb.once() + loader.load('file') + loader.once('load', cb) + loader.once('error', cb) +} +``` + +Ironically, the prototype feature makes this module twice as +complicated as necessary. + +To check whether you function has been called, use `fn.called`. Once the +function is called for the first time the return value of the original +function is saved in `fn.value` and subsequent calls will continue to +return this value. + +```javascript +var once = require('once') + +function load (cb) { + cb = once(cb) + var stream = createStream() + stream.once('data', cb) + stream.once('end', function () { + if (!cb.called) cb(new Error('not found')) + }) +} +``` + +## `once.strict(func)` + +Throw an error if the function is called twice. + +Some functions are expected to be called only once. Using `once` for them would +potentially hide logical errors. + +In the example below, the `greet` function has to call the callback only once: + +```javascript +function greet (name, cb) { + // return is missing from the if statement + // when no name is passed, the callback is called twice + if (!name) cb('Hello anonymous') + cb('Hello ' + name) +} + +function log (msg) { + console.log(msg) +} + +// this will print 'Hello anonymous' but the logical error will be missed +greet(null, once(msg)) + +// once.strict will print 'Hello anonymous' and throw an error when the callback will be called the second time +greet(null, once.strict(msg)) +``` diff --git a/node_modules/once/once.js b/node_modules/once/once.js new file mode 100644 index 0000000..2354067 --- /dev/null +++ b/node_modules/once/once.js @@ -0,0 +1,42 @@ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} diff --git a/node_modules/once/package.json b/node_modules/once/package.json new file mode 100644 index 0000000..16815b2 --- /dev/null +++ b/node_modules/once/package.json @@ -0,0 +1,33 @@ +{ + "name": "once", + "version": "1.4.0", + "description": "Run a function exactly one time", + "main": "once.js", + "directories": { + "test": "test" + }, + "dependencies": { + "wrappy": "1" + }, + "devDependencies": { + "tap": "^7.0.1" + }, + "scripts": { + "test": "tap test/*.js" + }, + "files": [ + "once.js" + ], + "repository": { + "type": "git", + "url": "git://github.com/isaacs/once" + }, + "keywords": [ + "once", + "function", + "one", + "single" + ], + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC" +} diff --git a/node_modules/p-cancelable/index.d.ts b/node_modules/p-cancelable/index.d.ts new file mode 100644 index 0000000..7c70057 --- /dev/null +++ b/node_modules/p-cancelable/index.d.ts @@ -0,0 +1,176 @@ +declare class CancelErrorClass extends Error { + readonly name: 'CancelError'; + readonly isCanceled: true; + + constructor(reason?: string); +} + +declare namespace PCancelable { + /** + Accepts a function that is called when the promise is canceled. + + You're not required to call this function. You can call this function multiple times to add multiple cancel handlers. + */ + interface OnCancelFunction { + (cancelHandler: () => void): void; + shouldReject: boolean; + } + + type CancelError = CancelErrorClass; +} + +declare class PCancelable extends Promise { + /** + Convenience method to make your promise-returning or async function cancelable. + + @param fn - A promise-returning function. The function you specify will have `onCancel` appended to its parameters. + + @example + ``` + import PCancelable = require('p-cancelable'); + + const fn = PCancelable.fn((input, onCancel) => { + const job = new Job(); + + onCancel(() => { + job.cleanup(); + }); + + return job.start(); //=> Promise + }); + + const cancelablePromise = fn('input'); //=> PCancelable + + // … + + cancelablePromise.cancel(); + ``` + */ + static fn( + userFn: (onCancel: PCancelable.OnCancelFunction) => PromiseLike + ): () => PCancelable; + static fn( + userFn: ( + argument1: Agument1Type, + onCancel: PCancelable.OnCancelFunction + ) => PromiseLike + ): (argument1: Agument1Type) => PCancelable; + static fn( + userFn: ( + argument1: Agument1Type, + argument2: Agument2Type, + onCancel: PCancelable.OnCancelFunction + ) => PromiseLike + ): ( + argument1: Agument1Type, + argument2: Agument2Type + ) => PCancelable; + static fn( + userFn: ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type, + onCancel: PCancelable.OnCancelFunction + ) => PromiseLike + ): ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type + ) => PCancelable; + static fn( + userFn: ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type, + argument4: Agument4Type, + onCancel: PCancelable.OnCancelFunction + ) => PromiseLike + ): ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type, + argument4: Agument4Type + ) => PCancelable; + static fn< + Agument1Type, + Agument2Type, + Agument3Type, + Agument4Type, + Agument5Type, + ReturnType + >( + userFn: ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type, + argument4: Agument4Type, + argument5: Agument5Type, + onCancel: PCancelable.OnCancelFunction + ) => PromiseLike + ): ( + argument1: Agument1Type, + argument2: Agument2Type, + argument3: Agument3Type, + argument4: Agument4Type, + argument5: Agument5Type + ) => PCancelable; + static fn( + userFn: (...arguments: unknown[]) => PromiseLike + ): (...arguments: unknown[]) => PCancelable; + + /** + Create a promise that can be canceled. + + Can be constructed in the same was as a [`Promise` constructor](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise), but with an appended `onCancel` parameter in `executor`. `PCancelable` is a subclass of `Promise`. + + Cancelling will reject the promise with `CancelError`. To avoid that, set `onCancel.shouldReject` to `false`. + + @example + ``` + import PCancelable = require('p-cancelable'); + + const cancelablePromise = new PCancelable((resolve, reject, onCancel) => { + const job = new Job(); + + onCancel.shouldReject = false; + onCancel(() => { + job.stop(); + }); + + job.on('finish', resolve); + }); + + cancelablePromise.cancel(); // Doesn't throw an error + ``` + */ + constructor( + executor: ( + resolve: (value?: ValueType | PromiseLike) => void, + reject: (reason?: unknown) => void, + onCancel: PCancelable.OnCancelFunction + ) => void + ); + + /** + Whether the promise is canceled. + */ + readonly isCanceled: boolean; + + /** + Cancel the promise and optionally provide a reason. + + The cancellation is synchronous. Calling it after the promise has settled or multiple times does nothing. + + @param reason - The cancellation reason to reject the promise with. + */ + cancel(reason?: string): void; + + /** + Rejection reason when `.cancel()` is called. + + It includes a `.isCanceled` property for convenience. + */ + static CancelError: typeof CancelErrorClass; +} + +export = PCancelable; diff --git a/node_modules/p-cancelable/index.js b/node_modules/p-cancelable/index.js new file mode 100644 index 0000000..186adce --- /dev/null +++ b/node_modules/p-cancelable/index.js @@ -0,0 +1,111 @@ +'use strict'; + +class CancelError extends Error { + constructor(reason) { + super(reason || 'Promise was canceled'); + this.name = 'CancelError'; + } + + get isCanceled() { + return true; + } +} + +class PCancelable { + static fn(userFn) { + return (...arguments_) => { + return new PCancelable((resolve, reject, onCancel) => { + arguments_.push(onCancel); + // eslint-disable-next-line promise/prefer-await-to-then + userFn(...arguments_).then(resolve, reject); + }); + }; + } + + constructor(executor) { + this._cancelHandlers = []; + this._isPending = true; + this._isCanceled = false; + this._rejectOnCancel = true; + + this._promise = new Promise((resolve, reject) => { + this._reject = reject; + + const onResolve = value => { + if (!this._isCanceled || !onCancel.shouldReject) { + this._isPending = false; + resolve(value); + } + }; + + const onReject = error => { + this._isPending = false; + reject(error); + }; + + const onCancel = handler => { + if (!this._isPending) { + throw new Error('The `onCancel` handler was attached after the promise settled.'); + } + + this._cancelHandlers.push(handler); + }; + + Object.defineProperties(onCancel, { + shouldReject: { + get: () => this._rejectOnCancel, + set: boolean => { + this._rejectOnCancel = boolean; + } + } + }); + + return executor(onResolve, onReject, onCancel); + }); + } + + then(onFulfilled, onRejected) { + // eslint-disable-next-line promise/prefer-await-to-then + return this._promise.then(onFulfilled, onRejected); + } + + catch(onRejected) { + return this._promise.catch(onRejected); + } + + finally(onFinally) { + return this._promise.finally(onFinally); + } + + cancel(reason) { + if (!this._isPending || this._isCanceled) { + return; + } + + this._isCanceled = true; + + if (this._cancelHandlers.length > 0) { + try { + for (const handler of this._cancelHandlers) { + handler(); + } + } catch (error) { + this._reject(error); + return; + } + } + + if (this._rejectOnCancel) { + this._reject(new CancelError(reason)); + } + } + + get isCanceled() { + return this._isCanceled; + } +} + +Object.setPrototypeOf(PCancelable.prototype, Promise.prototype); + +module.exports = PCancelable; +module.exports.CancelError = CancelError; diff --git a/node_modules/p-cancelable/license b/node_modules/p-cancelable/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/p-cancelable/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/p-cancelable/package.json b/node_modules/p-cancelable/package.json new file mode 100644 index 0000000..af75d39 --- /dev/null +++ b/node_modules/p-cancelable/package.json @@ -0,0 +1,49 @@ +{ + "name": "p-cancelable", + "version": "2.1.0", + "description": "Create a promise that can be canceled", + "license": "MIT", + "repository": "sindresorhus/p-cancelable", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "promise", + "cancelable", + "cancel", + "canceled", + "canceling", + "cancellable", + "cancellation", + "abort", + "abortable", + "aborting", + "cleanup", + "task", + "token", + "async", + "function", + "await", + "promises", + "bluebird" + ], + "devDependencies": { + "ava": "^1.4.1", + "delay": "^4.1.0", + "promise.prototype.finally": "^3.1.0", + "tsd": "^0.7.1", + "xo": "^0.24.0" + } +} diff --git a/node_modules/p-cancelable/readme.md b/node_modules/p-cancelable/readme.md new file mode 100644 index 0000000..0690cfa --- /dev/null +++ b/node_modules/p-cancelable/readme.md @@ -0,0 +1,153 @@ +# p-cancelable + +> Create a promise that can be canceled + +Useful for animation, loading resources, long-running async computations, async iteration, etc. + +*If you target [Node.js 15](https://medium.com/@nodejs/node-js-v15-0-0-is-here-deb00750f278) or later, this package is [less useful](https://github.com/sindresorhus/p-cancelable/issues/27) and you should probably use [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) instead.* + +## Install + +``` +$ npm install p-cancelable +``` + +## Usage + +```js +const PCancelable = require('p-cancelable'); + +const cancelablePromise = new PCancelable((resolve, reject, onCancel) => { + const worker = new SomeLongRunningOperation(); + + onCancel(() => { + worker.close(); + }); + + worker.on('finish', resolve); + worker.on('error', reject); +}); + +(async () => { + try { + console.log('Operation finished successfully:', await cancelablePromise); + } catch (error) { + if (cancelablePromise.isCanceled) { + // Handle the cancelation here + console.log('Operation was canceled'); + return; + } + + throw error; + } +})(); + +// Cancel the operation after 10 seconds +setTimeout(() => { + cancelablePromise.cancel('Unicorn has changed its color'); +}, 10000); +``` + +## API + +### new PCancelable(executor) + +Same as the [`Promise` constructor](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise), but with an appended `onCancel` parameter in `executor`.
+Cancelling will reject the promise with `PCancelable.CancelError`. To avoid that, set `onCancel.shouldReject` to `false`. + +```js +const PCancelable = require('p-cancelable'); + +const cancelablePromise = new PCancelable((resolve, reject, onCancel) => { + const job = new Job(); + + onCancel.shouldReject = false; + onCancel(() => { + job.stop(); + }); + + job.on('finish', resolve); +}); + +cancelablePromise.cancel(); // Doesn't throw an error +``` + +`PCancelable` is a subclass of `Promise`. + +#### onCanceled(fn) + +Type: `Function` + +Accepts a function that is called when the promise is canceled. + +You're not required to call this function. You can call this function multiple times to add multiple cancel handlers. + +### PCancelable#cancel(reason?) + +Type: `Function` + +Cancel the promise and optionally provide a reason. + +The cancellation is synchronous. Calling it after the promise has settled or multiple times does nothing. + +### PCancelable#isCanceled + +Type: `boolean` + +Whether the promise is canceled. + +### PCancelable.CancelError + +Type: `Error` + +Rejection reason when `.cancel()` is called. + +It includes a `.isCanceled` property for convenience. + +### PCancelable.fn(fn) + +Convenience method to make your promise-returning or async function cancelable. + +The function you specify will have `onCancel` appended to its parameters. + +```js +const PCancelable = require('p-cancelable'); + +const fn = PCancelable.fn((input, onCancel) => { + const job = new Job(); + + onCancel(() => { + job.cleanup(); + }); + + return job.start(); //=> Promise +}); + +const cancelablePromise = fn('input'); //=> PCancelable + +// … + +cancelablePromise.cancel(); +``` + +## FAQ + +### Cancelable vs. Cancellable + +[In American English, the verb cancel is usually inflected canceled and canceling—with one l.](http://grammarist.com/spelling/cancel/)
Both a [browser API](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable) and the [Cancelable Promises proposal](https://github.com/tc39/proposal-cancelable-promises) use this spelling. + +### What about the official [Cancelable Promises proposal](https://github.com/tc39/proposal-cancelable-promises)? + +~~It's still an early draft and I don't really like its current direction. It complicates everything and will require deep changes in the ecosystem to adapt to it. And the way you have to use cancel tokens is verbose and convoluted. I much prefer the more pragmatic and less invasive approach in this module.~~ The proposal was withdrawn. + +## p-cancelable for enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of p-cancelable and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-p-cancelable?utm_source=npm-p-cancelable&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +## Related + +- [p-progress](https://github.com/sindresorhus/p-progress) - Create a promise that reports progress +- [p-lazy](https://github.com/sindresorhus/p-lazy) - Create a lazy promise that defers execution until `.then()` or `.catch()` is called +- [More…](https://github.com/sindresorhus/promise-fun) diff --git a/node_modules/prism-media/LICENSE b/node_modules/prism-media/LICENSE new file mode 100644 index 0000000..369db8d --- /dev/null +++ b/node_modules/prism-media/LICENSE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019 - 2020 Amish Shah + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/prism-media/README.md b/node_modules/prism-media/README.md new file mode 100644 index 0000000..2be5e26 --- /dev/null +++ b/node_modules/prism-media/README.md @@ -0,0 +1,69 @@ +[![Logo](https://hydrabolt.me/assets/prism-media-logo.svg)](https://hydrabolt.me/prism-media/) + +
+ +[![Build Status](https://travis-ci.org/amishshah/prism-media.svg?branch=master)](https://travis-ci.org/hydrabolt/prism-media) +[![dependencies](https://david-dm.org/amishshah/prism-media/status.svg)](https://david-dm.org/hydrabolt/prism-media) +[![npm](https://img.shields.io/npm/dt/prism-media.svg)](https://www.npmjs.com/package/prism-media) +[![Patreon](https://img.shields.io/badge/donate-patreon-F96854.svg)](https://www.patreon.com/discordjs) + +
+ +## What is it? + +An easy-to-use stream-based toolkit that you can use for media processing. All the features provided have predictable +abstractions and join together coherently. + +```js +// This example will demux and decode an Opus-containing OGG file, and then write it to a file. +const prism = require('prism-media'); +const fs = require('fs'); + +fs.createReadStream('./audio.ogg') + .pipe(new prism.opus.OggDemuxer()) + .pipe(new prism.opus.Decoder({ rate: 48000, channels: 2, frameSize: 960 })) + .pipe(fs.createWriteStream('./audio.pcm')); +``` + +The example above can work with either a native or pure JavaScript Opus decoder - you don't need to worry about changing +your code for whichever you install. + +- FFmpeg support (either through npm modules or a normal installation) +- Opus support (native or pure JavaScript) +- Demuxing for WebM/OGG files (no modules required!) +- Volume Altering (no modules required!) + +## Dependencies + +The following dependencies are all optional, and you should only install one from each category (the first listed in +each category is preferred) + +- Opus + - [`@discordjs/opus`](https://github.com/discordjs/opus) + - [`node-opus`](https://github.com/Rantanen/node-opus) + - [`opusscript`](https://github.com/abalabahaha/opusscript) +- FFmpeg + - [`ffmpeg-static`](http://npmjs.com/ffmpeg-static) + - `ffmpeg` from a [normal installation](https://www.ffmpeg.org/download.html) + +## Useful Links + +- [Documentation](https://hydrabolt.me/prism-media) +- [Examples](https://github.com/amishshah/prism-media/tree/master/examples) +- [Patreon](https://www.patreon.com/discordjs) + +## License + +> Copyright 2019 - 2020 Amish Shah +> +> Licensed under the Apache License, Version 2.0 (the "License"); +> you may not use this file except in compliance with the License. +> You may obtain a copy of the License at +> +> http://www.apache.org/licenses/LICENSE-2.0 +> +> Unless required by applicable law or agreed to in writing, software +> distributed under the License is distributed on an "AS IS" BASIS, +> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +> See the License for the specific language governing permissions and +> limitations under the License. \ No newline at end of file diff --git a/node_modules/prism-media/package.json b/node_modules/prism-media/package.json new file mode 100644 index 0000000..7f96b34 --- /dev/null +++ b/node_modules/prism-media/package.json @@ -0,0 +1,63 @@ +{ + "name": "prism-media", + "version": "1.2.9", + "description": "Easy-to-use stream-based media transcoding", + "main": "src/index.js", + "types": "typings/index.d.ts", + "scripts": { + "lint": "eslint src", + "test": "npm run lint && jest && npm run docs", + "docs": "docma" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hydrabolt/prism-media.git" + }, + "keywords": [ + "audio", + "media", + "ffmpeg", + "opus", + "pcm", + "webm", + "ogg" + ], + "author": "Amish Shah ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/hydrabolt/prism-media/issues" + }, + "homepage": "https://github.com/hydrabolt/prism-media#readme", + "devDependencies": { + "docma": "^3.2.2", + "eslint": "^7.14.0", + "jest": "^26.6.3" + }, + "jest": { + "testURL": "http://localhost/" + }, + "peerDependencies": { + "@discordjs/opus": "^0.5.0", + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + } + }, + "files": [ + "src/", + "typings/" + ] +} diff --git a/node_modules/prism-media/src/core/FFmpeg.js b/node_modules/prism-media/src/core/FFmpeg.js new file mode 100644 index 0000000..a1d9215 --- /dev/null +++ b/node_modules/prism-media/src/core/FFmpeg.js @@ -0,0 +1,160 @@ +const ChildProcess = require('child_process'); +const { Duplex } = require('stream'); + +let FFMPEG = { + command: null, + output: null, +}; + +const VERSION_REGEX = /version (.+) Copyright/mi; + +Object.defineProperty(FFMPEG, 'version', { + get() { + return VERSION_REGEX.exec(FFMPEG.output)[1]; + }, + enumerable: true, +}); + +/** + * An FFmpeg transform stream that provides an interface to FFmpeg. + * @memberof core + */ +class FFmpeg extends Duplex { + /** + * Creates a new FFmpeg transform stream + * @memberof core + * @param {Object} options Options you would pass to a regular Transform stream, plus an `args` option + * @param {Array} options.args Arguments to pass to FFmpeg + * @param {boolean} [options.shell=false] Whether FFmpeg should be spawned inside a shell + * @example + * // By default, if you don't specify an input (`-i ...`) prism will assume you're piping a stream into it. + * const transcoder = new prism.FFmpeg({ + * args: [ + * '-analyzeduration', '0', + * '-loglevel', '0', + * '-f', 's16le', + * '-ar', '48000', + * '-ac', '2', + * ] + * }); + * const s16le = mp3File.pipe(transcoder); + * const opus = s16le.pipe(new prism.opus.Encoder({ rate: 48000, channels: 2, frameSize: 960 })); + */ + constructor(options = {}) { + super(); + this.process = FFmpeg.create({ shell: false, ...options }); + const EVENTS = { + readable: this._reader, + data: this._reader, + end: this._reader, + unpipe: this._reader, + finish: this._writer, + drain: this._writer, + }; + + this._readableState = this._reader._readableState; + this._writableState = this._writer._writableState; + + this._copy(['write', 'end'], this._writer); + this._copy(['read', 'setEncoding', 'pipe', 'unpipe'], this._reader); + + for (const method of ['on', 'once', 'removeListener', 'removeListeners', 'listeners']) { + this[method] = (ev, fn) => EVENTS[ev] ? EVENTS[ev][method](ev, fn) : Duplex.prototype[method].call(this, ev, fn); + } + + const processError = error => this.emit('error', error); + this._reader.on('error', processError); + this._writer.on('error', processError); + } + + get _reader() { return this.process.stdout; } + get _writer() { return this.process.stdin; } + + _copy(methods, target) { + for (const method of methods) { + this[method] = target[method].bind(target); + } + } + + _destroy(err, cb) { + this._cleanup(); + return cb ? cb(err) : undefined; + } + + _final(cb) { + this._cleanup(); + cb(); + } + + _cleanup() { + if (this.process) { + this.once('error', () => {}); + this.process.kill('SIGKILL'); + this.process = null; + } + } + + + /** + * The available FFmpeg information + * @typedef {Object} FFmpegInfo + * @memberof core + * @property {string} command The command used to launch FFmpeg + * @property {string} output The output from running `ffmpeg -h` + * @property {string} version The version of FFmpeg being used, determined from `output`. + */ + + /** + * Finds a suitable FFmpeg command and obtains the debug information from it. + * @param {boolean} [force=false] If true, will ignore any cached results and search for the command again + * @returns {FFmpegInfo} + * @throws Will throw an error if FFmpeg cannot be found. + * @example + * const ffmpeg = prism.FFmpeg.getInfo(); + * + * console.log(`Using FFmpeg version ${ffmpeg.version}`); + * + * if (ffmpeg.output.includes('--enable-libopus')) { + * console.log('libopus is available!'); + * } else { + * console.log('libopus is unavailable!'); + * } + */ + static getInfo(force = false) { + if (FFMPEG.command && !force) return FFMPEG; + const sources = [() => { + const ffmpegStatic = require('ffmpeg-static'); + return ffmpegStatic.path || ffmpegStatic; + }, 'ffmpeg', 'avconv', './ffmpeg', './avconv']; + for (let source of sources) { + try { + if (typeof source === 'function') source = source(); + const result = ChildProcess.spawnSync(source, ['-h'], { windowsHide: true }); + if (result.error) throw result.error; + Object.assign(FFMPEG, { + command: source, + output: Buffer.concat(result.output.filter(Boolean)).toString(), + }); + return FFMPEG; + } catch (error) { + // Do nothing + } + } + throw new Error('FFmpeg/avconv not found!'); + } + + /** + * Creates a new FFmpeg instance. If you do not include `-i ...` it will be assumed that `-i -` should be prepended + * to the options and that you'll be piping data into the process. + * @param {String[]} [args=[]] Arguments to pass to FFmpeg + * @returns {ChildProcess} + * @private + * @throws Will throw an error if FFmpeg cannot be found. + */ + static create({ args = [], shell = false } = {}) { + if (!args.includes('-i')) args.unshift('-i', '-'); + return ChildProcess.spawn(FFmpeg.getInfo().command, args.concat(['pipe:1']), { windowsHide: true, shell }); + } +} + +module.exports = FFmpeg; diff --git a/node_modules/prism-media/src/core/VolumeTransformer.js b/node_modules/prism-media/src/core/VolumeTransformer.js new file mode 100644 index 0000000..d4b5cb8 --- /dev/null +++ b/node_modules/prism-media/src/core/VolumeTransformer.js @@ -0,0 +1,128 @@ +// Based on discord.js' old volume system + +const { Transform } = require('stream'); + +/** + * Transforms a stream of PCM volume. + * @memberof core + * @extends TransformStream + */ +class VolumeTransformer extends Transform { + /** + * @memberof core + * @param {Object} options Any optional TransformStream options plus some extra: + * @param {string} options.type The type of transformer: s16le (signed 16-bit little-endian), s16be, s32le, s32be + * @param {number} [options.volume=1] The output volume of the stream + * @example + * // Half the volume of a signed 16-bit little-endian PCM stream + * input + * .pipe(new prism.VolumeTransformer({ type: 's16le', volume: 0.5 })) + * .pipe(writeStream); + */ + constructor(options = {}) { + super(options); + switch (options.type) { + case 's16le': + this._readInt = (buffer, index) => buffer.readInt16LE(index); + this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index); + this._bits = 16; + break; + case 's16be': + this._readInt = (buffer, index) => buffer.readInt16BE(index); + this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index); + this._bits = 16; + break; + case 's32le': + this._readInt = (buffer, index) => buffer.readInt32LE(index); + this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index); + this._bits = 32; + break; + case 's32be': + this._readInt = (buffer, index) => buffer.readInt32BE(index); + this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index); + this._bits = 32; + break; + default: + throw new Error('VolumeTransformer type should be one of s16le, s16be, s32le, s32be'); + } + this._bytes = this._bits / 8; + this._extremum = Math.pow(2, this._bits - 1); + this.volume = typeof options.volume === 'undefined' ? 1 : options.volume; + this._chunk = Buffer.alloc(0); + } + + _readInt(buffer, index) { return index; } + _writeInt(buffer, int, index) { return index; } + + _transform(chunk, encoding, done) { + // If the volume is 1, act like a passthrough stream + if (this.volume === 1) { + this.push(chunk); + return done(); + } + + const { _bytes, _extremum } = this; + + chunk = this._chunk = Buffer.concat([this._chunk, chunk]); + if (chunk.length < _bytes) return done(); + + const complete = Math.floor(chunk.length / _bytes) * _bytes; + + for (let i = 0; i < complete; i += _bytes) { + const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i)))); + this._writeInt(chunk, int, i); + } + + this._chunk = chunk.slice(complete); + this.push(chunk.slice(0, complete)); + return done(); + } + + _destroy(err, cb) { + super._destroy(err, cb); + this._chunk = null; + } + + /** + * Sets the volume relative to the input stream - i.e. 1 is normal, 0.5 is half, 2 is double. + * @param {number} volume The volume that you want to set + */ + setVolume(volume) { + this.volume = volume; + } + + /** + * Sets the volume in decibels. + * @param {number} db The decibels + */ + setVolumeDecibels(db) { + this.setVolume(Math.pow(10, db / 20)); + } + + /** + * Sets the volume so that a perceived value of 0.5 is half the perceived volume etc. + * @param {number} value The value for the volume + */ + setVolumeLogarithmic(value) { + this.setVolume(Math.pow(value, 1.660964)); + } + + /** + * The current volume of the stream in decibels + * @readonly + * @type {number} + */ + get volumeDecibels() { + return Math.log10(this._volume) * 20; + } + /** + * The current volume of the stream from a logarithmic scale + * @readonly + * @type {number} + */ + get volumeLogarithmic() { + return Math.pow(this._volume, 1 / 1.660964); + } +} + +module.exports = VolumeTransformer; diff --git a/node_modules/prism-media/src/core/WebmBase.js b/node_modules/prism-media/src/core/WebmBase.js new file mode 100644 index 0000000..453a4be --- /dev/null +++ b/node_modules/prism-media/src/core/WebmBase.js @@ -0,0 +1,218 @@ +const { Transform } = require('stream'); + +/** + * Base class for WebmOpusDemuxer and WebmVorbisDemuxer. + * **You shouldn't directly instantiate this class, use the opus.WebmDemuxer and vorbis.WebmDemuxer + * implementations instead!** + * @memberof core + * @protected + * @extends TransformStream + */ +class WebmBaseDemuxer extends Transform { + /** + * Creates a new Webm demuxer. + * @private + * @memberof core + * @param {Object} [options] options that you would pass to a regular Transform stream. + */ + constructor(options = {}) { + super(Object.assign({ readableObjectMode: true }, options)); + this._remainder = null; + this._length = 0; + this._count = 0; + this._skipUntil = null; + this._track = null; + this._incompleteTrack = {}; + this._ebmlFound = false; + } + + _transform(chunk, encoding, done) { + this._length += chunk.length; + if (this._remainder) { + chunk = Buffer.concat([this._remainder, chunk]); + this._remainder = null; + } + let offset = 0; + if (this._skipUntil && this._length > this._skipUntil) { + offset = this._skipUntil - this._count; + this._skipUntil = null; + } else if (this._skipUntil) { + this._count += chunk.length; + return done(); + } + let result; + while (result !== TOO_SHORT) { + result = this._readTag(chunk, offset); + if (result === TOO_SHORT) break; + if (result._skipUntil) { + this._skipUntil = result._skipUntil; + break; + } + if (result.offset) offset = result.offset; + else break; + } + this._count += offset; + this._remainder = chunk.slice(offset); + return done(); + } + + /** + * Reads an EBML ID from a buffer. + * @private + * @param {Buffer} chunk the buffer to read from. + * @param {number} offset the offset in the buffer. + * @returns {Object|Symbol} contains an `id` property (buffer) and the new `offset` (number). + * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request. + */ + _readEBMLId(chunk, offset) { + const idLength = vintLength(chunk, offset); + if (idLength === TOO_SHORT) return TOO_SHORT; + return { + id: chunk.slice(offset, offset + idLength), + offset: offset + idLength, + }; + } + + /** + * Reads a size variable-integer to calculate the length of the data of a tag. + * @private + * @param {Buffer} chunk the buffer to read from. + * @param {number} offset the offset in the buffer. + * @returns {Object|Symbol} contains property `offset` (number), `dataLength` (number) and `sizeLength` (number). + * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request. + */ + _readTagDataSize(chunk, offset) { + const sizeLength = vintLength(chunk, offset); + if (sizeLength === TOO_SHORT) return TOO_SHORT; + const dataLength = expandVint(chunk, offset, offset + sizeLength); + return { offset: offset + sizeLength, dataLength, sizeLength }; + } + + /** + * Takes a buffer and attempts to read and process a tag. + * @private + * @param {Buffer} chunk the buffer to read from. + * @param {number} offset the offset in the buffer. + * @returns {Object|Symbol} contains the new `offset` (number) and optionally the `_skipUntil` property, + * indicating that the stream should ignore any data until a certain length is reached. + * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request. + */ + _readTag(chunk, offset) { + const idData = this._readEBMLId(chunk, offset); + if (idData === TOO_SHORT) return TOO_SHORT; + const ebmlID = idData.id.toString('hex'); + if (!this._ebmlFound) { + if (ebmlID === '1a45dfa3') this._ebmlFound = true; + else throw Error('Did not find the EBML tag at the start of the stream'); + } + offset = idData.offset; + const sizeData = this._readTagDataSize(chunk, offset); + if (sizeData === TOO_SHORT) return TOO_SHORT; + const { dataLength } = sizeData; + offset = sizeData.offset; + // If this tag isn't useful, tell the stream to stop processing data until the tag ends + if (typeof TAGS[ebmlID] === 'undefined') { + if (chunk.length > offset + dataLength) { + return { offset: offset + dataLength }; + } + return { offset, _skipUntil: this._count + offset + dataLength }; + } + + const tagHasChildren = TAGS[ebmlID]; + if (tagHasChildren) { + return { offset }; + } + + if (offset + dataLength > chunk.length) return TOO_SHORT; + const data = chunk.slice(offset, offset + dataLength); + if (!this._track) { + if (ebmlID === 'ae') this._incompleteTrack = {}; + if (ebmlID === 'd7') this._incompleteTrack.number = data[0]; + if (ebmlID === '83') this._incompleteTrack.type = data[0]; + if (this._incompleteTrack.type === 2 && typeof this._incompleteTrack.number !== 'undefined') { + this._track = this._incompleteTrack; + } + } + if (ebmlID === '63a2') { + this._checkHead(data); + } else if (ebmlID === 'a3') { + if (!this._track) throw Error('No audio track in this webm!'); + if ((data[0] & 0xF) === this._track.number) { + this.push(data.slice(4)); + } + } + return { offset: offset + dataLength }; + } + + _destroy(err, cb) { + this._cleanup(); + return cb ? cb(err) : undefined; + } + + _final(cb) { + this._cleanup(); + cb(); + } + + /** + * Cleans up the demuxer when it is no longer required. + * @private + */ + _cleanup() { + this._remainder = null; + this._incompleteTrack = {}; + } +} + +/** + * A symbol that is returned by some functions that indicates the buffer it has been provided is not large enough + * to facilitate a request. + * @name WebmBaseDemuxer#TOO_SHORT + * @memberof core + * @private + * @type {Symbol} + */ +const TOO_SHORT = WebmBaseDemuxer.TOO_SHORT = Symbol('TOO_SHORT'); + +/** + * A map that takes a value of an EBML ID in hex string form, with the value being a boolean that indicates whether + * this tag has children. + * @name WebmBaseDemuxer#TAGS + * @memberof core + * @private + * @type {Object} + */ +const TAGS = WebmBaseDemuxer.TAGS = { // value is true if the element has children + '1a45dfa3': true, // EBML + '18538067': true, // Segment + '1f43b675': true, // Cluster + '1654ae6b': true, // Tracks + 'ae': true, // TrackEntry + 'd7': false, // TrackNumber + '83': false, // TrackType + 'a3': false, // SimpleBlock + '63a2': false, +}; + +module.exports = WebmBaseDemuxer; + +function vintLength(buffer, index) { + let i = 0; + for (; i < 8; i++) if ((1 << (7 - i)) & buffer[index]) break; + i++; + if (index + i > buffer.length) { + return TOO_SHORT; + } + return i; +} + +function expandVint(buffer, start, end) { + const length = vintLength(buffer, start); + if (end > buffer.length || length === TOO_SHORT) return TOO_SHORT; + let mask = (1 << (8 - length)) - 1; + let value = buffer[start] & mask; + for (let i = start + 1; i < end; i++) { + value = (value << 8) + buffer[i]; + } + return value; +} diff --git a/node_modules/prism-media/src/core/index.js b/node_modules/prism-media/src/core/index.js new file mode 100644 index 0000000..ae9967f --- /dev/null +++ b/node_modules/prism-media/src/core/index.js @@ -0,0 +1,9 @@ +/** + * Core features. + * **You shouldn't prefix imports from this namespace with `core`.** + * @namespace core + */ +module.exports = { + FFmpeg: require('./FFmpeg'), + VolumeTransformer: require('./VolumeTransformer'), +}; diff --git a/node_modules/prism-media/src/index.js b/node_modules/prism-media/src/index.js new file mode 100644 index 0000000..ce34849 --- /dev/null +++ b/node_modules/prism-media/src/index.js @@ -0,0 +1,5 @@ +module.exports = { + opus: require('./opus'), + vorbis: require('./vorbis'), + ...require('./core'), +}; diff --git a/node_modules/prism-media/src/opus/OggDemuxer.js b/node_modules/prism-media/src/opus/OggDemuxer.js new file mode 100644 index 0000000..fdb1bc0 --- /dev/null +++ b/node_modules/prism-media/src/opus/OggDemuxer.js @@ -0,0 +1,138 @@ +const { Transform } = require('stream'); + +const OGG_PAGE_HEADER_SIZE = 26; +const STREAM_STRUCTURE_VERSION = 0; + +const charCode = x => x.charCodeAt(0); +const OGGS_HEADER = Buffer.from([...'OggS'].map(charCode)); +const OPUS_HEAD = Buffer.from([...'OpusHead'].map(charCode)); +const OPUS_TAGS = Buffer.from([...'OpusTags'].map(charCode)); + +/** + * Demuxes an Ogg stream (containing Opus audio) to output an Opus stream. + * @extends {TransformStream} + * @memberof opus + */ +class OggDemuxer extends Transform { + /** + * Creates a new OggOpus demuxer. + * @param {Object} [options] options that you would pass to a regular Transform stream. + * @memberof opus + */ + constructor(options = {}) { + super(Object.assign({ readableObjectMode: true }, options)); + this._remainder = null; + this._head = null; + this._bitstream = null; + } + + _transform(chunk, encoding, done) { + if (this._remainder) { + chunk = Buffer.concat([this._remainder, chunk]); + this._remainder = null; + } + + while (chunk) { + const result = this._readPage(chunk); + if (result) chunk = result; + else break; + } + this._remainder = chunk; + done(); + } + + /** + * Reads a page from a buffer + * @private + * @param {Buffer} chunk the chunk containing the page + * @returns {boolean|Buffer} if a buffer, it will be a slice of the excess data of the original, otherwise it will be + * false and would indicate that there is not enough data to go ahead with reading this page. + */ + _readPage(chunk) { + if (chunk.length < OGG_PAGE_HEADER_SIZE) { + return false; + } + if (!chunk.slice(0, 4).equals(OGGS_HEADER)) { + throw Error(`capture_pattern is not ${OGGS_HEADER}`); + } + if (chunk.readUInt8(4) !== STREAM_STRUCTURE_VERSION) { + throw Error(`stream_structure_version is not ${STREAM_STRUCTURE_VERSION}`); + } + + if (chunk.length < 27) return false; + const pageSegments = chunk.readUInt8(26); + if (chunk.length < 27 + pageSegments) return false; + const table = chunk.slice(27, 27 + pageSegments); + const bitstream = chunk.readUInt32BE(14); + + let sizes = [], totalSize = 0; + + for (let i = 0; i < pageSegments;) { + let size = 0, x = 255; + while (x === 255) { + if (i >= table.length) return false; + x = table.readUInt8(i); + i++; + size += x; + } + sizes.push(size); + totalSize += size; + } + + if (chunk.length < 27 + pageSegments + totalSize) return false; + + let start = 27 + pageSegments; + for (const size of sizes) { + const segment = chunk.slice(start, start + size); + const header = segment.slice(0, 8); + if (this._head) { + if (header.equals(OPUS_TAGS)) this.emit('tags', segment); + else if (this._bitstream === bitstream) this.push(segment); + } else if (header.equals(OPUS_HEAD)) { + this.emit('head', segment); + this._head = segment; + this._bitstream = bitstream; + } else { + this.emit('unknownSegment', segment); + } + start += size; + } + return chunk.slice(start); + } + + _destroy(err, cb) { + this._cleanup(); + return cb ? cb(err) : undefined; + } + + _final(cb) { + this._cleanup(); + cb(); + } + + /** + * Cleans up the demuxer when it is no longer required. + * @private + */ + _cleanup() { + this._remainder = null; + this._head = null; + this._bitstream = null; + } +} + +/** + * Emitted when the demuxer encounters the opus head. + * @event OggDemuxer#head + * @memberof opus + * @param {Buffer} segment a buffer containing the opus head data. + */ + +/** + * Emitted when the demuxer encounters opus tags. + * @event OggDemuxer#tags + * @memberof opus + * @param {Buffer} segment a buffer containing the opus tags. + */ + +module.exports = OggDemuxer; diff --git a/node_modules/prism-media/src/opus/Opus.js b/node_modules/prism-media/src/opus/Opus.js new file mode 100644 index 0000000..d8d6c29 --- /dev/null +++ b/node_modules/prism-media/src/opus/Opus.js @@ -0,0 +1,212 @@ +// Partly based on https://github.com/Rantanen/node-opus/blob/master/lib/Encoder.js + +const { Transform } = require('stream'); +const loader = require('../util/loader'); + +const CTL = { + BITRATE: 4002, + FEC: 4012, + PLP: 4014, +}; + +let Opus = {}; + +function loadOpus(refresh = false) { + if (Opus.Encoder && !refresh) return Opus; + + Opus = loader.require([ + ['@discordjs/opus', opus => ({ Encoder: opus.OpusEncoder })], + ['node-opus', opus => ({ Encoder: opus.OpusEncoder })], + ['opusscript', opus => ({ Encoder: opus })], + ]); + return Opus; +} + +const charCode = x => x.charCodeAt(0); +const OPUS_HEAD = Buffer.from([...'OpusHead'].map(charCode)); +const OPUS_TAGS = Buffer.from([...'OpusTags'].map(charCode)); + +// frame size = (channels * rate * frame_duration) / 1000 + +/** + * Takes a stream of Opus data and outputs a stream of PCM data, or the inverse. + * **You shouldn't directly instantiate this class, see opus.Encoder and opus.Decoder instead!** + * @memberof opus + * @extends TransformStream + * @protected + */ +class OpusStream extends Transform { + /** + * Creates a new Opus transformer. + * @private + * @memberof opus + * @param {Object} [options] options that you would pass to a regular Transform stream + */ + constructor(options = {}) { + if (!loadOpus().Encoder) { + throw Error('Could not find an Opus module! Please install @discordjs/opus, node-opus, or opusscript.'); + } + super(Object.assign({ readableObjectMode: true }, options)); + if (Opus.name === 'opusscript') { + options.application = Opus.Encoder.Application[options.application]; + } + this.encoder = new Opus.Encoder(options.rate, options.channels, options.application); + + this._options = options; + this._required = this._options.frameSize * this._options.channels * 2; + } + + _encode(buffer) { + return this.encoder.encode(buffer, this._options.frameSize); + } + + _decode(buffer) { + return this.encoder.decode(buffer, Opus.name === 'opusscript' ? null : this._options.frameSize); + } + + /** + * Returns the Opus module being used - `opusscript`, `node-opus`, or `@discordjs/opus`. + * @type {string} + * @readonly + * @example + * console.log(`Using Opus module ${prism.opus.Encoder.type}`); + */ + static get type() { + return Opus.name; + } + + /** + * Sets the bitrate of the stream. + * @param {number} bitrate the bitrate to use use, e.g. 48000 + * @public + */ + setBitrate(bitrate) { + (this.encoder.applyEncoderCTL || this.encoder.encoderCTL) + .apply(this.encoder, [CTL.BITRATE, Math.min(128e3, Math.max(16e3, bitrate))]); + } + + /** + * Enables or disables forward error correction. + * @param {boolean} enabled whether or not to enable FEC. + * @public + */ + setFEC(enabled) { + (this.encoder.applyEncoderCTL || this.encoder.encoderCTL) + .apply(this.encoder, [CTL.FEC, enabled ? 1 : 0]); + } + + /** + * Sets the expected packet loss over network transmission. + * @param {number} [percentage] a percentage (represented between 0 and 1) + */ + setPLP(percentage) { + (this.encoder.applyEncoderCTL || this.encoder.encoderCTL) + .apply(this.encoder, [CTL.PLP, Math.min(100, Math.max(0, percentage * 100))]); + } + + _final(cb) { + this._cleanup(); + cb(); + } + + _destroy(err, cb) { + this._cleanup(); + return cb ? cb(err) : undefined; + } + + /** + * Cleans up the Opus stream when it is no longer needed + * @private + */ + _cleanup() { + if (Opus.name === 'opusscript' && this.encoder) this.encoder.delete(); + this.encoder = null; + } +} + +/** + * An Opus encoder stream. + * + * Outputs opus packets in [object mode.](https://nodejs.org/api/stream.html#stream_object_mode) + * @extends opus.OpusStream + * @memberof opus + * @example + * const encoder = new prism.opus.Encoder({ frameSize: 960, channels: 2, rate: 48000 }); + * pcmAudio.pipe(encoder); + * // encoder will now output Opus-encoded audio packets + */ +class Encoder extends OpusStream { + /** + * Creates a new Opus encoder stream. + * @memberof opus + * @param {Object} options options that you would pass to a regular OpusStream, plus a few more: + * @param {number} options.frameSize the frame size in bytes to use (e.g. 960 for stereo audio at 48KHz with a frame + * duration of 20ms) + * @param {number} options.channels the number of channels to use + * @param {number} options.rate the sampling rate in Hz + */ + constructor(options) { + super(options); + this._buffer = Buffer.alloc(0); + } + + _transform(chunk, encoding, done) { + this._buffer = Buffer.concat([this._buffer, chunk]); + let n = 0; + while (this._buffer.length >= this._required * (n + 1)) { + const buf = this._encode(this._buffer.slice(n * this._required, (n + 1) * this._required)); + this.push(buf); + n++; + } + if (n > 0) this._buffer = this._buffer.slice(n * this._required); + return done(); + } + + _destroy(err, cb) { + super._destroy(err, cb); + this._buffer = null; + } +} + +/** + * An Opus decoder stream. + * + * Note that any stream you pipe into this must be in + * [object mode](https://nodejs.org/api/stream.html#stream_object_mode) and should output Opus packets. + * @extends opus.OpusStream + * @memberof opus + * @example + * const decoder = new prism.opus.Decoder({ frameSize: 960, channels: 2, rate: 48000 }); + * input.pipe(decoder); + * // decoder will now output PCM audio + */ +class Decoder extends OpusStream { + _transform(chunk, encoding, done) { + const signature = chunk.slice(0, 8); + if (signature.equals(OPUS_HEAD)) { + this.emit('format', { + channels: this._options.channels, + sampleRate: this._options.rate, + bitDepth: 16, + float: false, + signed: true, + version: chunk.readUInt8(8), + preSkip: chunk.readUInt16LE(10), + gain: chunk.readUInt16LE(16), + }); + return done(); + } + if (signature.equals(OPUS_TAGS)) { + this.emit('tags', chunk); + return done(); + } + try { + this.push(this._decode(chunk)); + } catch (e) { + return done(e); + } + return done(); + } +} + +module.exports = { Decoder, Encoder }; diff --git a/node_modules/prism-media/src/opus/WebmDemuxer.js b/node_modules/prism-media/src/opus/WebmDemuxer.js new file mode 100644 index 0000000..4d78f9c --- /dev/null +++ b/node_modules/prism-media/src/opus/WebmDemuxer.js @@ -0,0 +1,24 @@ +const WebmBaseDemuxer = require('../core/WebmBase'); + +const OPUS_HEAD = Buffer.from([...'OpusHead'].map(x => x.charCodeAt(0))); + +/** + * Demuxes a Webm stream (containing Opus audio) to output an Opus stream. + * @extends core.WebmBaseDemuxer + * @memberof opus + * @example + * const fs = require('fs'); + * const file = fs.createReadStream('./audio.webm'); + * const demuxer = new prism.opus.WebmDemuxer(); + * const opus = file.pipe(demuxer); + * // opus is now a ReadableStream in object mode outputting Opus packets + */ +class WebmDemuxer extends WebmBaseDemuxer { + _checkHead(data) { + if (!data.slice(0, 8).equals(OPUS_HEAD)) { + throw Error('Audio codec is not Opus!'); + } + } +} + +module.exports = WebmDemuxer; diff --git a/node_modules/prism-media/src/opus/index.js b/node_modules/prism-media/src/opus/index.js new file mode 100644 index 0000000..3532fdc --- /dev/null +++ b/node_modules/prism-media/src/opus/index.js @@ -0,0 +1,10 @@ +/** + * Opus features + * @namespace opus + */ +module.exports = { + // Encoder and Decoder + ...require('./Opus'), + OggDemuxer: require('./OggDemuxer'), + WebmDemuxer: require('./WebmDemuxer'), +}; diff --git a/node_modules/prism-media/src/util/loader.js b/node_modules/prism-media/src/util/loader.js new file mode 100644 index 0000000..1b1deab --- /dev/null +++ b/node_modules/prism-media/src/util/loader.js @@ -0,0 +1,13 @@ +exports.require = function loader(list) { + const errorLog = []; + for (const [name, fn] of list) { + try { + const data = fn(require(name)); + data.name = name; + return data; + } catch (e) { + errorLog.push(e); + } + } + throw new Error(errorLog.join('\n')); +}; diff --git a/node_modules/prism-media/src/vorbis/WebmDemuxer.js b/node_modules/prism-media/src/vorbis/WebmDemuxer.js new file mode 100644 index 0000000..9ef84dc --- /dev/null +++ b/node_modules/prism-media/src/vorbis/WebmDemuxer.js @@ -0,0 +1,22 @@ +const WebmBaseDemuxer = require('../core/WebmBase'); + +const VORBIS_HEAD = Buffer.from([...'vorbis'].map(x => x.charCodeAt(0))); + +/** + * Demuxes a Webm stream (containing Vorbis audio) to output a Vorbis stream. + * @memberof vorbis + * @extends core.WebmBaseDemuxer + */ +class WebmDemuxer extends WebmBaseDemuxer { + _checkHead(data) { + if (data.readUInt8(0) !== 2 || !data.slice(4, 10).equals(VORBIS_HEAD)) { + throw Error('Audio codec is not Vorbis!'); + } + + this.push(data.slice(3, 3 + data.readUInt8(1))); + this.push(data.slice(3 + data.readUInt8(1), 3 + data.readUInt8(1) + data.readUInt8(2))); + this.push(data.slice(3 + data.readUInt8(1) + data.readUInt8(2))); + } +} + +module.exports = WebmDemuxer; diff --git a/node_modules/prism-media/src/vorbis/index.js b/node_modules/prism-media/src/vorbis/index.js new file mode 100644 index 0000000..9d06df8 --- /dev/null +++ b/node_modules/prism-media/src/vorbis/index.js @@ -0,0 +1,8 @@ +/** + * Vorbis features + * @namespace vorbis + */ + +module.exports = { + WebmDemuxer: require('./WebmDemuxer'), +}; diff --git a/node_modules/prism-media/typings/index.d.ts b/node_modules/prism-media/typings/index.d.ts new file mode 100644 index 0000000..cd980d3 --- /dev/null +++ b/node_modules/prism-media/typings/index.d.ts @@ -0,0 +1,43 @@ +import { Transform } from 'stream'; + +import { ChildProcess } from 'child_process'; +import { Duplex } from 'stream'; + +import { opus } from './opus'; +import { vorbis } from './vorbis'; + +export interface FFmpegOptions { + args?: string[]; + shell?: boolean; +} + +export interface FFmpegInfo { + command: string; + info: string; + version: string; + output: string; +} + +export class FFmpeg extends Duplex { + public process: ChildProcess; + constructor(options?: FFmpegOptions); + static getInfo(force?: boolean): FFmpegInfo; +} + +export interface VolumeOptions { + type: 's16le' | 's16be' | 's32le' | 's32be', + volume?: number +} + +export class VolumeTransformer extends Transform { + public volume: number; + + constructor(options: VolumeOptions); + public setVolume(volume: number): void; + public setVolumeDecibels(db: number): void; + public setVolumeLogarithmic(value: number): void; + public readonly volumeDecibels: number; + public readonly volumeLogarithmic: number; +} + +export { opus, vorbis }; diff --git a/node_modules/prism-media/typings/opus.d.ts b/node_modules/prism-media/typings/opus.d.ts new file mode 100644 index 0000000..b37facb --- /dev/null +++ b/node_modules/prism-media/typings/opus.d.ts @@ -0,0 +1,30 @@ +import { Transform } from 'stream'; + +interface OpusOptions { + frameSize: number, + channels: number, + rate: number +} + +export class OpusStream extends Transform { + public encoder: any; // TODO: type opusscript/node-opus + + constructor(options?: OpusOptions); + public static readonly type: 'opusscript' | 'node-opus' | '@discordjs/opus'; + public setBitrate(bitrate: number): void; + public setFEC(enabled: boolean): void; + public setPLP(percentage: number): void; +} + +export namespace opus { + interface OpusOptions { + frameSize: number, + channels: number, + rate: number + } + + export class Encoder extends OpusStream {} + export class Decoder extends OpusStream {} + export class OggDemuxer extends Transform {} + export class WebmDemuxer extends Transform {} +} \ No newline at end of file diff --git a/node_modules/prism-media/typings/vorbis.d.ts b/node_modules/prism-media/typings/vorbis.d.ts new file mode 100644 index 0000000..6c18898 --- /dev/null +++ b/node_modules/prism-media/typings/vorbis.d.ts @@ -0,0 +1,5 @@ +import { Transform } from 'stream'; + +export namespace vorbis { + export class WebmDemuxer extends Transform {} +} \ No newline at end of file diff --git a/node_modules/pump/.travis.yml b/node_modules/pump/.travis.yml new file mode 100644 index 0000000..17f9433 --- /dev/null +++ b/node_modules/pump/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" + +script: "npm test" diff --git a/node_modules/pump/LICENSE b/node_modules/pump/LICENSE new file mode 100644 index 0000000..757562e --- /dev/null +++ b/node_modules/pump/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/pump/README.md b/node_modules/pump/README.md new file mode 100644 index 0000000..4c81471 --- /dev/null +++ b/node_modules/pump/README.md @@ -0,0 +1,65 @@ +# pump + +pump is a small node module that pipes streams together and destroys all of them if one of them closes. + +``` +npm install pump +``` + +[![build status](http://img.shields.io/travis/mafintosh/pump.svg?style=flat)](http://travis-ci.org/mafintosh/pump) + +## What problem does it solve? + +When using standard `source.pipe(dest)` source will _not_ be destroyed if dest emits close or an error. +You are also not able to provide a callback to tell when then pipe has finished. + +pump does these two things for you + +## Usage + +Simply pass the streams you want to pipe together to pump and add an optional callback + +``` js +var pump = require('pump') +var fs = require('fs') + +var source = fs.createReadStream('/dev/random') +var dest = fs.createWriteStream('/dev/null') + +pump(source, dest, function(err) { + console.log('pipe finished', err) +}) + +setTimeout(function() { + dest.destroy() // when dest is closed pump will destroy source +}, 1000) +``` + +You can use pump to pipe more than two streams together as well + +``` js +var transform = someTransformStream() + +pump(source, transform, anotherTransform, dest, function(err) { + console.log('pipe finished', err) +}) +``` + +If `source`, `transform`, `anotherTransform` or `dest` closes all of them will be destroyed. + +Similarly to `stream.pipe()`, `pump()` returns the last stream passed in, so you can do: + +``` +return pump(s1, s2) // returns s2 +``` + +If you want to return a stream that combines *both* s1 and s2 to a single stream use +[pumpify](https://github.com/mafintosh/pumpify) instead. + +## License + +MIT + +## Related + +`pump` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one. diff --git a/node_modules/pump/index.js b/node_modules/pump/index.js new file mode 100644 index 0000000..c15059f --- /dev/null +++ b/node_modules/pump/index.js @@ -0,0 +1,82 @@ +var once = require('once') +var eos = require('end-of-stream') +var fs = require('fs') // we only need fs to get the ReadStream and WriteStream prototypes + +var noop = function () {} +var ancient = /^v?\.0/.test(process.version) + +var isFn = function (fn) { + return typeof fn === 'function' +} + +var isFS = function (stream) { + if (!ancient) return false // newer node version do not need to care about fs is a special way + if (!fs) return false // browser + return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close) +} + +var isRequest = function (stream) { + return stream.setHeader && isFn(stream.abort) +} + +var destroyer = function (stream, reading, writing, callback) { + callback = once(callback) + + var closed = false + stream.on('close', function () { + closed = true + }) + + eos(stream, {readable: reading, writable: writing}, function (err) { + if (err) return callback(err) + closed = true + callback() + }) + + var destroyed = false + return function (err) { + if (closed) return + if (destroyed) return + destroyed = true + + if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks + if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want + + if (isFn(stream.destroy)) return stream.destroy() + + callback(err || new Error('stream was destroyed')) + } +} + +var call = function (fn) { + fn() +} + +var pipe = function (from, to) { + return from.pipe(to) +} + +var pump = function () { + var streams = Array.prototype.slice.call(arguments) + var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop + + if (Array.isArray(streams[0])) streams = streams[0] + if (streams.length < 2) throw new Error('pump requires two streams per minimum') + + var error + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1 + var writing = i > 0 + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err + if (err) destroys.forEach(call) + if (reading) return + destroys.forEach(call) + callback(error) + }) + }) + + return streams.reduce(pipe) +} + +module.exports = pump diff --git a/node_modules/pump/package.json b/node_modules/pump/package.json new file mode 100644 index 0000000..0b838f9 --- /dev/null +++ b/node_modules/pump/package.json @@ -0,0 +1,24 @@ +{ + "name": "pump", + "version": "3.0.0", + "repository": "git://github.com/mafintosh/pump.git", + "license": "MIT", + "description": "pipe streams together and close all of them if one of them closes", + "browser": { + "fs": false + }, + "keywords": [ + "streams", + "pipe", + "destroy", + "callback" + ], + "author": "Mathias Buus Madsen ", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + }, + "scripts": { + "test": "node test-browser.js && node test-node.js" + } +} diff --git a/node_modules/pump/test-browser.js b/node_modules/pump/test-browser.js new file mode 100644 index 0000000..9a06c8a --- /dev/null +++ b/node_modules/pump/test-browser.js @@ -0,0 +1,66 @@ +var stream = require('stream') +var pump = require('./index') + +var rs = new stream.Readable() +var ws = new stream.Writable() + +rs._read = function (size) { + this.push(Buffer(size).fill('abc')) +} + +ws._write = function (chunk, encoding, cb) { + setTimeout(function () { + cb() + }, 100) +} + +var toHex = function () { + var reverse = new (require('stream').Transform)() + + reverse._transform = function (chunk, enc, callback) { + reverse.push(chunk.toString('hex')) + callback() + } + + return reverse +} + +var wsClosed = false +var rsClosed = false +var callbackCalled = false + +var check = function () { + if (wsClosed && rsClosed && callbackCalled) { + console.log('test-browser.js passes') + clearTimeout(timeout) + } +} + +ws.on('finish', function () { + wsClosed = true + check() +}) + +rs.on('end', function () { + rsClosed = true + check() +}) + +var res = pump(rs, toHex(), toHex(), toHex(), ws, function () { + callbackCalled = true + check() +}) + +if (res !== ws) { + throw new Error('should return last stream') +} + +setTimeout(function () { + rs.push(null) + rs.emit('close') +}, 1000) + +var timeout = setTimeout(function () { + check() + throw new Error('timeout') +}, 5000) diff --git a/node_modules/pump/test-node.js b/node_modules/pump/test-node.js new file mode 100644 index 0000000..561251a --- /dev/null +++ b/node_modules/pump/test-node.js @@ -0,0 +1,53 @@ +var pump = require('./index') + +var rs = require('fs').createReadStream('/dev/random') +var ws = require('fs').createWriteStream('/dev/null') + +var toHex = function () { + var reverse = new (require('stream').Transform)() + + reverse._transform = function (chunk, enc, callback) { + reverse.push(chunk.toString('hex')) + callback() + } + + return reverse +} + +var wsClosed = false +var rsClosed = false +var callbackCalled = false + +var check = function () { + if (wsClosed && rsClosed && callbackCalled) { + console.log('test-node.js passes') + clearTimeout(timeout) + } +} + +ws.on('close', function () { + wsClosed = true + check() +}) + +rs.on('close', function () { + rsClosed = true + check() +}) + +var res = pump(rs, toHex(), toHex(), toHex(), ws, function () { + callbackCalled = true + check() +}) + +if (res !== ws) { + throw new Error('should return last stream') +} + +setTimeout(function () { + rs.destroy() +}, 1000) + +var timeout = setTimeout(function () { + throw new Error('timeout') +}, 5000) diff --git a/node_modules/quick-lru/index.d.ts b/node_modules/quick-lru/index.d.ts new file mode 100644 index 0000000..fa58889 --- /dev/null +++ b/node_modules/quick-lru/index.d.ts @@ -0,0 +1,97 @@ +declare namespace QuickLRU { + interface Options { + /** + The maximum number of items before evicting the least recently used items. + */ + readonly maxSize: number; + + /** + Called right before an item is evicted from the cache. + + Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`). + */ + onEviction?: (key: KeyType, value: ValueType) => void; + } +} + +declare class QuickLRU + implements Iterable<[KeyType, ValueType]> { + /** + The stored item count. + */ + readonly size: number; + + /** + Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29). + + The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop. + + @example + ``` + import QuickLRU = require('quick-lru'); + + const lru = new QuickLRU({maxSize: 1000}); + + lru.set('🦄', '🌈'); + + lru.has('🦄'); + //=> true + + lru.get('🦄'); + //=> '🌈' + ``` + */ + constructor(options: QuickLRU.Options); + + [Symbol.iterator](): IterableIterator<[KeyType, ValueType]>; + + /** + Set an item. + + @returns The list instance. + */ + set(key: KeyType, value: ValueType): this; + + /** + Get an item. + + @returns The stored item or `undefined`. + */ + get(key: KeyType): ValueType | undefined; + + /** + Check if an item exists. + */ + has(key: KeyType): boolean; + + /** + Get an item without marking it as recently used. + + @returns The stored item or `undefined`. + */ + peek(key: KeyType): ValueType | undefined; + + /** + Delete an item. + + @returns `true` if the item is removed or `false` if the item doesn't exist. + */ + delete(key: KeyType): boolean; + + /** + Delete all items. + */ + clear(): void; + + /** + Iterable for all the keys. + */ + keys(): IterableIterator; + + /** + Iterable for all the values. + */ + values(): IterableIterator; +} + +export = QuickLRU; diff --git a/node_modules/quick-lru/index.js b/node_modules/quick-lru/index.js new file mode 100644 index 0000000..7d7032e --- /dev/null +++ b/node_modules/quick-lru/index.js @@ -0,0 +1,123 @@ +'use strict'; + +class QuickLRU { + constructor(options = {}) { + if (!(options.maxSize && options.maxSize > 0)) { + throw new TypeError('`maxSize` must be a number greater than 0'); + } + + this.maxSize = options.maxSize; + this.onEviction = options.onEviction; + this.cache = new Map(); + this.oldCache = new Map(); + this._size = 0; + } + + _set(key, value) { + this.cache.set(key, value); + this._size++; + + if (this._size >= this.maxSize) { + this._size = 0; + + if (typeof this.onEviction === 'function') { + for (const [key, value] of this.oldCache.entries()) { + this.onEviction(key, value); + } + } + + this.oldCache = this.cache; + this.cache = new Map(); + } + } + + get(key) { + if (this.cache.has(key)) { + return this.cache.get(key); + } + + if (this.oldCache.has(key)) { + const value = this.oldCache.get(key); + this.oldCache.delete(key); + this._set(key, value); + return value; + } + } + + set(key, value) { + if (this.cache.has(key)) { + this.cache.set(key, value); + } else { + this._set(key, value); + } + + return this; + } + + has(key) { + return this.cache.has(key) || this.oldCache.has(key); + } + + peek(key) { + if (this.cache.has(key)) { + return this.cache.get(key); + } + + if (this.oldCache.has(key)) { + return this.oldCache.get(key); + } + } + + delete(key) { + const deleted = this.cache.delete(key); + if (deleted) { + this._size--; + } + + return this.oldCache.delete(key) || deleted; + } + + clear() { + this.cache.clear(); + this.oldCache.clear(); + this._size = 0; + } + + * keys() { + for (const [key] of this) { + yield key; + } + } + + * values() { + for (const [, value] of this) { + yield value; + } + } + + * [Symbol.iterator]() { + for (const item of this.cache) { + yield item; + } + + for (const item of this.oldCache) { + const [key] = item; + if (!this.cache.has(key)) { + yield item; + } + } + } + + get size() { + let oldCacheSize = 0; + for (const key of this.oldCache.keys()) { + if (!this.cache.has(key)) { + oldCacheSize++; + } + } + + return Math.min(this._size + oldCacheSize, this.maxSize); + } +} + +module.exports = QuickLRU; diff --git a/node_modules/quick-lru/license b/node_modules/quick-lru/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/quick-lru/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/quick-lru/package.json b/node_modules/quick-lru/package.json new file mode 100644 index 0000000..ff0dd9a --- /dev/null +++ b/node_modules/quick-lru/package.json @@ -0,0 +1,43 @@ +{ + "name": "quick-lru", + "version": "5.1.1", + "description": "Simple “Least Recently Used” (LRU) cache", + "license": "MIT", + "repository": "sindresorhus/quick-lru", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=10" + }, + "scripts": { + "test": "xo && nyc ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "lru", + "quick", + "cache", + "caching", + "least", + "recently", + "used", + "fast", + "map", + "hash", + "buffer" + ], + "devDependencies": { + "ava": "^2.0.0", + "coveralls": "^3.0.3", + "nyc": "^15.0.0", + "tsd": "^0.11.0", + "xo": "^0.26.0" + } +} diff --git a/node_modules/quick-lru/readme.md b/node_modules/quick-lru/readme.md new file mode 100644 index 0000000..234294a --- /dev/null +++ b/node_modules/quick-lru/readme.md @@ -0,0 +1,111 @@ +# quick-lru [![Build Status](https://travis-ci.org/sindresorhus/quick-lru.svg?branch=master)](https://travis-ci.org/sindresorhus/quick-lru) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/quick-lru/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/quick-lru?branch=master) + +> Simple [“Least Recently Used” (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29) + +Useful when you need to cache something and limit memory usage. + +Inspired by the [`hashlru` algorithm](https://github.com/dominictarr/hashlru#algorithm), but instead uses [`Map`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map) to support keys of any type, not just strings, and values can be `undefined`. + +## Install + +``` +$ npm install quick-lru +``` + +## Usage + +```js +const QuickLRU = require('quick-lru'); + +const lru = new QuickLRU({maxSize: 1000}); + +lru.set('🦄', '🌈'); + +lru.has('🦄'); +//=> true + +lru.get('🦄'); +//=> '🌈' +``` + +## API + +### new QuickLRU(options?) + +Returns a new instance. + +### options + +Type: `object` + +#### maxSize + +*Required*\ +Type: `number` + +The maximum number of items before evicting the least recently used items. + +#### onEviction + +*Optional*\ +Type: `(key, value) => void` + +Called right before an item is evicted from the cache. + +Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`). + +### Instance + +The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop. + +Both `key` and `value` can be of any type. + +#### .set(key, value) + +Set an item. Returns the instance. + +#### .get(key) + +Get an item. + +#### .has(key) + +Check if an item exists. + +#### .peek(key) + +Get an item without marking it as recently used. + +#### .delete(key) + +Delete an item. + +Returns `true` if the item is removed or `false` if the item doesn't exist. + +#### .clear() + +Delete all items. + +#### .keys() + +Iterable for all the keys. + +#### .values() + +Iterable for all the values. + +#### .size + +The stored item count. + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/resolve-alpn/LICENSE b/node_modules/resolve-alpn/LICENSE new file mode 100644 index 0000000..f4fe9c4 --- /dev/null +++ b/node_modules/resolve-alpn/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Szymon Marczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/resolve-alpn/README.md b/node_modules/resolve-alpn/README.md new file mode 100644 index 0000000..d296f75 --- /dev/null +++ b/node_modules/resolve-alpn/README.md @@ -0,0 +1,53 @@ +# `resolve-alpn` + +[![Node CI](https://github.com/szmarczak/resolve-alpn/workflows/Node%20CI/badge.svg)](https://github.com/szmarczak/resolve-alpn/actions) +[![codecov](https://codecov.io/gh/szmarczak/resolve-alpn/branch/master/graph/badge.svg)](https://codecov.io/gh/szmarczak/resolve-alpn) + +## API + +### resolveALPN(options) + +Returns an object with an `alpnProtocol` property. The `socket` property may be also present. + +```js +const result = await resolveALPN({ + host: 'nghttp2.org', + port: 443, + ALPNProtocols: ['h2', 'http/1.1'], + servername: 'nghttp2.org' +}); + +console.log(result); // {alpnProtocol: 'h2'} +``` + +**Note:** While the `servername` option is not required in this case, many other servers do. It's best practice to set it anyway. + +**Note:** If the socket times out, the promise will resolve and `result.timeout` will be set to `true`. + +#### options + +Same as [TLS options](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback). + +##### options.resolveSocket + +By default, the socket gets destroyed and the promise resolves.
+If you set this to true, it will return the socket in a `socket` property. + +```js +const result = await resolveALPN({ + host: 'nghttp2.org', + port: 443, + ALPNProtocols: ['h2', 'http/1.1'], + servername: 'nghttp2.org', + resolveSocket: true +}); + +console.log(result); // {alpnProtocol: 'h2', socket: tls.TLSSocket} + +// Remember to destroy the socket if you don't use it! +result.socket.destroy(); +``` + +## License + +MIT diff --git a/node_modules/resolve-alpn/index.js b/node_modules/resolve-alpn/index.js new file mode 100644 index 0000000..ee6bd9a --- /dev/null +++ b/node_modules/resolve-alpn/index.js @@ -0,0 +1,33 @@ +'use strict'; +const tls = require('tls'); + +module.exports = (options = {}) => new Promise((resolve, reject) => { + let timeout = false; + + const callback = async () => { + socket.off('timeout', onTimeout); + socket.off('error', reject); + + if (options.resolveSocket) { + resolve({alpnProtocol: socket.alpnProtocol, socket, timeout}); + + if (timeout) { + await Promise.resolve(); + socket.emit('timeout'); + } + } else { + socket.destroy(); + resolve({alpnProtocol: socket.alpnProtocol, timeout}); + } + }; + + const onTimeout = async () => { + timeout = true; + callback(); + }; + + const socket = tls.connect(options, callback); + + socket.on('error', reject); + socket.once('timeout', onTimeout); +}); diff --git a/node_modules/resolve-alpn/package.json b/node_modules/resolve-alpn/package.json new file mode 100644 index 0000000..e9a6817 --- /dev/null +++ b/node_modules/resolve-alpn/package.json @@ -0,0 +1,34 @@ +{ + "name": "resolve-alpn", + "version": "1.1.2", + "description": "Detects the ALPN protocol", + "main": "index.js", + "scripts": { + "test": "xo && nyc --reporter=lcovonly --reporter=text --reporter=html ava" + }, + "files": [ + "index.js" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/szmarczak/resolve-alpn.git" + }, + "keywords": [ + "alpn", + "tls", + "socket", + "http2" + ], + "author": "Szymon Marczak", + "license": "MIT", + "bugs": { + "url": "https://github.com/szmarczak/resolve-alpn/issues" + }, + "homepage": "https://github.com/szmarczak/resolve-alpn#readme", + "devDependencies": { + "ava": "^3.15.0", + "nyc": "^15.1.0", + "pem": "1.14.3", + "xo": "^0.38.2" + } +} diff --git a/node_modules/responselike/LICENSE b/node_modules/responselike/LICENSE new file mode 100644 index 0000000..8829a00 --- /dev/null +++ b/node_modules/responselike/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 Luke Childs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/responselike/README.md b/node_modules/responselike/README.md new file mode 100644 index 0000000..6361931 --- /dev/null +++ b/node_modules/responselike/README.md @@ -0,0 +1,77 @@ +# responselike + +> A response-like object for mocking a Node.js HTTP response stream + +[![Build Status](https://travis-ci.org/lukechilds/responselike.svg?branch=master)](https://travis-ci.org/lukechilds/responselike) +[![Coverage Status](https://coveralls.io/repos/github/lukechilds/responselike/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/responselike?branch=master) +[![npm](https://img.shields.io/npm/dm/responselike.svg)](https://www.npmjs.com/package/responselike) +[![npm](https://img.shields.io/npm/v/responselike.svg)](https://www.npmjs.com/package/responselike) + +Returns a streamable response object similar to a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage). Useful for formatting cached responses so they can be consumed by code expecting a real response. + +## Install + +```shell +npm install --save responselike +``` + +Or if you're just using for testing you'll want: + +```shell +npm install --save-dev responselike +``` + +## Usage + +```js +const Response = require('responselike'); + +const response = new Response(200, { foo: 'bar' }, Buffer.from('Hi!'), 'https://example.com'); + +response.statusCode; +// 200 +response.headers; +// { foo: 'bar' } +response.body; +// +response.url; +// 'https://example.com' + +response.pipe(process.stdout); +// Hi! +``` + + +## API + +### new Response(statusCode, headers, body, url) + +Returns a streamable response object similar to a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage). + +#### statusCode + +Type: `number` + +HTTP response status code. + +#### headers + +Type: `object` + +HTTP headers object. Keys will be automatically lowercased. + +#### body + +Type: `buffer` + +A Buffer containing the response body. The Buffer contents will be streamable but is also exposed directly as `response.body`. + +#### url + +Type: `string` + +Request URL string. + +## License + +MIT © Luke Childs diff --git a/node_modules/responselike/package.json b/node_modules/responselike/package.json new file mode 100644 index 0000000..e3d44ae --- /dev/null +++ b/node_modules/responselike/package.json @@ -0,0 +1,38 @@ +{ + "name": "responselike", + "version": "2.0.0", + "description": "A response-like object for mocking a Node.js HTTP response stream", + "main": "src/index.js", + "scripts": { + "test": "xo && nyc ava", + "coverage": "nyc report --reporter=text-lcov | coveralls" + }, + "xo": { + "extends": "xo-lukechilds" + }, + "keywords": [ + "http", + "https", + "response", + "mock", + "request", + "responselike" + ], + "repository": { + "type": "git", + "url": "https://github.com/lukechilds/responselike.git" + }, + "author": "lukechilds", + "license": "MIT", + "devDependencies": { + "ava": "^0.25.0", + "coveralls": "^3.0.0", + "eslint-config-xo-lukechilds": "^1.0.0", + "get-stream": "^3.0.0", + "nyc": "^11.8.0", + "xo": "^0.19.0" + }, + "dependencies": { + "lowercase-keys": "^2.0.0" + } +} diff --git a/node_modules/responselike/src/index.js b/node_modules/responselike/src/index.js new file mode 100644 index 0000000..b17b481 --- /dev/null +++ b/node_modules/responselike/src/index.js @@ -0,0 +1,34 @@ +'use strict'; + +const Readable = require('stream').Readable; +const lowercaseKeys = require('lowercase-keys'); + +class Response extends Readable { + constructor(statusCode, headers, body, url) { + if (typeof statusCode !== 'number') { + throw new TypeError('Argument `statusCode` should be a number'); + } + if (typeof headers !== 'object') { + throw new TypeError('Argument `headers` should be an object'); + } + if (!(body instanceof Buffer)) { + throw new TypeError('Argument `body` should be a buffer'); + } + if (typeof url !== 'string') { + throw new TypeError('Argument `url` should be a string'); + } + + super(); + this.statusCode = statusCode; + this.headers = lowercaseKeys(headers); + this.body = body; + this.url = url; + } + + _read() { + this.push(this.body); + this.push(null); + } +} + +module.exports = Response; diff --git a/node_modules/setimmediate/LICENSE.txt b/node_modules/setimmediate/LICENSE.txt new file mode 100644 index 0000000..32b20de --- /dev/null +++ b/node_modules/setimmediate/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/setimmediate/package.json b/node_modules/setimmediate/package.json new file mode 100644 index 0000000..9b211e4 --- /dev/null +++ b/node_modules/setimmediate/package.json @@ -0,0 +1,30 @@ +{ + "name": "setimmediate", + "description": "A shim for the setImmediate efficient script yielding API", + "version": "1.0.5", + "author": "YuzuJS", + "contributors": [ + "Domenic Denicola (https://domenic.me)", + "Donavon West (http://donavon.com)", + "Yaffle" + ], + "license": "MIT", + "repository": "YuzuJS/setImmediate", + "main": "setImmediate.js", + "files": [ + "setImmediate.js" + ], + "scripts": { + "lint": "jshint setImmediate.js", + "test": "mocha test/tests.js", + "test-browser": "opener http://localhost:9008/__zuul && zuul test/tests.js --ui mocha-bdd --local 9008", + "test-browser-only": "opener http://localhost:9007/test/browserOnly/index.html && http-server . -p 9007" + }, + "devDependencies": { + "jshint": "^2.5.0", + "mocha": "~1.18.2", + "http-server": "~0.6.1", + "opener": "^1.3", + "zuul": "^1.6.4" + } +} diff --git a/node_modules/setimmediate/setImmediate.js b/node_modules/setimmediate/setImmediate.js new file mode 100644 index 0000000..3c1b06e --- /dev/null +++ b/node_modules/setimmediate/setImmediate.js @@ -0,0 +1,186 @@ +(function (global, undefined) { + "use strict"; + + if (global.setImmediate) { + return; + } + + var nextHandle = 1; // Spec says greater than zero + var tasksByHandle = {}; + var currentlyRunningATask = false; + var doc = global.document; + var registerImmediate; + + function setImmediate(callback) { + // Callback can either be a function or a string + if (typeof callback !== "function") { + callback = new Function("" + callback); + } + // Copy function arguments + var args = new Array(arguments.length - 1); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i + 1]; + } + // Store and register the task + var task = { callback: callback, args: args }; + tasksByHandle[nextHandle] = task; + registerImmediate(nextHandle); + return nextHandle++; + } + + function clearImmediate(handle) { + delete tasksByHandle[handle]; + } + + function run(task) { + var callback = task.callback; + var args = task.args; + switch (args.length) { + case 0: + callback(); + break; + case 1: + callback(args[0]); + break; + case 2: + callback(args[0], args[1]); + break; + case 3: + callback(args[0], args[1], args[2]); + break; + default: + callback.apply(undefined, args); + break; + } + } + + function runIfPresent(handle) { + // From the spec: "Wait until any invocations of this algorithm started before this one have completed." + // So if we're currently running a task, we'll need to delay this invocation. + if (currentlyRunningATask) { + // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a + // "too much recursion" error. + setTimeout(runIfPresent, 0, handle); + } else { + var task = tasksByHandle[handle]; + if (task) { + currentlyRunningATask = true; + try { + run(task); + } finally { + clearImmediate(handle); + currentlyRunningATask = false; + } + } + } + } + + function installNextTickImplementation() { + registerImmediate = function(handle) { + process.nextTick(function () { runIfPresent(handle); }); + }; + } + + function canUsePostMessage() { + // The test against `importScripts` prevents this implementation from being installed inside a web worker, + // where `global.postMessage` means something completely different and can't be used for this purpose. + if (global.postMessage && !global.importScripts) { + var postMessageIsAsynchronous = true; + var oldOnMessage = global.onmessage; + global.onmessage = function() { + postMessageIsAsynchronous = false; + }; + global.postMessage("", "*"); + global.onmessage = oldOnMessage; + return postMessageIsAsynchronous; + } + } + + function installPostMessageImplementation() { + // Installs an event handler on `global` for the `message` event: see + // * https://developer.mozilla.org/en/DOM/window.postMessage + // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages + + var messagePrefix = "setImmediate$" + Math.random() + "$"; + var onGlobalMessage = function(event) { + if (event.source === global && + typeof event.data === "string" && + event.data.indexOf(messagePrefix) === 0) { + runIfPresent(+event.data.slice(messagePrefix.length)); + } + }; + + if (global.addEventListener) { + global.addEventListener("message", onGlobalMessage, false); + } else { + global.attachEvent("onmessage", onGlobalMessage); + } + + registerImmediate = function(handle) { + global.postMessage(messagePrefix + handle, "*"); + }; + } + + function installMessageChannelImplementation() { + var channel = new MessageChannel(); + channel.port1.onmessage = function(event) { + var handle = event.data; + runIfPresent(handle); + }; + + registerImmediate = function(handle) { + channel.port2.postMessage(handle); + }; + } + + function installReadyStateChangeImplementation() { + var html = doc.documentElement; + registerImmediate = function(handle) { + // Create a + + + or + + var nacl = require('tweetnacl'); + nacl.util = require('tweetnacl-util'); + + However it is recommended to use better packages that have wider + compatibility and better performance. Functions from `nacl.util` were never + intended to be robust solution for string conversion and were included for + convenience: cryptography library is not the right place for them. + + Currently calling these functions will throw error pointing to + `tweetnacl-util-js` (in the next version this error message will be removed). + +* Improved detection of available random number generators, making it possible + to use `nacl.randomBytes` and related functions in Web Workers without + changes. + +* Changes to testing (see README). + + +v0.13.3 +------- + +No code changes. + +* Reverted license field in package.json to "Public domain". + +* Fixed typo in README. + + +v0.13.2 +------- + +* Fixed undefined variable bug in fast version of Poly1305. No worries, this + bug was *never* triggered. + +* Specified CC0 public domain dedication. + +* Updated development dependencies. + + +v0.13.1 +------- + +* Exclude `crypto` and `buffer` modules from browserify builds. + + +v0.13.0 +------- + +* Made `nacl-fast` the default version in NPM package. Now + `require("tweetnacl")` will use fast version; to get the original version, + use `require("tweetnacl/nacl.js")`. + +* Cleanup temporary array after generating random bytes. + + +v0.12.2 +------- + +* Improved performance of curve operations, making `nacl.scalarMult`, `nacl.box`, + `nacl.sign` and related functions up to 3x faster in `nacl-fast` version. + + +v0.12.1 +------- + +* Significantly improved performance of Salsa20 (~1.5x faster) and + Poly1305 (~3.5x faster) in `nacl-fast` version. + + +v0.12.0 +------- + +* Instead of using the given secret key directly, TweetNaCl.js now copies it to + a new array in `nacl.box.keyPair.fromSecretKey` and + `nacl.sign.keyPair.fromSecretKey`. + + +v0.11.2 +------- + +* Added new constant: `nacl.sign.seedLength`. + + +v0.11.1 +------- + +* Even faster hash for both short and long inputs (in `nacl-fast`). + + +v0.11.0 +------- + +* Implement `nacl.sign.keyPair.fromSeed` to enable creation of sign key pairs + deterministically from a 32-byte seed. (It behaves like + [libsodium's](http://doc.libsodium.org/public-key_cryptography/public-key_signatures.html) + `crypto_sign_seed_keypair`: the seed becomes a secret part of the secret key.) + +* Fast version now has an improved hash implementation that is 2x-5x faster. + +* Fixed benchmarks, which may have produced incorrect measurements. + + +v0.10.1 +------- + +* Exported undocumented `nacl.lowlevel.crypto_core_hsalsa20`. + + +v0.10.0 +------- + +* **Signature API breaking change!** `nacl.sign` and `nacl.sign.open` now deal + with signed messages, and new `nacl.sign.detached` and + `nacl.sign.detached.verify` are available. + + Previously, `nacl.sign` returned a signature, and `nacl.sign.open` accepted a + message and "detached" signature. This was unlike NaCl's API, which dealt with + signed messages (concatenation of signature and message). + + The new API is: + + nacl.sign(message, secretKey) -> signedMessage + nacl.sign.open(signedMessage, publicKey) -> message | null + + Since detached signatures are common, two new API functions were introduced: + + nacl.sign.detached(message, secretKey) -> signature + nacl.sign.detached.verify(message, signature, publicKey) -> true | false + + (Note that it's `verify`, not `open`, and it returns a boolean value, unlike + `open`, which returns an "unsigned" message.) + +* NPM package now comes without `test` directory to keep it small. + + +v0.9.2 +------ + +* Improved documentation. +* Fast version: increased theoretical message size limit from 2^32-1 to 2^52 + bytes in Poly1305 (and thus, secretbox and box). However this has no impact + in practice since JavaScript arrays or ArrayBuffers are limited to 32-bit + indexes, and most implementations won't allocate more than a gigabyte or so. + (Obviously, there are no tests for the correctness of implementation.) Also, + it's not recommended to use messages that large without splitting them into + smaller packets anyway. + + +v0.9.1 +------ + +* Initial release diff --git a/node_modules/tweetnacl/LICENSE b/node_modules/tweetnacl/LICENSE new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/node_modules/tweetnacl/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md b/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..a8eb4a9 --- /dev/null +++ b/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +# Important! + +If your contribution is not trivial (not a typo fix, etc.), we can only accept +it if you dedicate your copyright for the contribution to the public domain. +Make sure you understand what it means (see http://unlicense.org/)! If you +agree, please add yourself to AUTHORS.md file, and include the following text +to your pull request description or a comment in it: + +------------------------------------------------------------------------------ + + I dedicate any and all copyright interest in this software to the + public domain. I make this dedication for the benefit of the public at + large and to the detriment of my heirs and successors. I intend this + dedication to be an overt act of relinquishment in perpetuity of all + present and future rights to this software under copyright law. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. diff --git a/node_modules/tweetnacl/README.md b/node_modules/tweetnacl/README.md new file mode 100644 index 0000000..022bf6b --- /dev/null +++ b/node_modules/tweetnacl/README.md @@ -0,0 +1,494 @@ +TweetNaCl.js +============ + +Port of [TweetNaCl](http://tweetnacl.cr.yp.to) / [NaCl](http://nacl.cr.yp.to/) +to JavaScript for modern browsers and Node.js. Public domain. + +[![Build Status](https://travis-ci.org/dchest/tweetnacl-js.svg?branch=master) +](https://travis-ci.org/dchest/tweetnacl-js) + +Demo: + +Documentation +============= + +* [Overview](#overview) +* [Audits](#audits) +* [Installation](#installation) +* [Examples](#examples) +* [Usage](#usage) + * [Public-key authenticated encryption (box)](#public-key-authenticated-encryption-box) + * [Secret-key authenticated encryption (secretbox)](#secret-key-authenticated-encryption-secretbox) + * [Scalar multiplication](#scalar-multiplication) + * [Signatures](#signatures) + * [Hashing](#hashing) + * [Random bytes generation](#random-bytes-generation) + * [Constant-time comparison](#constant-time-comparison) +* [System requirements](#system-requirements) +* [Development and testing](#development-and-testing) +* [Benchmarks](#benchmarks) +* [Contributors](#contributors) +* [Who uses it](#who-uses-it) + + +Overview +-------- + +The primary goal of this project is to produce a translation of TweetNaCl to +JavaScript which is as close as possible to the original C implementation, plus +a thin layer of idiomatic high-level API on top of it. + +There are two versions, you can use either of them: + +* `nacl.js` is the port of TweetNaCl with minimum differences from the + original + high-level API. + +* `nacl-fast.js` is like `nacl.js`, but with some functions replaced with + faster versions. (Used by default when importing NPM package.) + + +Audits +------ + +TweetNaCl.js has been audited by [Cure53](https://cure53.de/) in January-February +2017 (audit was sponsored by [Deletype](https://deletype.com)): + +> The overall outcome of this audit signals a particularly positive assessment +> for TweetNaCl-js, as the testing team was unable to find any security +> problems in the library. It has to be noted that this is an exceptionally +> rare result of a source code audit for any project and must be seen as a true +> testament to a development proceeding with security at its core. +> +> To reiterate, the TweetNaCl-js project, the source code was found to be +> bug-free at this point. +> +> [...] +> +> In sum, the testing team is happy to recommend the TweetNaCl-js project as +> likely one of the safer and more secure cryptographic tools among its +> competition. + +[Read full audit report](https://cure53.de/tweetnacl.pdf) + + +Installation +------------ + +You can install TweetNaCl.js via a package manager: + +[Yarn](https://yarnpkg.com/): + + $ yarn add tweetnacl + +[NPM](https://www.npmjs.org/): + + $ npm install tweetnacl + +or [download source code](https://github.com/dchest/tweetnacl-js/releases). + + +Examples +-------- +You can find usage examples in our [wiki](https://github.com/dchest/tweetnacl-js/wiki/Examples). + + +Usage +----- + +All API functions accept and return bytes as `Uint8Array`s. If you need to +encode or decode strings, use functions from + or one of the more robust codec +packages. + +In Node.js v4 and later `Buffer` objects are backed by `Uint8Array`s, so you +can freely pass them to TweetNaCl.js functions as arguments. The returned +objects are still `Uint8Array`s, so if you need `Buffer`s, you'll have to +convert them manually; make sure to convert using copying: `Buffer.from(array)` +(or `new Buffer(array)` in Node.js v4 or earlier), instead of sharing: +`Buffer.from(array.buffer)` (or `new Buffer(array.buffer)` Node 4 or earlier), +because some functions return subarrays of their buffers. + + +### Public-key authenticated encryption (box) + +Implements *x25519-xsalsa20-poly1305*. + +#### nacl.box.keyPair() + +Generates a new random key pair for box and returns it as an object with +`publicKey` and `secretKey` members: + + { + publicKey: ..., // Uint8Array with 32-byte public key + secretKey: ... // Uint8Array with 32-byte secret key + } + + +#### nacl.box.keyPair.fromSecretKey(secretKey) + +Returns a key pair for box with public key corresponding to the given secret +key. + +#### nacl.box(message, nonce, theirPublicKey, mySecretKey) + +Encrypts and authenticates message using peer's public key, our secret key, and +the given nonce, which must be unique for each distinct message for a key pair. + +Returns an encrypted and authenticated message, which is +`nacl.box.overheadLength` longer than the original message. + +#### nacl.box.open(box, nonce, theirPublicKey, mySecretKey) + +Authenticates and decrypts the given box with peer's public key, our secret +key, and the given nonce. + +Returns the original message, or `null` if authentication fails. + +#### nacl.box.before(theirPublicKey, mySecretKey) + +Returns a precomputed shared key which can be used in `nacl.box.after` and +`nacl.box.open.after`. + +#### nacl.box.after(message, nonce, sharedKey) + +Same as `nacl.box`, but uses a shared key precomputed with `nacl.box.before`. + +#### nacl.box.open.after(box, nonce, sharedKey) + +Same as `nacl.box.open`, but uses a shared key precomputed with `nacl.box.before`. + +#### Constants + +##### nacl.box.publicKeyLength = 32 + +Length of public key in bytes. + +##### nacl.box.secretKeyLength = 32 + +Length of secret key in bytes. + +##### nacl.box.sharedKeyLength = 32 + +Length of precomputed shared key in bytes. + +##### nacl.box.nonceLength = 24 + +Length of nonce in bytes. + +##### nacl.box.overheadLength = 16 + +Length of overhead added to box compared to original message. + + +### Secret-key authenticated encryption (secretbox) + +Implements *xsalsa20-poly1305*. + +#### nacl.secretbox(message, nonce, key) + +Encrypts and authenticates message using the key and the nonce. The nonce must +be unique for each distinct message for this key. + +Returns an encrypted and authenticated message, which is +`nacl.secretbox.overheadLength` longer than the original message. + +#### nacl.secretbox.open(box, nonce, key) + +Authenticates and decrypts the given secret box using the key and the nonce. + +Returns the original message, or `null` if authentication fails. + +#### Constants + +##### nacl.secretbox.keyLength = 32 + +Length of key in bytes. + +##### nacl.secretbox.nonceLength = 24 + +Length of nonce in bytes. + +##### nacl.secretbox.overheadLength = 16 + +Length of overhead added to secret box compared to original message. + + +### Scalar multiplication + +Implements *x25519*. + +#### nacl.scalarMult(n, p) + +Multiplies an integer `n` by a group element `p` and returns the resulting +group element. + +#### nacl.scalarMult.base(n) + +Multiplies an integer `n` by a standard group element and returns the resulting +group element. + +#### Constants + +##### nacl.scalarMult.scalarLength = 32 + +Length of scalar in bytes. + +##### nacl.scalarMult.groupElementLength = 32 + +Length of group element in bytes. + + +### Signatures + +Implements [ed25519](http://ed25519.cr.yp.to). + +#### nacl.sign.keyPair() + +Generates new random key pair for signing and returns it as an object with +`publicKey` and `secretKey` members: + + { + publicKey: ..., // Uint8Array with 32-byte public key + secretKey: ... // Uint8Array with 64-byte secret key + } + +#### nacl.sign.keyPair.fromSecretKey(secretKey) + +Returns a signing key pair with public key corresponding to the given +64-byte secret key. The secret key must have been generated by +`nacl.sign.keyPair` or `nacl.sign.keyPair.fromSeed`. + +#### nacl.sign.keyPair.fromSeed(seed) + +Returns a new signing key pair generated deterministically from a 32-byte seed. +The seed must contain enough entropy to be secure. This method is not +recommended for general use: instead, use `nacl.sign.keyPair` to generate a new +key pair from a random seed. + +#### nacl.sign(message, secretKey) + +Signs the message using the secret key and returns a signed message. + +#### nacl.sign.open(signedMessage, publicKey) + +Verifies the signed message and returns the message without signature. + +Returns `null` if verification failed. + +#### nacl.sign.detached(message, secretKey) + +Signs the message using the secret key and returns a signature. + +#### nacl.sign.detached.verify(message, signature, publicKey) + +Verifies the signature for the message and returns `true` if verification +succeeded or `false` if it failed. + +#### Constants + +##### nacl.sign.publicKeyLength = 32 + +Length of signing public key in bytes. + +##### nacl.sign.secretKeyLength = 64 + +Length of signing secret key in bytes. + +##### nacl.sign.seedLength = 32 + +Length of seed for `nacl.sign.keyPair.fromSeed` in bytes. + +##### nacl.sign.signatureLength = 64 + +Length of signature in bytes. + + +### Hashing + +Implements *SHA-512*. + +#### nacl.hash(message) + +Returns SHA-512 hash of the message. + +#### Constants + +##### nacl.hash.hashLength = 64 + +Length of hash in bytes. + + +### Random bytes generation + +#### nacl.randomBytes(length) + +Returns a `Uint8Array` of the given length containing random bytes of +cryptographic quality. + +**Implementation note** + +TweetNaCl.js uses the following methods to generate random bytes, +depending on the platform it runs on: + +* `window.crypto.getRandomValues` (WebCrypto standard) +* `window.msCrypto.getRandomValues` (Internet Explorer 11) +* `crypto.randomBytes` (Node.js) + +If the platform doesn't provide a suitable PRNG, the following functions, +which require random numbers, will throw exception: + +* `nacl.randomBytes` +* `nacl.box.keyPair` +* `nacl.sign.keyPair` + +Other functions are deterministic and will continue working. + +If a platform you are targeting doesn't implement secure random number +generator, but you somehow have a cryptographically-strong source of entropy +(not `Math.random`!), and you know what you are doing, you can plug it into +TweetNaCl.js like this: + + nacl.setPRNG(function(x, n) { + // ... copy n random bytes into x ... + }); + +Note that `nacl.setPRNG` *completely replaces* internal random byte generator +with the one provided. + + +### Constant-time comparison + +#### nacl.verify(x, y) + +Compares `x` and `y` in constant time and returns `true` if their lengths are +non-zero and equal, and their contents are equal. + +Returns `false` if either of the arguments has zero length, or arguments have +different lengths, or their contents differ. + + +System requirements +------------------- + +TweetNaCl.js supports modern browsers that have a cryptographically secure +pseudorandom number generator and typed arrays, including the latest versions +of: + +* Chrome +* Firefox +* Safari (Mac, iOS) +* Internet Explorer 11 + +Other systems: + +* Node.js + + +Development and testing +------------------------ + +Install NPM modules needed for development: + + $ npm install + +To build minified versions: + + $ npm run build + +Tests use minified version, so make sure to rebuild it every time you change +`nacl.js` or `nacl-fast.js`. + +### Testing + +To run tests in Node.js: + + $ npm run test-node + +By default all tests described here work on `nacl.min.js`. To test other +versions, set environment variable `NACL_SRC` to the file name you want to test. +For example, the following command will test fast minified version: + + $ NACL_SRC=nacl-fast.min.js npm run test-node + +To run full suite of tests in Node.js, including comparing outputs of +JavaScript port to outputs of the original C version: + + $ npm run test-node-all + +To prepare tests for browsers: + + $ npm run build-test-browser + +and then open `test/browser/test.html` (or `test/browser/test-fast.html`) to +run them. + +To run tests in both Node and Electron: + + $ npm test + +### Benchmarking + +To run benchmarks in Node.js: + + $ npm run bench + $ NACL_SRC=nacl-fast.min.js npm run bench + +To run benchmarks in a browser, open `test/benchmark/bench.html` (or +`test/benchmark/bench-fast.html`). + + +Benchmarks +---------- + +For reference, here are benchmarks from MacBook Pro (Retina, 13-inch, Mid 2014) +laptop with 2.6 GHz Intel Core i5 CPU (Intel) in Chrome 53/OS X and Xiaomi Redmi +Note 3 smartphone with 1.8 GHz Qualcomm Snapdragon 650 64-bit CPU (ARM) in +Chrome 52/Android: + +| | nacl.js Intel | nacl-fast.js Intel | nacl.js ARM | nacl-fast.js ARM | +| ------------- |:-------------:|:-------------------:|:-------------:|:-----------------:| +| salsa20 | 1.3 MB/s | 128 MB/s | 0.4 MB/s | 43 MB/s | +| poly1305 | 13 MB/s | 171 MB/s | 4 MB/s | 52 MB/s | +| hash | 4 MB/s | 34 MB/s | 0.9 MB/s | 12 MB/s | +| secretbox 1K | 1113 op/s | 57583 op/s | 334 op/s | 14227 op/s | +| box 1K | 145 op/s | 718 op/s | 37 op/s | 368 op/s | +| scalarMult | 171 op/s | 733 op/s | 56 op/s | 380 op/s | +| sign | 77 op/s | 200 op/s | 20 op/s | 61 op/s | +| sign.open | 39 op/s | 102 op/s | 11 op/s | 31 op/s | + +(You can run benchmarks on your devices by clicking on the links at the bottom +of the [home page](https://tweetnacl.js.org)). + +In short, with *nacl-fast.js* and 1024-byte messages you can expect to encrypt and +authenticate more than 57000 messages per second on a typical laptop or more than +14000 messages per second on a $170 smartphone, sign about 200 and verify 100 +messages per second on a laptop or 60 and 30 messages per second on a smartphone, +per CPU core (with Web Workers you can do these operations in parallel), +which is good enough for most applications. + + +Contributors +------------ + +See AUTHORS.md file. + + +Third-party libraries based on TweetNaCl.js +------------------------------------------- + +* [forward-secrecy](https://github.com/alax/forward-secrecy) — Axolotl ratchet implementation +* [nacl-stream](https://github.com/dchest/nacl-stream-js) - streaming encryption +* [tweetnacl-auth-js](https://github.com/dchest/tweetnacl-auth-js) — implementation of [`crypto_auth`](http://nacl.cr.yp.to/auth.html) +* [tweetnacl-sealed-box](https://github.com/whs/tweetnacl-sealed-box) — implementation of [`sealed boxes`](https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html) +* [chloride](https://github.com/dominictarr/chloride) - unified API for various NaCl modules + + +Who uses it +----------- + +Some notable users of TweetNaCl.js: + +* [GitHub](https://github.com) +* [MEGA](https://github.com/meganz/webclient) +* [Stellar](https://www.stellar.org/) +* [miniLock](https://github.com/kaepora/miniLock) diff --git a/node_modules/tweetnacl/nacl-fast.js b/node_modules/tweetnacl/nacl-fast.js new file mode 100644 index 0000000..7ea5fb5 --- /dev/null +++ b/node_modules/tweetnacl/nacl-fast.js @@ -0,0 +1,2391 @@ +(function(nacl) { +'use strict'; + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _0 = new Uint8Array(16); +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function ts64(x, i, h, l) { + x[i] = (h >> 24) & 0xff; + x[i+1] = (h >> 16) & 0xff; + x[i+2] = (h >> 8) & 0xff; + x[i+3] = h & 0xff; + x[i+4] = (l >> 24) & 0xff; + x[i+5] = (l >> 16) & 0xff; + x[i+6] = (l >> 8) & 0xff; + x[i+7] = l & 0xff; +} + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_16(x, xi, y, yi) { + return vn(x,xi,y,yi,16); +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function core_salsa20(o, p, k, c) { + var j0 = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24, + j1 = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24, + j2 = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24, + j3 = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24, + j4 = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24, + j5 = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24, + j6 = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24, + j7 = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24, + j8 = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24, + j9 = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24, + j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24, + j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24, + j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24, + j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24, + j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24, + j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24; + + var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, + x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, + x15 = j15, u; + + for (var i = 0; i < 20; i += 2) { + u = x0 + x12 | 0; + x4 ^= u<<7 | u>>>(32-7); + u = x4 + x0 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x4 | 0; + x12 ^= u<<13 | u>>>(32-13); + u = x12 + x8 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x1 | 0; + x9 ^= u<<7 | u>>>(32-7); + u = x9 + x5 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x9 | 0; + x1 ^= u<<13 | u>>>(32-13); + u = x1 + x13 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x6 | 0; + x14 ^= u<<7 | u>>>(32-7); + u = x14 + x10 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x14 | 0; + x6 ^= u<<13 | u>>>(32-13); + u = x6 + x2 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x11 | 0; + x3 ^= u<<7 | u>>>(32-7); + u = x3 + x15 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x3 | 0; + x11 ^= u<<13 | u>>>(32-13); + u = x11 + x7 | 0; + x15 ^= u<<18 | u>>>(32-18); + + u = x0 + x3 | 0; + x1 ^= u<<7 | u>>>(32-7); + u = x1 + x0 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x1 | 0; + x3 ^= u<<13 | u>>>(32-13); + u = x3 + x2 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x4 | 0; + x6 ^= u<<7 | u>>>(32-7); + u = x6 + x5 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x6 | 0; + x4 ^= u<<13 | u>>>(32-13); + u = x4 + x7 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x9 | 0; + x11 ^= u<<7 | u>>>(32-7); + u = x11 + x10 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x11 | 0; + x9 ^= u<<13 | u>>>(32-13); + u = x9 + x8 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x14 | 0; + x12 ^= u<<7 | u>>>(32-7); + u = x12 + x15 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x12 | 0; + x14 ^= u<<13 | u>>>(32-13); + u = x14 + x13 | 0; + x15 ^= u<<18 | u>>>(32-18); + } + x0 = x0 + j0 | 0; + x1 = x1 + j1 | 0; + x2 = x2 + j2 | 0; + x3 = x3 + j3 | 0; + x4 = x4 + j4 | 0; + x5 = x5 + j5 | 0; + x6 = x6 + j6 | 0; + x7 = x7 + j7 | 0; + x8 = x8 + j8 | 0; + x9 = x9 + j9 | 0; + x10 = x10 + j10 | 0; + x11 = x11 + j11 | 0; + x12 = x12 + j12 | 0; + x13 = x13 + j13 | 0; + x14 = x14 + j14 | 0; + x15 = x15 + j15 | 0; + + o[ 0] = x0 >>> 0 & 0xff; + o[ 1] = x0 >>> 8 & 0xff; + o[ 2] = x0 >>> 16 & 0xff; + o[ 3] = x0 >>> 24 & 0xff; + + o[ 4] = x1 >>> 0 & 0xff; + o[ 5] = x1 >>> 8 & 0xff; + o[ 6] = x1 >>> 16 & 0xff; + o[ 7] = x1 >>> 24 & 0xff; + + o[ 8] = x2 >>> 0 & 0xff; + o[ 9] = x2 >>> 8 & 0xff; + o[10] = x2 >>> 16 & 0xff; + o[11] = x2 >>> 24 & 0xff; + + o[12] = x3 >>> 0 & 0xff; + o[13] = x3 >>> 8 & 0xff; + o[14] = x3 >>> 16 & 0xff; + o[15] = x3 >>> 24 & 0xff; + + o[16] = x4 >>> 0 & 0xff; + o[17] = x4 >>> 8 & 0xff; + o[18] = x4 >>> 16 & 0xff; + o[19] = x4 >>> 24 & 0xff; + + o[20] = x5 >>> 0 & 0xff; + o[21] = x5 >>> 8 & 0xff; + o[22] = x5 >>> 16 & 0xff; + o[23] = x5 >>> 24 & 0xff; + + o[24] = x6 >>> 0 & 0xff; + o[25] = x6 >>> 8 & 0xff; + o[26] = x6 >>> 16 & 0xff; + o[27] = x6 >>> 24 & 0xff; + + o[28] = x7 >>> 0 & 0xff; + o[29] = x7 >>> 8 & 0xff; + o[30] = x7 >>> 16 & 0xff; + o[31] = x7 >>> 24 & 0xff; + + o[32] = x8 >>> 0 & 0xff; + o[33] = x8 >>> 8 & 0xff; + o[34] = x8 >>> 16 & 0xff; + o[35] = x8 >>> 24 & 0xff; + + o[36] = x9 >>> 0 & 0xff; + o[37] = x9 >>> 8 & 0xff; + o[38] = x9 >>> 16 & 0xff; + o[39] = x9 >>> 24 & 0xff; + + o[40] = x10 >>> 0 & 0xff; + o[41] = x10 >>> 8 & 0xff; + o[42] = x10 >>> 16 & 0xff; + o[43] = x10 >>> 24 & 0xff; + + o[44] = x11 >>> 0 & 0xff; + o[45] = x11 >>> 8 & 0xff; + o[46] = x11 >>> 16 & 0xff; + o[47] = x11 >>> 24 & 0xff; + + o[48] = x12 >>> 0 & 0xff; + o[49] = x12 >>> 8 & 0xff; + o[50] = x12 >>> 16 & 0xff; + o[51] = x12 >>> 24 & 0xff; + + o[52] = x13 >>> 0 & 0xff; + o[53] = x13 >>> 8 & 0xff; + o[54] = x13 >>> 16 & 0xff; + o[55] = x13 >>> 24 & 0xff; + + o[56] = x14 >>> 0 & 0xff; + o[57] = x14 >>> 8 & 0xff; + o[58] = x14 >>> 16 & 0xff; + o[59] = x14 >>> 24 & 0xff; + + o[60] = x15 >>> 0 & 0xff; + o[61] = x15 >>> 8 & 0xff; + o[62] = x15 >>> 16 & 0xff; + o[63] = x15 >>> 24 & 0xff; +} + +function core_hsalsa20(o,p,k,c) { + var j0 = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24, + j1 = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24, + j2 = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24, + j3 = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24, + j4 = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24, + j5 = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24, + j6 = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24, + j7 = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24, + j8 = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24, + j9 = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24, + j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24, + j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24, + j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24, + j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24, + j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24, + j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24; + + var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, + x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, + x15 = j15, u; + + for (var i = 0; i < 20; i += 2) { + u = x0 + x12 | 0; + x4 ^= u<<7 | u>>>(32-7); + u = x4 + x0 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x4 | 0; + x12 ^= u<<13 | u>>>(32-13); + u = x12 + x8 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x1 | 0; + x9 ^= u<<7 | u>>>(32-7); + u = x9 + x5 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x9 | 0; + x1 ^= u<<13 | u>>>(32-13); + u = x1 + x13 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x6 | 0; + x14 ^= u<<7 | u>>>(32-7); + u = x14 + x10 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x14 | 0; + x6 ^= u<<13 | u>>>(32-13); + u = x6 + x2 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x11 | 0; + x3 ^= u<<7 | u>>>(32-7); + u = x3 + x15 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x3 | 0; + x11 ^= u<<13 | u>>>(32-13); + u = x11 + x7 | 0; + x15 ^= u<<18 | u>>>(32-18); + + u = x0 + x3 | 0; + x1 ^= u<<7 | u>>>(32-7); + u = x1 + x0 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x1 | 0; + x3 ^= u<<13 | u>>>(32-13); + u = x3 + x2 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x4 | 0; + x6 ^= u<<7 | u>>>(32-7); + u = x6 + x5 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x6 | 0; + x4 ^= u<<13 | u>>>(32-13); + u = x4 + x7 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x9 | 0; + x11 ^= u<<7 | u>>>(32-7); + u = x11 + x10 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x11 | 0; + x9 ^= u<<13 | u>>>(32-13); + u = x9 + x8 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x14 | 0; + x12 ^= u<<7 | u>>>(32-7); + u = x12 + x15 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x12 | 0; + x14 ^= u<<13 | u>>>(32-13); + u = x14 + x13 | 0; + x15 ^= u<<18 | u>>>(32-18); + } + + o[ 0] = x0 >>> 0 & 0xff; + o[ 1] = x0 >>> 8 & 0xff; + o[ 2] = x0 >>> 16 & 0xff; + o[ 3] = x0 >>> 24 & 0xff; + + o[ 4] = x5 >>> 0 & 0xff; + o[ 5] = x5 >>> 8 & 0xff; + o[ 6] = x5 >>> 16 & 0xff; + o[ 7] = x5 >>> 24 & 0xff; + + o[ 8] = x10 >>> 0 & 0xff; + o[ 9] = x10 >>> 8 & 0xff; + o[10] = x10 >>> 16 & 0xff; + o[11] = x10 >>> 24 & 0xff; + + o[12] = x15 >>> 0 & 0xff; + o[13] = x15 >>> 8 & 0xff; + o[14] = x15 >>> 16 & 0xff; + o[15] = x15 >>> 24 & 0xff; + + o[16] = x6 >>> 0 & 0xff; + o[17] = x6 >>> 8 & 0xff; + o[18] = x6 >>> 16 & 0xff; + o[19] = x6 >>> 24 & 0xff; + + o[20] = x7 >>> 0 & 0xff; + o[21] = x7 >>> 8 & 0xff; + o[22] = x7 >>> 16 & 0xff; + o[23] = x7 >>> 24 & 0xff; + + o[24] = x8 >>> 0 & 0xff; + o[25] = x8 >>> 8 & 0xff; + o[26] = x8 >>> 16 & 0xff; + o[27] = x8 >>> 24 & 0xff; + + o[28] = x9 >>> 0 & 0xff; + o[29] = x9 >>> 8 & 0xff; + o[30] = x9 >>> 16 & 0xff; + o[31] = x9 >>> 24 & 0xff; +} + +function crypto_core_salsa20(out,inp,k,c) { + core_salsa20(out,inp,k,c); +} + +function crypto_core_hsalsa20(out,inp,k,c) { + core_hsalsa20(out,inp,k,c); +} + +var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); + // "expand 32-byte k" + +function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + mpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + } + return 0; +} + +function crypto_stream_salsa20(c,cpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = x[i]; + } + return 0; +} + +function crypto_stream(c,cpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + var sn = new Uint8Array(8); + for (var i = 0; i < 8; i++) sn[i] = n[i+16]; + return crypto_stream_salsa20(c,cpos,d,sn,s); +} + +function crypto_stream_xor(c,cpos,m,mpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + var sn = new Uint8Array(8); + for (var i = 0; i < 8; i++) sn[i] = n[i+16]; + return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,sn,s); +} + +/* +* Port of Andrew Moon's Poly1305-donna-16. Public domain. +* https://github.com/floodyberry/poly1305-donna +*/ + +var poly1305 = function(key) { + this.buffer = new Uint8Array(16); + this.r = new Uint16Array(10); + this.h = new Uint16Array(10); + this.pad = new Uint16Array(8); + this.leftover = 0; + this.fin = 0; + + var t0, t1, t2, t3, t4, t5, t6, t7; + + t0 = key[ 0] & 0xff | (key[ 1] & 0xff) << 8; this.r[0] = ( t0 ) & 0x1fff; + t1 = key[ 2] & 0xff | (key[ 3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = key[ 4] & 0xff | (key[ 5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03; + t3 = key[ 6] & 0xff | (key[ 7] & 0xff) << 8; this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = key[ 8] & 0xff | (key[ 9] & 0xff) << 8; this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff; + this.r[5] = ((t4 >>> 1)) & 0x1ffe; + t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81; + t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + this.r[9] = ((t7 >>> 5)) & 0x007f; + + this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8; + this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8; + this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8; + this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8; + this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8; + this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8; + this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8; + this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8; +}; + +poly1305.prototype.blocks = function(m, mpos, bytes) { + var hibit = this.fin ? 0 : (1 << 11); + var t0, t1, t2, t3, t4, t5, t6, t7, c; + var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9; + + var h0 = this.h[0], + h1 = this.h[1], + h2 = this.h[2], + h3 = this.h[3], + h4 = this.h[4], + h5 = this.h[5], + h6 = this.h[6], + h7 = this.h[7], + h8 = this.h[8], + h9 = this.h[9]; + + var r0 = this.r[0], + r1 = this.r[1], + r2 = this.r[2], + r3 = this.r[3], + r4 = this.r[4], + r5 = this.r[5], + r6 = this.r[6], + r7 = this.r[7], + r8 = this.r[8], + r9 = this.r[9]; + + while (bytes >= 16) { + t0 = m[mpos+ 0] & 0xff | (m[mpos+ 1] & 0xff) << 8; h0 += ( t0 ) & 0x1fff; + t1 = m[mpos+ 2] & 0xff | (m[mpos+ 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = m[mpos+ 4] & 0xff | (m[mpos+ 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff; + t3 = m[mpos+ 6] & 0xff | (m[mpos+ 7] & 0xff) << 8; h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = m[mpos+ 8] & 0xff | (m[mpos+ 9] & 0xff) << 8; h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff; + h5 += ((t4 >>> 1)) & 0x1fff; + t5 = m[mpos+10] & 0xff | (m[mpos+11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = m[mpos+12] & 0xff | (m[mpos+13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff; + t7 = m[mpos+14] & 0xff | (m[mpos+15] & 0xff) << 8; h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + h9 += ((t7 >>> 5)) | hibit; + + c = 0; + + d0 = c; + d0 += h0 * r0; + d0 += h1 * (5 * r9); + d0 += h2 * (5 * r8); + d0 += h3 * (5 * r7); + d0 += h4 * (5 * r6); + c = (d0 >>> 13); d0 &= 0x1fff; + d0 += h5 * (5 * r5); + d0 += h6 * (5 * r4); + d0 += h7 * (5 * r3); + d0 += h8 * (5 * r2); + d0 += h9 * (5 * r1); + c += (d0 >>> 13); d0 &= 0x1fff; + + d1 = c; + d1 += h0 * r1; + d1 += h1 * r0; + d1 += h2 * (5 * r9); + d1 += h3 * (5 * r8); + d1 += h4 * (5 * r7); + c = (d1 >>> 13); d1 &= 0x1fff; + d1 += h5 * (5 * r6); + d1 += h6 * (5 * r5); + d1 += h7 * (5 * r4); + d1 += h8 * (5 * r3); + d1 += h9 * (5 * r2); + c += (d1 >>> 13); d1 &= 0x1fff; + + d2 = c; + d2 += h0 * r2; + d2 += h1 * r1; + d2 += h2 * r0; + d2 += h3 * (5 * r9); + d2 += h4 * (5 * r8); + c = (d2 >>> 13); d2 &= 0x1fff; + d2 += h5 * (5 * r7); + d2 += h6 * (5 * r6); + d2 += h7 * (5 * r5); + d2 += h8 * (5 * r4); + d2 += h9 * (5 * r3); + c += (d2 >>> 13); d2 &= 0x1fff; + + d3 = c; + d3 += h0 * r3; + d3 += h1 * r2; + d3 += h2 * r1; + d3 += h3 * r0; + d3 += h4 * (5 * r9); + c = (d3 >>> 13); d3 &= 0x1fff; + d3 += h5 * (5 * r8); + d3 += h6 * (5 * r7); + d3 += h7 * (5 * r6); + d3 += h8 * (5 * r5); + d3 += h9 * (5 * r4); + c += (d3 >>> 13); d3 &= 0x1fff; + + d4 = c; + d4 += h0 * r4; + d4 += h1 * r3; + d4 += h2 * r2; + d4 += h3 * r1; + d4 += h4 * r0; + c = (d4 >>> 13); d4 &= 0x1fff; + d4 += h5 * (5 * r9); + d4 += h6 * (5 * r8); + d4 += h7 * (5 * r7); + d4 += h8 * (5 * r6); + d4 += h9 * (5 * r5); + c += (d4 >>> 13); d4 &= 0x1fff; + + d5 = c; + d5 += h0 * r5; + d5 += h1 * r4; + d5 += h2 * r3; + d5 += h3 * r2; + d5 += h4 * r1; + c = (d5 >>> 13); d5 &= 0x1fff; + d5 += h5 * r0; + d5 += h6 * (5 * r9); + d5 += h7 * (5 * r8); + d5 += h8 * (5 * r7); + d5 += h9 * (5 * r6); + c += (d5 >>> 13); d5 &= 0x1fff; + + d6 = c; + d6 += h0 * r6; + d6 += h1 * r5; + d6 += h2 * r4; + d6 += h3 * r3; + d6 += h4 * r2; + c = (d6 >>> 13); d6 &= 0x1fff; + d6 += h5 * r1; + d6 += h6 * r0; + d6 += h7 * (5 * r9); + d6 += h8 * (5 * r8); + d6 += h9 * (5 * r7); + c += (d6 >>> 13); d6 &= 0x1fff; + + d7 = c; + d7 += h0 * r7; + d7 += h1 * r6; + d7 += h2 * r5; + d7 += h3 * r4; + d7 += h4 * r3; + c = (d7 >>> 13); d7 &= 0x1fff; + d7 += h5 * r2; + d7 += h6 * r1; + d7 += h7 * r0; + d7 += h8 * (5 * r9); + d7 += h9 * (5 * r8); + c += (d7 >>> 13); d7 &= 0x1fff; + + d8 = c; + d8 += h0 * r8; + d8 += h1 * r7; + d8 += h2 * r6; + d8 += h3 * r5; + d8 += h4 * r4; + c = (d8 >>> 13); d8 &= 0x1fff; + d8 += h5 * r3; + d8 += h6 * r2; + d8 += h7 * r1; + d8 += h8 * r0; + d8 += h9 * (5 * r9); + c += (d8 >>> 13); d8 &= 0x1fff; + + d9 = c; + d9 += h0 * r9; + d9 += h1 * r8; + d9 += h2 * r7; + d9 += h3 * r6; + d9 += h4 * r5; + c = (d9 >>> 13); d9 &= 0x1fff; + d9 += h5 * r4; + d9 += h6 * r3; + d9 += h7 * r2; + d9 += h8 * r1; + d9 += h9 * r0; + c += (d9 >>> 13); d9 &= 0x1fff; + + c = (((c << 2) + c)) | 0; + c = (c + d0) | 0; + d0 = c & 0x1fff; + c = (c >>> 13); + d1 += c; + + h0 = d0; + h1 = d1; + h2 = d2; + h3 = d3; + h4 = d4; + h5 = d5; + h6 = d6; + h7 = d7; + h8 = d8; + h9 = d9; + + mpos += 16; + bytes -= 16; + } + this.h[0] = h0; + this.h[1] = h1; + this.h[2] = h2; + this.h[3] = h3; + this.h[4] = h4; + this.h[5] = h5; + this.h[6] = h6; + this.h[7] = h7; + this.h[8] = h8; + this.h[9] = h9; +}; + +poly1305.prototype.finish = function(mac, macpos) { + var g = new Uint16Array(10); + var c, mask, f, i; + + if (this.leftover) { + i = this.leftover; + this.buffer[i++] = 1; + for (; i < 16; i++) this.buffer[i] = 0; + this.fin = 1; + this.blocks(this.buffer, 0, 16); + } + + c = this.h[1] >>> 13; + this.h[1] &= 0x1fff; + for (i = 2; i < 10; i++) { + this.h[i] += c; + c = this.h[i] >>> 13; + this.h[i] &= 0x1fff; + } + this.h[0] += (c * 5); + c = this.h[0] >>> 13; + this.h[0] &= 0x1fff; + this.h[1] += c; + c = this.h[1] >>> 13; + this.h[1] &= 0x1fff; + this.h[2] += c; + + g[0] = this.h[0] + 5; + c = g[0] >>> 13; + g[0] &= 0x1fff; + for (i = 1; i < 10; i++) { + g[i] = this.h[i] + c; + c = g[i] >>> 13; + g[i] &= 0x1fff; + } + g[9] -= (1 << 13); + + mask = (c ^ 1) - 1; + for (i = 0; i < 10; i++) g[i] &= mask; + mask = ~mask; + for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i]; + + this.h[0] = ((this.h[0] ) | (this.h[1] << 13) ) & 0xffff; + this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10) ) & 0xffff; + this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7) ) & 0xffff; + this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4) ) & 0xffff; + this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff; + this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11) ) & 0xffff; + this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8) ) & 0xffff; + this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5) ) & 0xffff; + + f = this.h[0] + this.pad[0]; + this.h[0] = f & 0xffff; + for (i = 1; i < 8; i++) { + f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0; + this.h[i] = f & 0xffff; + } + + mac[macpos+ 0] = (this.h[0] >>> 0) & 0xff; + mac[macpos+ 1] = (this.h[0] >>> 8) & 0xff; + mac[macpos+ 2] = (this.h[1] >>> 0) & 0xff; + mac[macpos+ 3] = (this.h[1] >>> 8) & 0xff; + mac[macpos+ 4] = (this.h[2] >>> 0) & 0xff; + mac[macpos+ 5] = (this.h[2] >>> 8) & 0xff; + mac[macpos+ 6] = (this.h[3] >>> 0) & 0xff; + mac[macpos+ 7] = (this.h[3] >>> 8) & 0xff; + mac[macpos+ 8] = (this.h[4] >>> 0) & 0xff; + mac[macpos+ 9] = (this.h[4] >>> 8) & 0xff; + mac[macpos+10] = (this.h[5] >>> 0) & 0xff; + mac[macpos+11] = (this.h[5] >>> 8) & 0xff; + mac[macpos+12] = (this.h[6] >>> 0) & 0xff; + mac[macpos+13] = (this.h[6] >>> 8) & 0xff; + mac[macpos+14] = (this.h[7] >>> 0) & 0xff; + mac[macpos+15] = (this.h[7] >>> 8) & 0xff; +}; + +poly1305.prototype.update = function(m, mpos, bytes) { + var i, want; + + if (this.leftover) { + want = (16 - this.leftover); + if (want > bytes) + want = bytes; + for (i = 0; i < want; i++) + this.buffer[this.leftover + i] = m[mpos+i]; + bytes -= want; + mpos += want; + this.leftover += want; + if (this.leftover < 16) + return; + this.blocks(this.buffer, 0, 16); + this.leftover = 0; + } + + if (bytes >= 16) { + want = bytes - (bytes % 16); + this.blocks(m, mpos, want); + mpos += want; + bytes -= want; + } + + if (bytes) { + for (i = 0; i < bytes; i++) + this.buffer[this.leftover + i] = m[mpos+i]; + this.leftover += bytes; + } +}; + +function crypto_onetimeauth(out, outpos, m, mpos, n, k) { + var s = new poly1305(k); + s.update(m, mpos, n); + s.finish(out, outpos); + return 0; +} + +function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { + var x = new Uint8Array(16); + crypto_onetimeauth(x,0,m,mpos,n,k); + return crypto_verify_16(h,hpos,x,0); +} + +function crypto_secretbox(c,m,d,n,k) { + var i; + if (d < 32) return -1; + crypto_stream_xor(c,0,m,0,d,n,k); + crypto_onetimeauth(c, 16, c, 32, d - 32, c); + for (i = 0; i < 16; i++) c[i] = 0; + return 0; +} + +function crypto_secretbox_open(m,c,d,n,k) { + var i; + var x = new Uint8Array(32); + if (d < 32) return -1; + crypto_stream(x,0,32,n,k); + if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; + crypto_stream_xor(m,0,c,0,d,n,k); + for (i = 0; i < 32; i++) m[i] = 0; + return 0; +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; +} + +function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; +} + +function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function crypto_box_beforenm(k, y, x) { + var s = new Uint8Array(32); + crypto_scalarmult(s, x, y); + return crypto_core_hsalsa20(k, _0, s, sigma); +} + +var crypto_box_afternm = crypto_secretbox; +var crypto_box_open_afternm = crypto_secretbox_open; + +function crypto_box(c, m, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +function crypto_box_open(m, c, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_open_afternm(m, c, d, n, k); +} + +var K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +]; + +function crypto_hashblocks_hl(hh, hl, m, n) { + var wh = new Int32Array(16), wl = new Int32Array(16), + bh0, bh1, bh2, bh3, bh4, bh5, bh6, bh7, + bl0, bl1, bl2, bl3, bl4, bl5, bl6, bl7, + th, tl, i, j, h, l, a, b, c, d; + + var ah0 = hh[0], + ah1 = hh[1], + ah2 = hh[2], + ah3 = hh[3], + ah4 = hh[4], + ah5 = hh[5], + ah6 = hh[6], + ah7 = hh[7], + + al0 = hl[0], + al1 = hl[1], + al2 = hl[2], + al3 = hl[3], + al4 = hl[4], + al5 = hl[5], + al6 = hl[6], + al7 = hl[7]; + + var pos = 0; + while (n >= 128) { + for (i = 0; i < 16; i++) { + j = 8 * i + pos; + wh[i] = (m[j+0] << 24) | (m[j+1] << 16) | (m[j+2] << 8) | m[j+3]; + wl[i] = (m[j+4] << 24) | (m[j+5] << 16) | (m[j+6] << 8) | m[j+7]; + } + for (i = 0; i < 80; i++) { + bh0 = ah0; + bh1 = ah1; + bh2 = ah2; + bh3 = ah3; + bh4 = ah4; + bh5 = ah5; + bh6 = ah6; + bh7 = ah7; + + bl0 = al0; + bl1 = al1; + bl2 = al2; + bl3 = al3; + bl4 = al4; + bl5 = al5; + bl6 = al6; + bl7 = al7; + + // add + h = ah7; + l = al7; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + // Sigma1 + h = ((ah4 >>> 14) | (al4 << (32-14))) ^ ((ah4 >>> 18) | (al4 << (32-18))) ^ ((al4 >>> (41-32)) | (ah4 << (32-(41-32)))); + l = ((al4 >>> 14) | (ah4 << (32-14))) ^ ((al4 >>> 18) | (ah4 << (32-18))) ^ ((ah4 >>> (41-32)) | (al4 << (32-(41-32)))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // Ch + h = (ah4 & ah5) ^ (~ah4 & ah6); + l = (al4 & al5) ^ (~al4 & al6); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // K + h = K[i*2]; + l = K[i*2+1]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // w + h = wh[i%16]; + l = wl[i%16]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + th = c & 0xffff | d << 16; + tl = a & 0xffff | b << 16; + + // add + h = th; + l = tl; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + // Sigma0 + h = ((ah0 >>> 28) | (al0 << (32-28))) ^ ((al0 >>> (34-32)) | (ah0 << (32-(34-32)))) ^ ((al0 >>> (39-32)) | (ah0 << (32-(39-32)))); + l = ((al0 >>> 28) | (ah0 << (32-28))) ^ ((ah0 >>> (34-32)) | (al0 << (32-(34-32)))) ^ ((ah0 >>> (39-32)) | (al0 << (32-(39-32)))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // Maj + h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2); + l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + bh7 = (c & 0xffff) | (d << 16); + bl7 = (a & 0xffff) | (b << 16); + + // add + h = bh3; + l = bl3; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = th; + l = tl; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + bh3 = (c & 0xffff) | (d << 16); + bl3 = (a & 0xffff) | (b << 16); + + ah1 = bh0; + ah2 = bh1; + ah3 = bh2; + ah4 = bh3; + ah5 = bh4; + ah6 = bh5; + ah7 = bh6; + ah0 = bh7; + + al1 = bl0; + al2 = bl1; + al3 = bl2; + al4 = bl3; + al5 = bl4; + al6 = bl5; + al7 = bl6; + al0 = bl7; + + if (i%16 === 15) { + for (j = 0; j < 16; j++) { + // add + h = wh[j]; + l = wl[j]; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = wh[(j+9)%16]; + l = wl[(j+9)%16]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // sigma0 + th = wh[(j+1)%16]; + tl = wl[(j+1)%16]; + h = ((th >>> 1) | (tl << (32-1))) ^ ((th >>> 8) | (tl << (32-8))) ^ (th >>> 7); + l = ((tl >>> 1) | (th << (32-1))) ^ ((tl >>> 8) | (th << (32-8))) ^ ((tl >>> 7) | (th << (32-7))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // sigma1 + th = wh[(j+14)%16]; + tl = wl[(j+14)%16]; + h = ((th >>> 19) | (tl << (32-19))) ^ ((tl >>> (61-32)) | (th << (32-(61-32)))) ^ (th >>> 6); + l = ((tl >>> 19) | (th << (32-19))) ^ ((th >>> (61-32)) | (tl << (32-(61-32)))) ^ ((tl >>> 6) | (th << (32-6))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + wh[j] = (c & 0xffff) | (d << 16); + wl[j] = (a & 0xffff) | (b << 16); + } + } + } + + // add + h = ah0; + l = al0; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[0]; + l = hl[0]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[0] = ah0 = (c & 0xffff) | (d << 16); + hl[0] = al0 = (a & 0xffff) | (b << 16); + + h = ah1; + l = al1; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[1]; + l = hl[1]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[1] = ah1 = (c & 0xffff) | (d << 16); + hl[1] = al1 = (a & 0xffff) | (b << 16); + + h = ah2; + l = al2; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[2]; + l = hl[2]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[2] = ah2 = (c & 0xffff) | (d << 16); + hl[2] = al2 = (a & 0xffff) | (b << 16); + + h = ah3; + l = al3; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[3]; + l = hl[3]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[3] = ah3 = (c & 0xffff) | (d << 16); + hl[3] = al3 = (a & 0xffff) | (b << 16); + + h = ah4; + l = al4; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[4]; + l = hl[4]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[4] = ah4 = (c & 0xffff) | (d << 16); + hl[4] = al4 = (a & 0xffff) | (b << 16); + + h = ah5; + l = al5; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[5]; + l = hl[5]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[5] = ah5 = (c & 0xffff) | (d << 16); + hl[5] = al5 = (a & 0xffff) | (b << 16); + + h = ah6; + l = al6; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[6]; + l = hl[6]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[6] = ah6 = (c & 0xffff) | (d << 16); + hl[6] = al6 = (a & 0xffff) | (b << 16); + + h = ah7; + l = al7; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[7]; + l = hl[7]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[7] = ah7 = (c & 0xffff) | (d << 16); + hl[7] = al7 = (a & 0xffff) | (b << 16); + + pos += 128; + n -= 128; + } + + return n; +} + +function crypto_hash(out, m, n) { + var hh = new Int32Array(8), + hl = new Int32Array(8), + x = new Uint8Array(256), + i, b = n; + + hh[0] = 0x6a09e667; + hh[1] = 0xbb67ae85; + hh[2] = 0x3c6ef372; + hh[3] = 0xa54ff53a; + hh[4] = 0x510e527f; + hh[5] = 0x9b05688c; + hh[6] = 0x1f83d9ab; + hh[7] = 0x5be0cd19; + + hl[0] = 0xf3bcc908; + hl[1] = 0x84caa73b; + hl[2] = 0xfe94f82b; + hl[3] = 0x5f1d36f1; + hl[4] = 0xade682d1; + hl[5] = 0x2b3e6c1f; + hl[6] = 0xfb41bd6b; + hl[7] = 0x137e2179; + + crypto_hashblocks_hl(hh, hl, m, n); + n %= 128; + + for (i = 0; i < n; i++) x[i] = m[b-n+i]; + x[n] = 128; + + n = 256-128*(n<112?1:0); + x[n-9] = 0; + ts64(x, n-8, (b / 0x20000000) | 0, b << 3); + crypto_hashblocks_hl(hh, hl, x, n); + + for (i = 0; i < 8; i++) ts64(out, 8*i, hh[i], hl[i]); + + return 0; +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm.subarray(32), n+32); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + crypto_hash(h, sm, n + 64); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + crypto_hash(h, m, n); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; +} + +var crypto_secretbox_KEYBYTES = 32, + crypto_secretbox_NONCEBYTES = 24, + crypto_secretbox_ZEROBYTES = 32, + crypto_secretbox_BOXZEROBYTES = 16, + crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_box_BEFORENMBYTES = 32, + crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, + crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, + crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64; + +nacl.lowlevel = { + crypto_core_hsalsa20: crypto_core_hsalsa20, + crypto_stream_xor: crypto_stream_xor, + crypto_stream: crypto_stream, + crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, + crypto_stream_salsa20: crypto_stream_salsa20, + crypto_onetimeauth: crypto_onetimeauth, + crypto_onetimeauth_verify: crypto_onetimeauth_verify, + crypto_verify_16: crypto_verify_16, + crypto_verify_32: crypto_verify_32, + crypto_secretbox: crypto_secretbox, + crypto_secretbox_open: crypto_secretbox_open, + crypto_scalarmult: crypto_scalarmult, + crypto_scalarmult_base: crypto_scalarmult_base, + crypto_box_beforenm: crypto_box_beforenm, + crypto_box_afternm: crypto_box_afternm, + crypto_box: crypto_box, + crypto_box_open: crypto_box_open, + crypto_box_keypair: crypto_box_keypair, + crypto_hash: crypto_hash, + crypto_sign: crypto_sign, + crypto_sign_keypair: crypto_sign_keypair, + crypto_sign_open: crypto_sign_open, + + crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, + crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, + crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, + crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, + crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, + crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, + crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, + crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, + crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, + crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, + crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, + crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, + crypto_sign_BYTES: crypto_sign_BYTES, + crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, + crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, + crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, + crypto_hash_BYTES: crypto_hash_BYTES, + + gf: gf, + D: D, + L: L, + pack25519: pack25519, + unpack25519: unpack25519, + M: M, + A: A, + S: S, + Z: Z, + pow2523: pow2523, + add: add, + set25519: set25519, + modL: modL, + scalarmult: scalarmult, + scalarbase: scalarbase, +}; + +/* High-level API */ + +function checkLengths(k, n) { + if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); + if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); +} + +function checkBoxLengths(pk, sk) { + if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); + if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); +} + +function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +nacl.randomBytes = function(n) { + var b = new Uint8Array(n); + randombytes(b, n); + return b; +}; + +nacl.secretbox = function(msg, nonce, key) { + checkArrayTypes(msg, nonce, key); + checkLengths(key, nonce); + var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); + var c = new Uint8Array(m.length); + for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + crypto_secretbox(c, m, m.length, nonce, key); + return c.subarray(crypto_secretbox_BOXZEROBYTES); +}; + +nacl.secretbox.open = function(box, nonce, key) { + checkArrayTypes(box, nonce, key); + checkLengths(key, nonce); + var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); + var m = new Uint8Array(c.length); + for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + if (c.length < 32) return null; + if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null; + return m.subarray(crypto_secretbox_ZEROBYTES); +}; + +nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; +nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; +nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.scalarMult.base = function(n) { + checkArrayTypes(n); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult_base(q, n); + return q; +}; + +nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; +nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; + +nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox(msg, nonce, k); +}; + +nacl.box.before = function(publicKey, secretKey) { + checkArrayTypes(publicKey, secretKey); + checkBoxLengths(publicKey, secretKey); + var k = new Uint8Array(crypto_box_BEFORENMBYTES); + crypto_box_beforenm(k, publicKey, secretKey); + return k; +}; + +nacl.box.after = nacl.secretbox; + +nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox.open(msg, nonce, k); +}; + +nacl.box.open.after = nacl.secretbox.open; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; +nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; +nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; +nacl.box.nonceLength = crypto_box_NONCEBYTES; +nacl.box.overheadLength = nacl.secretbox.overheadLength; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.open = function(signedMsg, publicKey) { + checkArrayTypes(signedMsg, publicKey); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var tmp = new Uint8Array(signedMsg.length); + var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); + if (mlen < 0) return null; + var m = new Uint8Array(mlen); + for (var i = 0; i < m.length; i++) m[i] = tmp[i]; + return m; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; +nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; +nacl.sign.seedLength = crypto_sign_SEEDBYTES; +nacl.sign.signatureLength = crypto_sign_BYTES; + +nacl.hash = function(msg) { + checkArrayTypes(msg); + var h = new Uint8Array(crypto_hash_BYTES); + crypto_hash(h, msg, msg.length); + return h; +}; + +nacl.hash.hashLength = crypto_hash_BYTES; + +nacl.verify = function(x, y) { + checkArrayTypes(x, y); + // Zero length arguments are considered not equal. + if (x.length === 0 || y.length === 0) return false; + if (x.length !== y.length) return false; + return (vn(x, 0, y, 0, x.length) === 0) ? true : false; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof require !== 'undefined') { + // Node.js. + crypto = require('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); diff --git a/node_modules/tweetnacl/nacl-fast.min.js b/node_modules/tweetnacl/nacl-fast.min.js new file mode 100644 index 0000000..348ec2e --- /dev/null +++ b/node_modules/tweetnacl/nacl-fast.min.js @@ -0,0 +1 @@ +!function(i){"use strict";var v=function(r){var t,n=new Float64Array(16);if(r)for(t=0;t>24&255,r[t+1]=n>>16&255,r[t+2]=n>>8&255,r[t+3]=255&n,r[t+4]=e>>24&255,r[t+5]=e>>16&255,r[t+6]=e>>8&255,r[t+7]=255&e}function w(r,t,n,e,o){var i,h=0;for(i=0;i>>8)-1}function b(r,t,n,e){return w(r,t,n,e,16)}function g(r,t,n,e){return w(r,t,n,e,32)}function A(r,t,n,e){!function(r,t,n,e){for(var o,i=255&e[0]|(255&e[1])<<8|(255&e[2])<<16|(255&e[3])<<24,h=255&n[0]|(255&n[1])<<8|(255&n[2])<<16|(255&n[3])<<24,a=255&n[4]|(255&n[5])<<8|(255&n[6])<<16|(255&n[7])<<24,f=255&n[8]|(255&n[9])<<8|(255&n[10])<<16|(255&n[11])<<24,s=255&n[12]|(255&n[13])<<8|(255&n[14])<<16|(255&n[15])<<24,u=255&e[4]|(255&e[5])<<8|(255&e[6])<<16|(255&e[7])<<24,c=255&t[0]|(255&t[1])<<8|(255&t[2])<<16|(255&t[3])<<24,y=255&t[4]|(255&t[5])<<8|(255&t[6])<<16|(255&t[7])<<24,l=255&t[8]|(255&t[9])<<8|(255&t[10])<<16|(255&t[11])<<24,w=255&t[12]|(255&t[13])<<8|(255&t[14])<<16|(255&t[15])<<24,v=255&e[8]|(255&e[9])<<8|(255&e[10])<<16|(255&e[11])<<24,p=255&n[16]|(255&n[17])<<8|(255&n[18])<<16|(255&n[19])<<24,b=255&n[20]|(255&n[21])<<8|(255&n[22])<<16|(255&n[23])<<24,g=255&n[24]|(255&n[25])<<8|(255&n[26])<<16|(255&n[27])<<24,A=255&n[28]|(255&n[29])<<8|(255&n[30])<<16|(255&n[31])<<24,_=255&e[12]|(255&e[13])<<8|(255&e[14])<<16|(255&e[15])<<24,U=i,d=h,E=a,x=f,M=s,m=u,B=c,S=y,k=l,K=w,Y=v,L=p,T=b,z=g,R=A,P=_,N=0;N<20;N+=2)U^=(o=(T^=(o=(k^=(o=(M^=(o=U+T|0)<<7|o>>>25)+U|0)<<9|o>>>23)+M|0)<<13|o>>>19)+k|0)<<18|o>>>14,m^=(o=(d^=(o=(z^=(o=(K^=(o=m+d|0)<<7|o>>>25)+m|0)<<9|o>>>23)+K|0)<<13|o>>>19)+z|0)<<18|o>>>14,Y^=(o=(B^=(o=(E^=(o=(R^=(o=Y+B|0)<<7|o>>>25)+Y|0)<<9|o>>>23)+R|0)<<13|o>>>19)+E|0)<<18|o>>>14,P^=(o=(L^=(o=(S^=(o=(x^=(o=P+L|0)<<7|o>>>25)+P|0)<<9|o>>>23)+x|0)<<13|o>>>19)+S|0)<<18|o>>>14,U^=(o=(x^=(o=(E^=(o=(d^=(o=U+x|0)<<7|o>>>25)+U|0)<<9|o>>>23)+d|0)<<13|o>>>19)+E|0)<<18|o>>>14,m^=(o=(M^=(o=(S^=(o=(B^=(o=m+M|0)<<7|o>>>25)+m|0)<<9|o>>>23)+B|0)<<13|o>>>19)+S|0)<<18|o>>>14,Y^=(o=(K^=(o=(k^=(o=(L^=(o=Y+K|0)<<7|o>>>25)+Y|0)<<9|o>>>23)+L|0)<<13|o>>>19)+k|0)<<18|o>>>14,P^=(o=(R^=(o=(z^=(o=(T^=(o=P+R|0)<<7|o>>>25)+P|0)<<9|o>>>23)+T|0)<<13|o>>>19)+z|0)<<18|o>>>14;U=U+i|0,d=d+h|0,E=E+a|0,x=x+f|0,M=M+s|0,m=m+u|0,B=B+c|0,S=S+y|0,k=k+l|0,K=K+w|0,Y=Y+v|0,L=L+p|0,T=T+b|0,z=z+g|0,R=R+A|0,P=P+_|0,r[0]=U>>>0&255,r[1]=U>>>8&255,r[2]=U>>>16&255,r[3]=U>>>24&255,r[4]=d>>>0&255,r[5]=d>>>8&255,r[6]=d>>>16&255,r[7]=d>>>24&255,r[8]=E>>>0&255,r[9]=E>>>8&255,r[10]=E>>>16&255,r[11]=E>>>24&255,r[12]=x>>>0&255,r[13]=x>>>8&255,r[14]=x>>>16&255,r[15]=x>>>24&255,r[16]=M>>>0&255,r[17]=M>>>8&255,r[18]=M>>>16&255,r[19]=M>>>24&255,r[20]=m>>>0&255,r[21]=m>>>8&255,r[22]=m>>>16&255,r[23]=m>>>24&255,r[24]=B>>>0&255,r[25]=B>>>8&255,r[26]=B>>>16&255,r[27]=B>>>24&255,r[28]=S>>>0&255,r[29]=S>>>8&255,r[30]=S>>>16&255,r[31]=S>>>24&255,r[32]=k>>>0&255,r[33]=k>>>8&255,r[34]=k>>>16&255,r[35]=k>>>24&255,r[36]=K>>>0&255,r[37]=K>>>8&255,r[38]=K>>>16&255,r[39]=K>>>24&255,r[40]=Y>>>0&255,r[41]=Y>>>8&255,r[42]=Y>>>16&255,r[43]=Y>>>24&255,r[44]=L>>>0&255,r[45]=L>>>8&255,r[46]=L>>>16&255,r[47]=L>>>24&255,r[48]=T>>>0&255,r[49]=T>>>8&255,r[50]=T>>>16&255,r[51]=T>>>24&255,r[52]=z>>>0&255,r[53]=z>>>8&255,r[54]=z>>>16&255,r[55]=z>>>24&255,r[56]=R>>>0&255,r[57]=R>>>8&255,r[58]=R>>>16&255,r[59]=R>>>24&255,r[60]=P>>>0&255,r[61]=P>>>8&255,r[62]=P>>>16&255,r[63]=P>>>24&255}(r,t,n,e)}function _(r,t,n,e){!function(r,t,n,e){for(var o,i=255&e[0]|(255&e[1])<<8|(255&e[2])<<16|(255&e[3])<<24,h=255&n[0]|(255&n[1])<<8|(255&n[2])<<16|(255&n[3])<<24,a=255&n[4]|(255&n[5])<<8|(255&n[6])<<16|(255&n[7])<<24,f=255&n[8]|(255&n[9])<<8|(255&n[10])<<16|(255&n[11])<<24,s=255&n[12]|(255&n[13])<<8|(255&n[14])<<16|(255&n[15])<<24,u=255&e[4]|(255&e[5])<<8|(255&e[6])<<16|(255&e[7])<<24,c=255&t[0]|(255&t[1])<<8|(255&t[2])<<16|(255&t[3])<<24,y=255&t[4]|(255&t[5])<<8|(255&t[6])<<16|(255&t[7])<<24,l=255&t[8]|(255&t[9])<<8|(255&t[10])<<16|(255&t[11])<<24,w=255&t[12]|(255&t[13])<<8|(255&t[14])<<16|(255&t[15])<<24,v=255&e[8]|(255&e[9])<<8|(255&e[10])<<16|(255&e[11])<<24,p=255&n[16]|(255&n[17])<<8|(255&n[18])<<16|(255&n[19])<<24,b=255&n[20]|(255&n[21])<<8|(255&n[22])<<16|(255&n[23])<<24,g=255&n[24]|(255&n[25])<<8|(255&n[26])<<16|(255&n[27])<<24,A=255&n[28]|(255&n[29])<<8|(255&n[30])<<16|(255&n[31])<<24,_=255&e[12]|(255&e[13])<<8|(255&e[14])<<16|(255&e[15])<<24,U=0;U<20;U+=2)i^=(o=(b^=(o=(l^=(o=(s^=(o=i+b|0)<<7|o>>>25)+i|0)<<9|o>>>23)+s|0)<<13|o>>>19)+l|0)<<18|o>>>14,u^=(o=(h^=(o=(g^=(o=(w^=(o=u+h|0)<<7|o>>>25)+u|0)<<9|o>>>23)+w|0)<<13|o>>>19)+g|0)<<18|o>>>14,v^=(o=(c^=(o=(a^=(o=(A^=(o=v+c|0)<<7|o>>>25)+v|0)<<9|o>>>23)+A|0)<<13|o>>>19)+a|0)<<18|o>>>14,_^=(o=(p^=(o=(y^=(o=(f^=(o=_+p|0)<<7|o>>>25)+_|0)<<9|o>>>23)+f|0)<<13|o>>>19)+y|0)<<18|o>>>14,i^=(o=(f^=(o=(a^=(o=(h^=(o=i+f|0)<<7|o>>>25)+i|0)<<9|o>>>23)+h|0)<<13|o>>>19)+a|0)<<18|o>>>14,u^=(o=(s^=(o=(y^=(o=(c^=(o=u+s|0)<<7|o>>>25)+u|0)<<9|o>>>23)+c|0)<<13|o>>>19)+y|0)<<18|o>>>14,v^=(o=(w^=(o=(l^=(o=(p^=(o=v+w|0)<<7|o>>>25)+v|0)<<9|o>>>23)+p|0)<<13|o>>>19)+l|0)<<18|o>>>14,_^=(o=(A^=(o=(g^=(o=(b^=(o=_+A|0)<<7|o>>>25)+_|0)<<9|o>>>23)+b|0)<<13|o>>>19)+g|0)<<18|o>>>14;r[0]=i>>>0&255,r[1]=i>>>8&255,r[2]=i>>>16&255,r[3]=i>>>24&255,r[4]=u>>>0&255,r[5]=u>>>8&255,r[6]=u>>>16&255,r[7]=u>>>24&255,r[8]=v>>>0&255,r[9]=v>>>8&255,r[10]=v>>>16&255,r[11]=v>>>24&255,r[12]=_>>>0&255,r[13]=_>>>8&255,r[14]=_>>>16&255,r[15]=_>>>24&255,r[16]=c>>>0&255,r[17]=c>>>8&255,r[18]=c>>>16&255,r[19]=c>>>24&255,r[20]=y>>>0&255,r[21]=y>>>8&255,r[22]=y>>>16&255,r[23]=y>>>24&255,r[24]=l>>>0&255,r[25]=l>>>8&255,r[26]=l>>>16&255,r[27]=l>>>24&255,r[28]=w>>>0&255,r[29]=w>>>8&255,r[30]=w>>>16&255,r[31]=w>>>24&255}(r,t,n,e)}var U=new Uint8Array([101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107]);function d(r,t,n,e,o,i,h){var a,f,s=new Uint8Array(16),u=new Uint8Array(64);for(f=0;f<16;f++)s[f]=0;for(f=0;f<8;f++)s[f]=i[f];for(;64<=o;){for(A(u,s,h,U),f=0;f<64;f++)r[t+f]=n[e+f]^u[f];for(a=1,f=8;f<16;f++)a=a+(255&s[f])|0,s[f]=255&a,a>>>=8;o-=64,t+=64,e+=64}if(0>>=8;n-=64,t+=64}if(0>>13|n<<3),e=255&r[4]|(255&r[5])<<8,this.r[2]=7939&(n>>>10|e<<6),o=255&r[6]|(255&r[7])<<8,this.r[3]=8191&(e>>>7|o<<9),i=255&r[8]|(255&r[9])<<8,this.r[4]=255&(o>>>4|i<<12),this.r[5]=i>>>1&8190,h=255&r[10]|(255&r[11])<<8,this.r[6]=8191&(i>>>14|h<<2),a=255&r[12]|(255&r[13])<<8,this.r[7]=8065&(h>>>11|a<<5),f=255&r[14]|(255&r[15])<<8,this.r[8]=8191&(a>>>8|f<<8),this.r[9]=f>>>5&127,this.pad[0]=255&r[16]|(255&r[17])<<8,this.pad[1]=255&r[18]|(255&r[19])<<8,this.pad[2]=255&r[20]|(255&r[21])<<8,this.pad[3]=255&r[22]|(255&r[23])<<8,this.pad[4]=255&r[24]|(255&r[25])<<8,this.pad[5]=255&r[26]|(255&r[27])<<8,this.pad[6]=255&r[28]|(255&r[29])<<8,this.pad[7]=255&r[30]|(255&r[31])<<8};function B(r,t,n,e,o,i){var h=new m(i);return h.update(n,e,o),h.finish(r,t),0}function S(r,t,n,e,o,i){var h=new Uint8Array(16);return B(h,0,n,e,o,i),b(r,t,h,0)}function k(r,t,n,e,o){var i;if(n<32)return-1;for(M(r,0,t,0,n,e,o),B(r,16,r,32,n-32,r),i=0;i<16;i++)r[i]=0;return 0}function K(r,t,n,e,o){var i,h=new Uint8Array(32);if(n<32)return-1;if(x(h,0,32,e,o),0!==S(t,16,t,32,n-32,h))return-1;for(M(r,0,t,0,n,e,o),i=0;i<32;i++)r[i]=0;return 0}function Y(r,t){var n;for(n=0;n<16;n++)r[n]=0|t[n]}function L(r){var t,n,e=1;for(t=0;t<16;t++)n=r[t]+e+65535,e=Math.floor(n/65536),r[t]=n-65536*e;r[0]+=e-1+37*(e-1)}function T(r,t,n){for(var e,o=~(n-1),i=0;i<16;i++)e=o&(r[i]^t[i]),r[i]^=e,t[i]^=e}function z(r,t){var n,e,o,i=v(),h=v();for(n=0;n<16;n++)h[n]=t[n];for(L(h),L(h),L(h),e=0;e<2;e++){for(i[0]=h[0]-65517,n=1;n<15;n++)i[n]=h[n]-65535-(i[n-1]>>16&1),i[n-1]&=65535;i[15]=h[15]-32767-(i[14]>>16&1),o=i[15]>>16&1,i[14]&=65535,T(h,i,1-o)}for(n=0;n<16;n++)r[2*n]=255&h[n],r[2*n+1]=h[n]>>8}function R(r,t){var n=new Uint8Array(32),e=new Uint8Array(32);return z(n,r),z(e,t),g(n,0,e,0)}function P(r){var t=new Uint8Array(32);return z(t,r),1&t[0]}function N(r,t){var n;for(n=0;n<16;n++)r[n]=t[2*n]+(t[2*n+1]<<8);r[15]&=32767}function O(r,t,n){for(var e=0;e<16;e++)r[e]=t[e]+n[e]}function C(r,t,n){for(var e=0;e<16;e++)r[e]=t[e]-n[e]}function F(r,t,n){var e,o,i=0,h=0,a=0,f=0,s=0,u=0,c=0,y=0,l=0,w=0,v=0,p=0,b=0,g=0,A=0,_=0,U=0,d=0,E=0,x=0,M=0,m=0,B=0,S=0,k=0,K=0,Y=0,L=0,T=0,z=0,R=0,P=n[0],N=n[1],O=n[2],C=n[3],F=n[4],I=n[5],Z=n[6],G=n[7],q=n[8],D=n[9],V=n[10],X=n[11],j=n[12],H=n[13],J=n[14],Q=n[15];i+=(e=t[0])*P,h+=e*N,a+=e*O,f+=e*C,s+=e*F,u+=e*I,c+=e*Z,y+=e*G,l+=e*q,w+=e*D,v+=e*V,p+=e*X,b+=e*j,g+=e*H,A+=e*J,_+=e*Q,h+=(e=t[1])*P,a+=e*N,f+=e*O,s+=e*C,u+=e*F,c+=e*I,y+=e*Z,l+=e*G,w+=e*q,v+=e*D,p+=e*V,b+=e*X,g+=e*j,A+=e*H,_+=e*J,U+=e*Q,a+=(e=t[2])*P,f+=e*N,s+=e*O,u+=e*C,c+=e*F,y+=e*I,l+=e*Z,w+=e*G,v+=e*q,p+=e*D,b+=e*V,g+=e*X,A+=e*j,_+=e*H,U+=e*J,d+=e*Q,f+=(e=t[3])*P,s+=e*N,u+=e*O,c+=e*C,y+=e*F,l+=e*I,w+=e*Z,v+=e*G,p+=e*q,b+=e*D,g+=e*V,A+=e*X,_+=e*j,U+=e*H,d+=e*J,E+=e*Q,s+=(e=t[4])*P,u+=e*N,c+=e*O,y+=e*C,l+=e*F,w+=e*I,v+=e*Z,p+=e*G,b+=e*q,g+=e*D,A+=e*V,_+=e*X,U+=e*j,d+=e*H,E+=e*J,x+=e*Q,u+=(e=t[5])*P,c+=e*N,y+=e*O,l+=e*C,w+=e*F,v+=e*I,p+=e*Z,b+=e*G,g+=e*q,A+=e*D,_+=e*V,U+=e*X,d+=e*j,E+=e*H,x+=e*J,M+=e*Q,c+=(e=t[6])*P,y+=e*N,l+=e*O,w+=e*C,v+=e*F,p+=e*I,b+=e*Z,g+=e*G,A+=e*q,_+=e*D,U+=e*V,d+=e*X,E+=e*j,x+=e*H,M+=e*J,m+=e*Q,y+=(e=t[7])*P,l+=e*N,w+=e*O,v+=e*C,p+=e*F,b+=e*I,g+=e*Z,A+=e*G,_+=e*q,U+=e*D,d+=e*V,E+=e*X,x+=e*j,M+=e*H,m+=e*J,B+=e*Q,l+=(e=t[8])*P,w+=e*N,v+=e*O,p+=e*C,b+=e*F,g+=e*I,A+=e*Z,_+=e*G,U+=e*q,d+=e*D,E+=e*V,x+=e*X,M+=e*j,m+=e*H,B+=e*J,S+=e*Q,w+=(e=t[9])*P,v+=e*N,p+=e*O,b+=e*C,g+=e*F,A+=e*I,_+=e*Z,U+=e*G,d+=e*q,E+=e*D,x+=e*V,M+=e*X,m+=e*j,B+=e*H,S+=e*J,k+=e*Q,v+=(e=t[10])*P,p+=e*N,b+=e*O,g+=e*C,A+=e*F,_+=e*I,U+=e*Z,d+=e*G,E+=e*q,x+=e*D,M+=e*V,m+=e*X,B+=e*j,S+=e*H,k+=e*J,K+=e*Q,p+=(e=t[11])*P,b+=e*N,g+=e*O,A+=e*C,_+=e*F,U+=e*I,d+=e*Z,E+=e*G,x+=e*q,M+=e*D,m+=e*V,B+=e*X,S+=e*j,k+=e*H,K+=e*J,Y+=e*Q,b+=(e=t[12])*P,g+=e*N,A+=e*O,_+=e*C,U+=e*F,d+=e*I,E+=e*Z,x+=e*G,M+=e*q,m+=e*D,B+=e*V,S+=e*X,k+=e*j,K+=e*H,Y+=e*J,L+=e*Q,g+=(e=t[13])*P,A+=e*N,_+=e*O,U+=e*C,d+=e*F,E+=e*I,x+=e*Z,M+=e*G,m+=e*q,B+=e*D,S+=e*V,k+=e*X,K+=e*j,Y+=e*H,L+=e*J,T+=e*Q,A+=(e=t[14])*P,_+=e*N,U+=e*O,d+=e*C,E+=e*F,x+=e*I,M+=e*Z,m+=e*G,B+=e*q,S+=e*D,k+=e*V,K+=e*X,Y+=e*j,L+=e*H,T+=e*J,z+=e*Q,_+=(e=t[15])*P,h+=38*(d+=e*O),a+=38*(E+=e*C),f+=38*(x+=e*F),s+=38*(M+=e*I),u+=38*(m+=e*Z),c+=38*(B+=e*G),y+=38*(S+=e*q),l+=38*(k+=e*D),w+=38*(K+=e*V),v+=38*(Y+=e*X),p+=38*(L+=e*j),b+=38*(T+=e*H),g+=38*(z+=e*J),A+=38*(R+=e*Q),i=(e=(i+=38*(U+=e*N))+(o=1)+65535)-65536*(o=Math.floor(e/65536)),h=(e=h+o+65535)-65536*(o=Math.floor(e/65536)),a=(e=a+o+65535)-65536*(o=Math.floor(e/65536)),f=(e=f+o+65535)-65536*(o=Math.floor(e/65536)),s=(e=s+o+65535)-65536*(o=Math.floor(e/65536)),u=(e=u+o+65535)-65536*(o=Math.floor(e/65536)),c=(e=c+o+65535)-65536*(o=Math.floor(e/65536)),y=(e=y+o+65535)-65536*(o=Math.floor(e/65536)),l=(e=l+o+65535)-65536*(o=Math.floor(e/65536)),w=(e=w+o+65535)-65536*(o=Math.floor(e/65536)),v=(e=v+o+65535)-65536*(o=Math.floor(e/65536)),p=(e=p+o+65535)-65536*(o=Math.floor(e/65536)),b=(e=b+o+65535)-65536*(o=Math.floor(e/65536)),g=(e=g+o+65535)-65536*(o=Math.floor(e/65536)),A=(e=A+o+65535)-65536*(o=Math.floor(e/65536)),_=(e=_+o+65535)-65536*(o=Math.floor(e/65536)),i=(e=(i+=o-1+37*(o-1))+(o=1)+65535)-65536*(o=Math.floor(e/65536)),h=(e=h+o+65535)-65536*(o=Math.floor(e/65536)),a=(e=a+o+65535)-65536*(o=Math.floor(e/65536)),f=(e=f+o+65535)-65536*(o=Math.floor(e/65536)),s=(e=s+o+65535)-65536*(o=Math.floor(e/65536)),u=(e=u+o+65535)-65536*(o=Math.floor(e/65536)),c=(e=c+o+65535)-65536*(o=Math.floor(e/65536)),y=(e=y+o+65535)-65536*(o=Math.floor(e/65536)),l=(e=l+o+65535)-65536*(o=Math.floor(e/65536)),w=(e=w+o+65535)-65536*(o=Math.floor(e/65536)),v=(e=v+o+65535)-65536*(o=Math.floor(e/65536)),p=(e=p+o+65535)-65536*(o=Math.floor(e/65536)),b=(e=b+o+65535)-65536*(o=Math.floor(e/65536)),g=(e=g+o+65535)-65536*(o=Math.floor(e/65536)),A=(e=A+o+65535)-65536*(o=Math.floor(e/65536)),_=(e=_+o+65535)-65536*(o=Math.floor(e/65536)),i+=o-1+37*(o-1),r[0]=i,r[1]=h,r[2]=a,r[3]=f,r[4]=s,r[5]=u,r[6]=c,r[7]=y,r[8]=l,r[9]=w,r[10]=v,r[11]=p,r[12]=b,r[13]=g,r[14]=A,r[15]=_}function I(r,t){F(r,t,t)}function Z(r,t){var n,e=v();for(n=0;n<16;n++)e[n]=t[n];for(n=253;0<=n;n--)I(e,e),2!==n&&4!==n&&F(e,e,t);for(n=0;n<16;n++)r[n]=e[n]}function G(r,t){var n,e=v();for(n=0;n<16;n++)e[n]=t[n];for(n=250;0<=n;n--)I(e,e),1!==n&&F(e,e,t);for(n=0;n<16;n++)r[n]=e[n]}function q(r,t,n){var e,o,i=new Uint8Array(32),h=new Float64Array(80),a=v(),f=v(),s=v(),u=v(),c=v(),y=v();for(o=0;o<31;o++)i[o]=t[o];for(i[31]=127&t[31]|64,i[0]&=248,N(h,n),o=0;o<16;o++)f[o]=h[o],u[o]=a[o]=s[o]=0;for(a[0]=u[0]=1,o=254;0<=o;--o)T(a,f,e=i[o>>>3]>>>(7&o)&1),T(s,u,e),O(c,a,s),C(a,a,s),O(s,f,u),C(f,f,u),I(u,c),I(y,a),F(a,s,a),F(s,f,c),O(c,a,s),C(a,a,s),I(f,a),C(s,u,y),F(a,s,p),O(a,a,u),F(s,s,a),F(a,u,y),F(u,f,h),I(f,c),T(a,f,e),T(s,u,e);for(o=0;o<16;o++)h[o+16]=a[o],h[o+32]=s[o],h[o+48]=f[o],h[o+64]=u[o];var l=h.subarray(32),w=h.subarray(16);return Z(l,l),F(w,w,l),z(r,w),0}function D(r,t){return q(r,t,n)}function V(r,t){return h(t,32),D(r,t)}function X(r,t,n){var e=new Uint8Array(32);return q(e,n,t),_(r,o,e,U)}m.prototype.blocks=function(r,t,n){for(var e,o,i,h,a,f,s,u,c,y,l,w,v,p,b,g,A,_,U,d=this.fin?0:2048,E=this.h[0],x=this.h[1],M=this.h[2],m=this.h[3],B=this.h[4],S=this.h[5],k=this.h[6],K=this.h[7],Y=this.h[8],L=this.h[9],T=this.r[0],z=this.r[1],R=this.r[2],P=this.r[3],N=this.r[4],O=this.r[5],C=this.r[6],F=this.r[7],I=this.r[8],Z=this.r[9];16<=n;)y=c=0,y+=(E+=8191&(e=255&r[t+0]|(255&r[t+1])<<8))*T,y+=(x+=8191&(e>>>13|(o=255&r[t+2]|(255&r[t+3])<<8)<<3))*(5*Z),y+=(M+=8191&(o>>>10|(i=255&r[t+4]|(255&r[t+5])<<8)<<6))*(5*I),y+=(m+=8191&(i>>>7|(h=255&r[t+6]|(255&r[t+7])<<8)<<9))*(5*F),c=(y+=(B+=8191&(h>>>4|(a=255&r[t+8]|(255&r[t+9])<<8)<<12))*(5*C))>>>13,y&=8191,y+=(S+=a>>>1&8191)*(5*O),y+=(k+=8191&(a>>>14|(f=255&r[t+10]|(255&r[t+11])<<8)<<2))*(5*N),y+=(K+=8191&(f>>>11|(s=255&r[t+12]|(255&r[t+13])<<8)<<5))*(5*P),y+=(Y+=8191&(s>>>8|(u=255&r[t+14]|(255&r[t+15])<<8)<<8))*(5*R),l=c+=(y+=(L+=u>>>5|d)*(5*z))>>>13,l+=E*z,l+=x*T,l+=M*(5*Z),l+=m*(5*I),c=(l+=B*(5*F))>>>13,l&=8191,l+=S*(5*C),l+=k*(5*O),l+=K*(5*N),l+=Y*(5*P),c+=(l+=L*(5*R))>>>13,l&=8191,w=c,w+=E*R,w+=x*z,w+=M*T,w+=m*(5*Z),c=(w+=B*(5*I))>>>13,w&=8191,w+=S*(5*F),w+=k*(5*C),w+=K*(5*O),w+=Y*(5*N),v=c+=(w+=L*(5*P))>>>13,v+=E*P,v+=x*R,v+=M*z,v+=m*T,c=(v+=B*(5*Z))>>>13,v&=8191,v+=S*(5*I),v+=k*(5*F),v+=K*(5*C),v+=Y*(5*O),p=c+=(v+=L*(5*N))>>>13,p+=E*N,p+=x*P,p+=M*R,p+=m*z,c=(p+=B*T)>>>13,p&=8191,p+=S*(5*Z),p+=k*(5*I),p+=K*(5*F),p+=Y*(5*C),b=c+=(p+=L*(5*O))>>>13,b+=E*O,b+=x*N,b+=M*P,b+=m*R,c=(b+=B*z)>>>13,b&=8191,b+=S*T,b+=k*(5*Z),b+=K*(5*I),b+=Y*(5*F),g=c+=(b+=L*(5*C))>>>13,g+=E*C,g+=x*O,g+=M*N,g+=m*P,c=(g+=B*R)>>>13,g&=8191,g+=S*z,g+=k*T,g+=K*(5*Z),g+=Y*(5*I),A=c+=(g+=L*(5*F))>>>13,A+=E*F,A+=x*C,A+=M*O,A+=m*N,c=(A+=B*P)>>>13,A&=8191,A+=S*R,A+=k*z,A+=K*T,A+=Y*(5*Z),_=c+=(A+=L*(5*I))>>>13,_+=E*I,_+=x*F,_+=M*C,_+=m*O,c=(_+=B*N)>>>13,_&=8191,_+=S*P,_+=k*R,_+=K*z,_+=Y*T,U=c+=(_+=L*(5*Z))>>>13,U+=E*Z,U+=x*I,U+=M*F,U+=m*C,c=(U+=B*O)>>>13,U&=8191,U+=S*N,U+=k*P,U+=K*R,U+=Y*z,E=y=8191&(c=(c=((c+=(U+=L*T)>>>13)<<2)+c|0)+(y&=8191)|0),x=l+=c>>>=13,M=w&=8191,m=v&=8191,B=p&=8191,S=b&=8191,k=g&=8191,K=A&=8191,Y=_&=8191,L=U&=8191,t+=16,n-=16;this.h[0]=E,this.h[1]=x,this.h[2]=M,this.h[3]=m,this.h[4]=B,this.h[5]=S,this.h[6]=k,this.h[7]=K,this.h[8]=Y,this.h[9]=L},m.prototype.finish=function(r,t){var n,e,o,i,h=new Uint16Array(10);if(this.leftover){for(i=this.leftover,this.buffer[i++]=1;i<16;i++)this.buffer[i]=0;this.fin=1,this.blocks(this.buffer,0,16)}for(n=this.h[1]>>>13,this.h[1]&=8191,i=2;i<10;i++)this.h[i]+=n,n=this.h[i]>>>13,this.h[i]&=8191;for(this.h[0]+=5*n,n=this.h[0]>>>13,this.h[0]&=8191,this.h[1]+=n,n=this.h[1]>>>13,this.h[1]&=8191,this.h[2]+=n,h[0]=this.h[0]+5,n=h[0]>>>13,h[0]&=8191,i=1;i<10;i++)h[i]=this.h[i]+n,n=h[i]>>>13,h[i]&=8191;for(h[9]-=8192,e=(1^n)-1,i=0;i<10;i++)h[i]&=e;for(e=~e,i=0;i<10;i++)this.h[i]=this.h[i]&e|h[i];for(this.h[0]=65535&(this.h[0]|this.h[1]<<13),this.h[1]=65535&(this.h[1]>>>3|this.h[2]<<10),this.h[2]=65535&(this.h[2]>>>6|this.h[3]<<7),this.h[3]=65535&(this.h[3]>>>9|this.h[4]<<4),this.h[4]=65535&(this.h[4]>>>12|this.h[5]<<1|this.h[6]<<14),this.h[5]=65535&(this.h[6]>>>2|this.h[7]<<11),this.h[6]=65535&(this.h[7]>>>5|this.h[8]<<8),this.h[7]=65535&(this.h[8]>>>8|this.h[9]<<5),o=this.h[0]+this.pad[0],this.h[0]=65535&o,i=1;i<8;i++)o=(this.h[i]+this.pad[i]|0)+(o>>>16)|0,this.h[i]=65535&o;r[t+0]=this.h[0]>>>0&255,r[t+1]=this.h[0]>>>8&255,r[t+2]=this.h[1]>>>0&255,r[t+3]=this.h[1]>>>8&255,r[t+4]=this.h[2]>>>0&255,r[t+5]=this.h[2]>>>8&255,r[t+6]=this.h[3]>>>0&255,r[t+7]=this.h[3]>>>8&255,r[t+8]=this.h[4]>>>0&255,r[t+9]=this.h[4]>>>8&255,r[t+10]=this.h[5]>>>0&255,r[t+11]=this.h[5]>>>8&255,r[t+12]=this.h[6]>>>0&255,r[t+13]=this.h[6]>>>8&255,r[t+14]=this.h[7]>>>0&255,r[t+15]=this.h[7]>>>8&255},m.prototype.update=function(r,t,n){var e,o;if(this.leftover){for(n<(o=16-this.leftover)&&(o=n),e=0;e>>16,m=65535&(d=N),B=d>>>16,x+=65535&(E=((w=Z)>>>14|(a=z)<<18)^(Z>>>18|z<<14)^(z>>>9|Z<<23)),M+=E>>>16,m+=65535&(d=(z>>>14|Z<<18)^(z>>>18|Z<<14)^(Z>>>9|z<<23)),B+=d>>>16,x+=65535&(E=Z&(v=G)^~Z&(p=q)),M+=E>>>16,m+=65535&(d=z&(f=R)^~z&(s=P)),B+=d>>>16,d=J[2*_],x+=65535&(E=J[2*_+1]),M+=E>>>16,m+=65535&d,B+=d>>>16,d=S[_%16],M+=(E=k[_%16])>>>16,m+=65535&d,B+=d>>>16,m+=(M+=(x+=65535&E)>>>16)>>>16,x=65535&(E=A=65535&x|M<<16),M=E>>>16,m=65535&(d=g=65535&m|(B+=m>>>16)<<16),B=d>>>16,x+=65535&(E=(O>>>28|K<<4)^(K>>>2|O<<30)^(K>>>7|O<<25)),M+=E>>>16,m+=65535&(d=(K>>>28|O<<4)^(O>>>2|K<<30)^(O>>>7|K<<25)),B+=d>>>16,M+=(E=O&C^O&F^C&F)>>>16,m+=65535&(d=K&Y^K&L^Y&L),B+=d>>>16,u=65535&(m+=(M+=(x+=65535&E)>>>16)>>>16)|(B+=m>>>16)<<16,b=65535&x|M<<16,x=65535&(E=l),M=E>>>16,m=65535&(d=h),B=d>>>16,M+=(E=A)>>>16,m+=65535&(d=g),B+=d>>>16,Y=K,L=o,T=i,z=h=65535&(m+=(M+=(x+=65535&E)>>>16)>>>16)|(B+=m>>>16)<<16,R=a,P=f,N=s,K=u,C=O,F=c,I=y,Z=l=65535&x|M<<16,G=w,q=v,D=p,O=b,_%16==15)for(U=0;U<16;U++)d=S[U],x=65535&(E=k[U]),M=E>>>16,m=65535&d,B=d>>>16,d=S[(U+9)%16],x+=65535&(E=k[(U+9)%16]),M+=E>>>16,m+=65535&d,B+=d>>>16,g=S[(U+1)%16],x+=65535&(E=((A=k[(U+1)%16])>>>1|g<<31)^(A>>>8|g<<24)^(A>>>7|g<<25)),M+=E>>>16,m+=65535&(d=(g>>>1|A<<31)^(g>>>8|A<<24)^g>>>7),B+=d>>>16,g=S[(U+14)%16],M+=(E=((A=k[(U+14)%16])>>>19|g<<13)^(g>>>29|A<<3)^(A>>>6|g<<26))>>>16,m+=65535&(d=(g>>>19|A<<13)^(A>>>29|g<<3)^g>>>6),B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,S[U]=65535&m|B<<16,k[U]=65535&x|M<<16;x=65535&(E=O),M=E>>>16,m=65535&(d=K),B=d>>>16,d=r[0],M+=(E=t[0])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[0]=K=65535&m|B<<16,t[0]=O=65535&x|M<<16,x=65535&(E=C),M=E>>>16,m=65535&(d=Y),B=d>>>16,d=r[1],M+=(E=t[1])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[1]=Y=65535&m|B<<16,t[1]=C=65535&x|M<<16,x=65535&(E=F),M=E>>>16,m=65535&(d=L),B=d>>>16,d=r[2],M+=(E=t[2])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[2]=L=65535&m|B<<16,t[2]=F=65535&x|M<<16,x=65535&(E=I),M=E>>>16,m=65535&(d=T),B=d>>>16,d=r[3],M+=(E=t[3])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[3]=T=65535&m|B<<16,t[3]=I=65535&x|M<<16,x=65535&(E=Z),M=E>>>16,m=65535&(d=z),B=d>>>16,d=r[4],M+=(E=t[4])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[4]=z=65535&m|B<<16,t[4]=Z=65535&x|M<<16,x=65535&(E=G),M=E>>>16,m=65535&(d=R),B=d>>>16,d=r[5],M+=(E=t[5])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[5]=R=65535&m|B<<16,t[5]=G=65535&x|M<<16,x=65535&(E=q),M=E>>>16,m=65535&(d=P),B=d>>>16,d=r[6],M+=(E=t[6])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[6]=P=65535&m|B<<16,t[6]=q=65535&x|M<<16,x=65535&(E=D),M=E>>>16,m=65535&(d=N),B=d>>>16,d=r[7],M+=(E=t[7])>>>16,m+=65535&d,B+=d>>>16,B+=(m+=(M+=(x+=65535&E)>>>16)>>>16)>>>16,r[7]=N=65535&m|B<<16,t[7]=D=65535&x|M<<16,V+=128,e-=128}return e}function W(r,t,n){var e,o=new Int32Array(8),i=new Int32Array(8),h=new Uint8Array(256),a=n;for(o[0]=1779033703,o[1]=3144134277,o[2]=1013904242,o[3]=2773480762,o[4]=1359893119,o[5]=2600822924,o[6]=528734635,o[7]=1541459225,i[0]=4089235720,i[1]=2227873595,i[2]=4271175723,i[3]=1595750129,i[4]=2917565137,i[5]=725511199,i[6]=4215389547,i[7]=327033209,Q(o,i,t,n),n%=128,e=0;e>(7&o)&1),$(t,r),$(r,r),rr(r,t,e)}function er(r,t){var n=[v(),v(),v(),v()];Y(n[0],e),Y(n[1],a),Y(n[2],u),F(n[3],e,a),nr(r,n,t)}function or(r,t,n){var e,o=new Uint8Array(64),i=[v(),v(),v(),v()];for(n||h(t,32),W(o,t,32),o[0]&=248,o[31]&=127,o[31]|=64,er(i,o),tr(r,i),e=0;e<32;e++)t[e+32]=r[e];return 0}var ir=new Float64Array([237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16]);function hr(r,t){var n,e,o,i;for(e=63;32<=e;--e){for(n=0,o=e-32,i=e-12;o>4)*ir[o],n=t[o]>>8,t[o]&=255;for(o=0;o<32;o++)t[o]-=n*ir[o];for(e=0;e<32;e++)t[e+1]+=t[e]>>8,r[e]=255&t[e]}function ar(r){var t,n=new Float64Array(64);for(t=0;t<64;t++)n[t]=r[t];for(t=0;t<64;t++)r[t]=0;hr(r,n)}function fr(r,t,n,e){var o,i,h=new Uint8Array(64),a=new Uint8Array(64),f=new Uint8Array(64),s=new Float64Array(64),u=[v(),v(),v(),v()];W(h,e,32),h[0]&=248,h[31]&=127,h[31]|=64;var c=n+64;for(o=0;o>7&&C(r[0],s,r[0]),F(r[3],r[0],r[1])}(f,e))return-1;for(o=0;o void): void; +} diff --git a/node_modules/tweetnacl/nacl.js b/node_modules/tweetnacl/nacl.js new file mode 100644 index 0000000..fd8e678 --- /dev/null +++ b/node_modules/tweetnacl/nacl.js @@ -0,0 +1,1178 @@ +(function(nacl) { +'use strict'; + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var u64 = function(h, l) { this.hi = h|0 >>> 0; this.lo = l|0 >>> 0; }; +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _0 = new Uint8Array(16); +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function L32(x, c) { return (x << c) | (x >>> (32 - c)); } + +function ld32(x, i) { + var u = x[i+3] & 0xff; + u = (u<<8)|(x[i+2] & 0xff); + u = (u<<8)|(x[i+1] & 0xff); + return (u<<8)|(x[i+0] & 0xff); +} + +function dl64(x, i) { + var h = (x[i] << 24) | (x[i+1] << 16) | (x[i+2] << 8) | x[i+3]; + var l = (x[i+4] << 24) | (x[i+5] << 16) | (x[i+6] << 8) | x[i+7]; + return new u64(h, l); +} + +function st32(x, j, u) { + var i; + for (i = 0; i < 4; i++) { x[j+i] = u & 255; u >>>= 8; } +} + +function ts64(x, i, u) { + x[i] = (u.hi >> 24) & 0xff; + x[i+1] = (u.hi >> 16) & 0xff; + x[i+2] = (u.hi >> 8) & 0xff; + x[i+3] = u.hi & 0xff; + x[i+4] = (u.lo >> 24) & 0xff; + x[i+5] = (u.lo >> 16) & 0xff; + x[i+6] = (u.lo >> 8) & 0xff; + x[i+7] = u.lo & 0xff; +} + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_16(x, xi, y, yi) { + return vn(x,xi,y,yi,16); +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function core(out,inp,k,c,h) { + var w = new Uint32Array(16), x = new Uint32Array(16), + y = new Uint32Array(16), t = new Uint32Array(4); + var i, j, m; + + for (i = 0; i < 4; i++) { + x[5*i] = ld32(c, 4*i); + x[1+i] = ld32(k, 4*i); + x[6+i] = ld32(inp, 4*i); + x[11+i] = ld32(k, 16+4*i); + } + + for (i = 0; i < 16; i++) y[i] = x[i]; + + for (i = 0; i < 20; i++) { + for (j = 0; j < 4; j++) { + for (m = 0; m < 4; m++) t[m] = x[(5*j+4*m)%16]; + t[1] ^= L32((t[0]+t[3])|0, 7); + t[2] ^= L32((t[1]+t[0])|0, 9); + t[3] ^= L32((t[2]+t[1])|0,13); + t[0] ^= L32((t[3]+t[2])|0,18); + for (m = 0; m < 4; m++) w[4*j+(j+m)%4] = t[m]; + } + for (m = 0; m < 16; m++) x[m] = w[m]; + } + + if (h) { + for (i = 0; i < 16; i++) x[i] = (x[i] + y[i]) | 0; + for (i = 0; i < 4; i++) { + x[5*i] = (x[5*i] - ld32(c, 4*i)) | 0; + x[6+i] = (x[6+i] - ld32(inp, 4*i)) | 0; + } + for (i = 0; i < 4; i++) { + st32(out,4*i,x[5*i]); + st32(out,16+4*i,x[6+i]); + } + } else { + for (i = 0; i < 16; i++) st32(out, 4 * i, (x[i] + y[i]) | 0); + } +} + +function crypto_core_salsa20(out,inp,k,c) { + core(out,inp,k,c,false); + return 0; +} + +function crypto_core_hsalsa20(out,inp,k,c) { + core(out,inp,k,c,true); + return 0; +} + +var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); + // "expand 32-byte k" + +function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + if (!b) return 0; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + if (m) mpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; + } + return 0; +} + +function crypto_stream_salsa20(c,cpos,d,n,k) { + return crypto_stream_salsa20_xor(c,cpos,null,0,d,n,k); +} + +function crypto_stream(c,cpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20(c,cpos,d,n.subarray(16),s); +} + +function crypto_stream_xor(c,cpos,m,mpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,n.subarray(16),s); +} + +function add1305(h, c) { + var j, u = 0; + for (j = 0; j < 17; j++) { + u = (u + ((h[j] + c[j]) | 0)) | 0; + h[j] = u & 255; + u >>>= 8; + } +} + +var minusp = new Uint32Array([ + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +]); + +function crypto_onetimeauth(out, outpos, m, mpos, n, k) { + var s, i, j, u; + var x = new Uint32Array(17), r = new Uint32Array(17), + h = new Uint32Array(17), c = new Uint32Array(17), + g = new Uint32Array(17); + for (j = 0; j < 17; j++) r[j]=h[j]=0; + for (j = 0; j < 16; j++) r[j]=k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + for (j = 0; j < 17; j++) c[j] = 0; + for (j = 0; (j < 16) && (j < n); ++j) c[j] = m[mpos+j]; + c[j] = 1; + mpos += j; n -= j; + add1305(h,c); + for (i = 0; i < 17; i++) { + x[i] = 0; + for (j = 0; j < 17; j++) x[i] = (x[i] + (h[j] * ((j <= i) ? r[i - j] : ((320 * r[i + 17 - j])|0))) | 0) | 0; + } + for (i = 0; i < 17; i++) h[i] = x[i]; + u = 0; + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0; + h[j] = u & 255; + u >>>= 8; + } + u = (u + h[16]) | 0; h[16] = u & 3; + u = (5 * (u >>> 2)) | 0; + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0; + h[j] = u & 255; + u >>>= 8; + } + u = (u + h[16]) | 0; h[16] = u; + } + + for (j = 0; j < 17; j++) g[j] = h[j]; + add1305(h,minusp); + s = (-(h[16] >>> 7) | 0); + for (j = 0; j < 17; j++) h[j] ^= s & (g[j] ^ h[j]); + + for (j = 0; j < 16; j++) c[j] = k[j + 16]; + c[16] = 0; + add1305(h,c); + for (j = 0; j < 16; j++) out[outpos+j] = h[j]; + return 0; +} + +function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { + var x = new Uint8Array(16); + crypto_onetimeauth(x,0,m,mpos,n,k); + return crypto_verify_16(h,hpos,x,0); +} + +function crypto_secretbox(c,m,d,n,k) { + var i; + if (d < 32) return -1; + crypto_stream_xor(c,0,m,0,d,n,k); + crypto_onetimeauth(c, 16, c, 32, d - 32, c); + for (i = 0; i < 16; i++) c[i] = 0; + return 0; +} + +function crypto_secretbox_open(m,c,d,n,k) { + var i; + var x = new Uint8Array(32); + if (d < 32) return -1; + crypto_stream(x,0,32,n,k); + if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; + crypto_stream_xor(m,0,c,0,d,n,k); + for (i = 0; i < 32; i++) m[i] = 0; + return 0; +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var c; + var i; + for (i = 0; i < 16; i++) { + o[i] += 65536; + c = Math.floor(o[i] / 65536); + o[(i+1)*(i<15?1:0)] += c - 1 + 37 * (c-1) * (i===15?1:0); + o[i] -= (c * 65536); + } +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + var i; + for (i = 0; i < 16; i++) o[i] = (a[i] + b[i])|0; +} + +function Z(o, a, b) { + var i; + for (i = 0; i < 16; i++) o[i] = (a[i] - b[i])|0; +} + +function M(o, a, b) { + var i, j, t = new Float64Array(31); + for (i = 0; i < 31; i++) t[i] = 0; + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + t[i+j] += a[i] * b[j]; + } + } + for (i = 0; i < 15; i++) { + t[i] += 38 * t[i+16]; + } + for (i = 0; i < 16; i++) o[i] = t[i]; + car25519(o); + car25519(o); +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function crypto_box_beforenm(k, y, x) { + var s = new Uint8Array(32); + crypto_scalarmult(s, x, y); + return crypto_core_hsalsa20(k, _0, s, sigma); +} + +var crypto_box_afternm = crypto_secretbox; +var crypto_box_open_afternm = crypto_secretbox_open; + +function crypto_box(c, m, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +function crypto_box_open(m, c, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_open_afternm(m, c, d, n, k); +} + +function add64() { + var a = 0, b = 0, c = 0, d = 0, m16 = 65535, l, h, i; + for (i = 0; i < arguments.length; i++) { + l = arguments[i].lo; + h = arguments[i].hi; + a += (l & m16); b += (l >>> 16); + c += (h & m16); d += (h >>> 16); + } + + b += (a >>> 16); + c += (b >>> 16); + d += (c >>> 16); + + return new u64((c & m16) | (d << 16), (a & m16) | (b << 16)); +} + +function shr64(x, c) { + return new u64((x.hi >>> c), (x.lo >>> c) | (x.hi << (32 - c))); +} + +function xor64() { + var l = 0, h = 0, i; + for (i = 0; i < arguments.length; i++) { + l ^= arguments[i].lo; + h ^= arguments[i].hi; + } + return new u64(h, l); +} + +function R(x, c) { + var h, l, c1 = 32 - c; + if (c < 32) { + h = (x.hi >>> c) | (x.lo << c1); + l = (x.lo >>> c) | (x.hi << c1); + } else if (c < 64) { + h = (x.lo >>> c) | (x.hi << c1); + l = (x.hi >>> c) | (x.lo << c1); + } + return new u64(h, l); +} + +function Ch(x, y, z) { + var h = (x.hi & y.hi) ^ (~x.hi & z.hi), + l = (x.lo & y.lo) ^ (~x.lo & z.lo); + return new u64(h, l); +} + +function Maj(x, y, z) { + var h = (x.hi & y.hi) ^ (x.hi & z.hi) ^ (y.hi & z.hi), + l = (x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo); + return new u64(h, l); +} + +function Sigma0(x) { return xor64(R(x,28), R(x,34), R(x,39)); } +function Sigma1(x) { return xor64(R(x,14), R(x,18), R(x,41)); } +function sigma0(x) { return xor64(R(x, 1), R(x, 8), shr64(x,7)); } +function sigma1(x) { return xor64(R(x,19), R(x,61), shr64(x,6)); } + +var K = [ + new u64(0x428a2f98, 0xd728ae22), new u64(0x71374491, 0x23ef65cd), + new u64(0xb5c0fbcf, 0xec4d3b2f), new u64(0xe9b5dba5, 0x8189dbbc), + new u64(0x3956c25b, 0xf348b538), new u64(0x59f111f1, 0xb605d019), + new u64(0x923f82a4, 0xaf194f9b), new u64(0xab1c5ed5, 0xda6d8118), + new u64(0xd807aa98, 0xa3030242), new u64(0x12835b01, 0x45706fbe), + new u64(0x243185be, 0x4ee4b28c), new u64(0x550c7dc3, 0xd5ffb4e2), + new u64(0x72be5d74, 0xf27b896f), new u64(0x80deb1fe, 0x3b1696b1), + new u64(0x9bdc06a7, 0x25c71235), new u64(0xc19bf174, 0xcf692694), + new u64(0xe49b69c1, 0x9ef14ad2), new u64(0xefbe4786, 0x384f25e3), + new u64(0x0fc19dc6, 0x8b8cd5b5), new u64(0x240ca1cc, 0x77ac9c65), + new u64(0x2de92c6f, 0x592b0275), new u64(0x4a7484aa, 0x6ea6e483), + new u64(0x5cb0a9dc, 0xbd41fbd4), new u64(0x76f988da, 0x831153b5), + new u64(0x983e5152, 0xee66dfab), new u64(0xa831c66d, 0x2db43210), + new u64(0xb00327c8, 0x98fb213f), new u64(0xbf597fc7, 0xbeef0ee4), + new u64(0xc6e00bf3, 0x3da88fc2), new u64(0xd5a79147, 0x930aa725), + new u64(0x06ca6351, 0xe003826f), new u64(0x14292967, 0x0a0e6e70), + new u64(0x27b70a85, 0x46d22ffc), new u64(0x2e1b2138, 0x5c26c926), + new u64(0x4d2c6dfc, 0x5ac42aed), new u64(0x53380d13, 0x9d95b3df), + new u64(0x650a7354, 0x8baf63de), new u64(0x766a0abb, 0x3c77b2a8), + new u64(0x81c2c92e, 0x47edaee6), new u64(0x92722c85, 0x1482353b), + new u64(0xa2bfe8a1, 0x4cf10364), new u64(0xa81a664b, 0xbc423001), + new u64(0xc24b8b70, 0xd0f89791), new u64(0xc76c51a3, 0x0654be30), + new u64(0xd192e819, 0xd6ef5218), new u64(0xd6990624, 0x5565a910), + new u64(0xf40e3585, 0x5771202a), new u64(0x106aa070, 0x32bbd1b8), + new u64(0x19a4c116, 0xb8d2d0c8), new u64(0x1e376c08, 0x5141ab53), + new u64(0x2748774c, 0xdf8eeb99), new u64(0x34b0bcb5, 0xe19b48a8), + new u64(0x391c0cb3, 0xc5c95a63), new u64(0x4ed8aa4a, 0xe3418acb), + new u64(0x5b9cca4f, 0x7763e373), new u64(0x682e6ff3, 0xd6b2b8a3), + new u64(0x748f82ee, 0x5defb2fc), new u64(0x78a5636f, 0x43172f60), + new u64(0x84c87814, 0xa1f0ab72), new u64(0x8cc70208, 0x1a6439ec), + new u64(0x90befffa, 0x23631e28), new u64(0xa4506ceb, 0xde82bde9), + new u64(0xbef9a3f7, 0xb2c67915), new u64(0xc67178f2, 0xe372532b), + new u64(0xca273ece, 0xea26619c), new u64(0xd186b8c7, 0x21c0c207), + new u64(0xeada7dd6, 0xcde0eb1e), new u64(0xf57d4f7f, 0xee6ed178), + new u64(0x06f067aa, 0x72176fba), new u64(0x0a637dc5, 0xa2c898a6), + new u64(0x113f9804, 0xbef90dae), new u64(0x1b710b35, 0x131c471b), + new u64(0x28db77f5, 0x23047d84), new u64(0x32caab7b, 0x40c72493), + new u64(0x3c9ebe0a, 0x15c9bebc), new u64(0x431d67c4, 0x9c100d4c), + new u64(0x4cc5d4be, 0xcb3e42b6), new u64(0x597f299c, 0xfc657e2a), + new u64(0x5fcb6fab, 0x3ad6faec), new u64(0x6c44198c, 0x4a475817) +]; + +function crypto_hashblocks(x, m, n) { + var z = [], b = [], a = [], w = [], t, i, j; + + for (i = 0; i < 8; i++) z[i] = a[i] = dl64(x, 8*i); + + var pos = 0; + while (n >= 128) { + for (i = 0; i < 16; i++) w[i] = dl64(m, 8*i+pos); + for (i = 0; i < 80; i++) { + for (j = 0; j < 8; j++) b[j] = a[j]; + t = add64(a[7], Sigma1(a[4]), Ch(a[4], a[5], a[6]), K[i], w[i%16]); + b[7] = add64(t, Sigma0(a[0]), Maj(a[0], a[1], a[2])); + b[3] = add64(b[3], t); + for (j = 0; j < 8; j++) a[(j+1)%8] = b[j]; + if (i%16 === 15) { + for (j = 0; j < 16; j++) { + w[j] = add64(w[j], w[(j+9)%16], sigma0(w[(j+1)%16]), sigma1(w[(j+14)%16])); + } + } + } + + for (i = 0; i < 8; i++) { + a[i] = add64(a[i], z[i]); + z[i] = a[i]; + } + + pos += 128; + n -= 128; + } + + for (i = 0; i < 8; i++) ts64(x, 8*i, z[i]); + return n; +} + +var iv = new Uint8Array([ + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +]); + +function crypto_hash(out, m, n) { + var h = new Uint8Array(64), x = new Uint8Array(256); + var i, b = n; + + for (i = 0; i < 64; i++) h[i] = iv[i]; + + crypto_hashblocks(h, m, n); + n %= 128; + + for (i = 0; i < 256; i++) x[i] = 0; + for (i = 0; i < n; i++) x[i] = m[b-n+i]; + x[n] = 128; + + n = 256-128*(n<112?1:0); + x[n-9] = 0; + ts64(x, n-8, new u64((b / 0x20000000) | 0, b << 3)); + crypto_hashblocks(h, x, n); + + for (i = 0; i < 64; i++) out[i] = h[i]; + + return 0; +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm.subarray(32), n+32); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + crypto_hash(h, sm, n + 64); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + crypto_hash(h, m, n); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; +} + +var crypto_secretbox_KEYBYTES = 32, + crypto_secretbox_NONCEBYTES = 24, + crypto_secretbox_ZEROBYTES = 32, + crypto_secretbox_BOXZEROBYTES = 16, + crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_box_BEFORENMBYTES = 32, + crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, + crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, + crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64; + +nacl.lowlevel = { + crypto_core_hsalsa20: crypto_core_hsalsa20, + crypto_stream_xor: crypto_stream_xor, + crypto_stream: crypto_stream, + crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, + crypto_stream_salsa20: crypto_stream_salsa20, + crypto_onetimeauth: crypto_onetimeauth, + crypto_onetimeauth_verify: crypto_onetimeauth_verify, + crypto_verify_16: crypto_verify_16, + crypto_verify_32: crypto_verify_32, + crypto_secretbox: crypto_secretbox, + crypto_secretbox_open: crypto_secretbox_open, + crypto_scalarmult: crypto_scalarmult, + crypto_scalarmult_base: crypto_scalarmult_base, + crypto_box_beforenm: crypto_box_beforenm, + crypto_box_afternm: crypto_box_afternm, + crypto_box: crypto_box, + crypto_box_open: crypto_box_open, + crypto_box_keypair: crypto_box_keypair, + crypto_hash: crypto_hash, + crypto_sign: crypto_sign, + crypto_sign_keypair: crypto_sign_keypair, + crypto_sign_open: crypto_sign_open, + + crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, + crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, + crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, + crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, + crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, + crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, + crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, + crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, + crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, + crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, + crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, + crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, + crypto_sign_BYTES: crypto_sign_BYTES, + crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, + crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, + crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, + crypto_hash_BYTES: crypto_hash_BYTES, + + gf: gf, + D: D, + L: L, + pack25519: pack25519, + unpack25519: unpack25519, + M: M, + A: A, + S: S, + Z: Z, + pow2523: pow2523, + add: add, + set25519: set25519, + modL: modL, + scalarmult: scalarmult, + scalarbase: scalarbase, +}; + +/* High-level API */ + +function checkLengths(k, n) { + if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); + if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); +} + +function checkBoxLengths(pk, sk) { + if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); + if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); +} + +function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +nacl.randomBytes = function(n) { + var b = new Uint8Array(n); + randombytes(b, n); + return b; +}; + +nacl.secretbox = function(msg, nonce, key) { + checkArrayTypes(msg, nonce, key); + checkLengths(key, nonce); + var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); + var c = new Uint8Array(m.length); + for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + crypto_secretbox(c, m, m.length, nonce, key); + return c.subarray(crypto_secretbox_BOXZEROBYTES); +}; + +nacl.secretbox.open = function(box, nonce, key) { + checkArrayTypes(box, nonce, key); + checkLengths(key, nonce); + var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); + var m = new Uint8Array(c.length); + for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + if (c.length < 32) return null; + if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null; + return m.subarray(crypto_secretbox_ZEROBYTES); +}; + +nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; +nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; +nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.scalarMult.base = function(n) { + checkArrayTypes(n); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult_base(q, n); + return q; +}; + +nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; +nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; + +nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox(msg, nonce, k); +}; + +nacl.box.before = function(publicKey, secretKey) { + checkArrayTypes(publicKey, secretKey); + checkBoxLengths(publicKey, secretKey); + var k = new Uint8Array(crypto_box_BEFORENMBYTES); + crypto_box_beforenm(k, publicKey, secretKey); + return k; +}; + +nacl.box.after = nacl.secretbox; + +nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox.open(msg, nonce, k); +}; + +nacl.box.open.after = nacl.secretbox.open; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; +nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; +nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; +nacl.box.nonceLength = crypto_box_NONCEBYTES; +nacl.box.overheadLength = nacl.secretbox.overheadLength; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.open = function(signedMsg, publicKey) { + checkArrayTypes(signedMsg, publicKey); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var tmp = new Uint8Array(signedMsg.length); + var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); + if (mlen < 0) return null; + var m = new Uint8Array(mlen); + for (var i = 0; i < m.length; i++) m[i] = tmp[i]; + return m; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; +nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; +nacl.sign.seedLength = crypto_sign_SEEDBYTES; +nacl.sign.signatureLength = crypto_sign_BYTES; + +nacl.hash = function(msg) { + checkArrayTypes(msg); + var h = new Uint8Array(crypto_hash_BYTES); + crypto_hash(h, msg, msg.length); + return h; +}; + +nacl.hash.hashLength = crypto_hash_BYTES; + +nacl.verify = function(x, y) { + checkArrayTypes(x, y); + // Zero length arguments are considered not equal. + if (x.length === 0 || y.length === 0) return false; + if (x.length !== y.length) return false; + return (vn(x, 0, y, 0, x.length) === 0) ? true : false; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof require !== 'undefined') { + // Node.js. + crypto = require('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); diff --git a/node_modules/tweetnacl/nacl.min.js b/node_modules/tweetnacl/nacl.min.js new file mode 100644 index 0000000..65340cc --- /dev/null +++ b/node_modules/tweetnacl/nacl.min.js @@ -0,0 +1 @@ +!function(i){"use strict";var m=function(r,n){this.hi=0|r,this.lo=0|n},v=function(r){var n,e=new Float64Array(16);if(r)for(n=0;n>>32-n}function b(r,n){var e=255&r[n+3];return(e=(e=e<<8|255&r[n+2])<<8|255&r[n+1])<<8|255&r[n+0]}function B(r,n){var e=r[n]<<24|r[n+1]<<16|r[n+2]<<8|r[n+3],t=r[n+4]<<24|r[n+5]<<16|r[n+6]<<8|r[n+7];return new m(e,t)}function p(r,n,e){var t;for(t=0;t<4;t++)r[n+t]=255&e,e>>>=8}function S(r,n,e){r[n]=e.hi>>24&255,r[n+1]=e.hi>>16&255,r[n+2]=e.hi>>8&255,r[n+3]=255&e.hi,r[n+4]=e.lo>>24&255,r[n+5]=e.lo>>16&255,r[n+6]=e.lo>>8&255,r[n+7]=255&e.lo}function u(r,n,e,t,o){var i,a=0;for(i=0;i>>8)-1}function A(r,n,e,t){return u(r,n,e,t,16)}function _(r,n,e,t){return u(r,n,e,t,32)}function U(r,n,e,t,o){var i,a,f,u=new Uint32Array(16),c=new Uint32Array(16),w=new Uint32Array(16),y=new Uint32Array(4);for(i=0;i<4;i++)c[5*i]=b(t,4*i),c[1+i]=b(e,4*i),c[6+i]=b(n,4*i),c[11+i]=b(e,16+4*i);for(i=0;i<16;i++)w[i]=c[i];for(i=0;i<20;i++){for(a=0;a<4;a++){for(f=0;f<4;f++)y[f]=c[(5*a+4*f)%16];for(y[1]^=h(y[0]+y[3]|0,7),y[2]^=h(y[1]+y[0]|0,9),y[3]^=h(y[2]+y[1]|0,13),y[0]^=h(y[3]+y[2]|0,18),f=0;f<4;f++)u[4*a+(a+f)%4]=y[f]}for(f=0;f<16;f++)c[f]=u[f]}if(o){for(i=0;i<16;i++)c[i]=c[i]+w[i]|0;for(i=0;i<4;i++)c[5*i]=c[5*i]-b(t,4*i)|0,c[6+i]=c[6+i]-b(n,4*i)|0;for(i=0;i<4;i++)p(r,4*i,c[5*i]),p(r,16+4*i,c[6+i])}else for(i=0;i<16;i++)p(r,4*i,c[i]+w[i]|0)}function E(r,n,e,t){U(r,n,e,t,!1)}function x(r,n,e,t){return U(r,n,e,t,!0),0}var d=new Uint8Array([101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107]);function K(r,n,e,t,o,i,a){var f,u,c=new Uint8Array(16),w=new Uint8Array(64);if(!o)return 0;for(u=0;u<16;u++)c[u]=0;for(u=0;u<8;u++)c[u]=i[u];for(;64<=o;){for(E(w,c,a,d),u=0;u<64;u++)r[n+u]=(e?e[t+u]:0)^w[u];for(f=1,u=8;u<16;u++)f=f+(255&c[u])|0,c[u]=255&f,f>>>=8;o-=64,n+=64,e&&(t+=64)}if(0>>=8}var z=new Uint32Array([5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252]);function R(r,n,e,t,o,i){var a,f,u,c,w=new Uint32Array(17),y=new Uint32Array(17),l=new Uint32Array(17),s=new Uint32Array(17),h=new Uint32Array(17);for(u=0;u<17;u++)y[u]=l[u]=0;for(u=0;u<16;u++)y[u]=i[u];for(y[3]&=15,y[4]&=252,y[7]&=15,y[8]&=252,y[11]&=15,y[12]&=252,y[15]&=15;0>>=8;for(c=c+l[16]|0,l[16]=3&c,c=5*(c>>>2)|0,u=0;u<16;u++)c=c+l[u]|0,l[u]=255&c,c>>>=8;c=c+l[16]|0,l[16]=c}for(u=0;u<17;u++)h[u]=l[u];for(k(l,z),a=0|-(l[16]>>>7),u=0;u<17;u++)l[u]^=a&(h[u]^l[u]);for(u=0;u<16;u++)s[u]=i[u+16];for(s[16]=0,k(l,s),u=0;u<16;u++)r[n+u]=l[u];return 0}function P(r,n,e,t,o,i){var a=new Uint8Array(16);return R(a,0,e,t,o,i),A(r,n,a,0)}function M(r,n,e,t,o){var i;if(e<32)return-1;for(T(r,0,n,0,e,t,o),R(r,16,r,32,e-32,r),i=0;i<16;i++)r[i]=0;return 0}function N(r,n,e,t,o){var i,a=new Uint8Array(32);if(e<32)return-1;if(L(a,0,32,t,o),0!==P(n,16,n,32,e-32,a))return-1;for(T(r,0,n,0,e,t,o),i=0;i<32;i++)r[i]=0;return 0}function O(r,n){var e;for(e=0;e<16;e++)r[e]=0|n[e]}function C(r){var n,e;for(e=0;e<16;e++)r[e]+=65536,n=Math.floor(r[e]/65536),r[(e+1)*(e<15?1:0)]+=n-1+37*(n-1)*(15===e?1:0),r[e]-=65536*n}function F(r,n,e){for(var t,o=~(e-1),i=0;i<16;i++)t=o&(r[i]^n[i]),r[i]^=t,n[i]^=t}function Z(r,n){var e,t,o,i=v(),a=v();for(e=0;e<16;e++)a[e]=n[e];for(C(a),C(a),C(a),t=0;t<2;t++){for(i[0]=a[0]-65517,e=1;e<15;e++)i[e]=a[e]-65535-(i[e-1]>>16&1),i[e-1]&=65535;i[15]=a[15]-32767-(i[14]>>16&1),o=i[15]>>16&1,i[14]&=65535,F(a,i,1-o)}for(e=0;e<16;e++)r[2*e]=255&a[e],r[2*e+1]=a[e]>>8}function G(r,n){var e=new Uint8Array(32),t=new Uint8Array(32);return Z(e,r),Z(t,n),_(e,0,t,0)}function q(r){var n=new Uint8Array(32);return Z(n,r),1&n[0]}function D(r,n){var e;for(e=0;e<16;e++)r[e]=n[2*e]+(n[2*e+1]<<8);r[15]&=32767}function I(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]+e[t]|0}function V(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]-e[t]|0}function X(r,n,e){var t,o,i=new Float64Array(31);for(t=0;t<31;t++)i[t]=0;for(t=0;t<16;t++)for(o=0;o<16;o++)i[t+o]+=n[t]*e[o];for(t=0;t<15;t++)i[t]+=38*i[t+16];for(t=0;t<16;t++)r[t]=i[t];C(r),C(r)}function j(r,n){X(r,n,n)}function H(r,n){var e,t=v();for(e=0;e<16;e++)t[e]=n[e];for(e=253;0<=e;e--)j(t,t),2!==e&&4!==e&&X(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function J(r,n){var e,t=v();for(e=0;e<16;e++)t[e]=n[e];for(e=250;0<=e;e--)j(t,t),1!==e&&X(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function Q(r,n,e){var t,o,i=new Uint8Array(32),a=new Float64Array(80),f=v(),u=v(),c=v(),w=v(),y=v(),l=v();for(o=0;o<31;o++)i[o]=n[o];for(i[31]=127&n[31]|64,i[0]&=248,D(a,e),o=0;o<16;o++)u[o]=a[o],w[o]=f[o]=c[o]=0;for(f[0]=w[0]=1,o=254;0<=o;--o)F(f,u,t=i[o>>>3]>>>(7&o)&1),F(c,w,t),I(y,f,c),V(f,f,c),I(c,u,w),V(u,u,w),j(w,y),j(l,f),X(f,c,f),X(c,u,y),I(y,f,c),V(f,f,c),j(u,f),V(c,w,l),X(f,c,g),I(f,f,w),X(c,c,f),X(f,w,l),X(w,u,a),j(u,y),F(f,u,t),F(c,w,t);for(o=0;o<16;o++)a[o+16]=f[o],a[o+32]=c[o],a[o+48]=u[o],a[o+64]=w[o];var s=a.subarray(32),h=a.subarray(16);return H(s,s),X(h,h,s),Z(r,h),0}function W(r,n){return Q(r,n,e)}function $(r,n){return a(n,32),W(r,n)}function rr(r,n,e){var t=new Uint8Array(32);return Q(t,e,n),x(r,o,t,d)}var nr=M,er=N;function tr(){var r,n,e,t=0,o=0,i=0,a=0,f=65535;for(e=0;e>>16,i+=(n=arguments[e].hi)&f,a+=n>>>16;return new m((i+=(o+=t>>>16)>>>16)&f|(a+=i>>>16)<<16,t&f|o<<16)}function or(r,n){return new m(r.hi>>>n,r.lo>>>n|r.hi<<32-n)}function ir(){var r,n=0,e=0;for(r=0;r>>n|r.lo<>>n|r.hi<>>n|r.hi<>>n|r.lo<>(7&o)&1),yr(n,r),yr(r,r),lr(r,n,t)}function vr(r,n){var e=[v(),v(),v(),v()];O(e[0],t),O(e[1],f),O(e[2],w),X(e[3],t,f),hr(r,e,n)}function gr(r,n,e){var t,o=new Uint8Array(64),i=[v(),v(),v(),v()];for(e||a(n,32),wr(o,n,32),o[0]&=248,o[31]&=127,o[31]|=64,vr(i,o),sr(r,i),t=0;t<32;t++)n[t+32]=r[t];return 0}var br=new Float64Array([237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16]);function pr(r,n){var e,t,o,i;for(t=63;32<=t;--t){for(e=0,o=t-32,i=t-12;o>4)*br[o],e=n[o]>>8,n[o]&=255;for(o=0;o<32;o++)n[o]-=e*br[o];for(t=0;t<32;t++)n[t+1]+=n[t]>>8,r[t]=255&n[t]}function Ar(r){var n,e=new Float64Array(64);for(n=0;n<64;n++)e[n]=r[n];for(n=0;n<64;n++)r[n]=0;pr(r,e)}function _r(r,n,e,t){var o,i,a=new Uint8Array(64),f=new Uint8Array(64),u=new Uint8Array(64),c=new Float64Array(64),w=[v(),v(),v(),v()];wr(a,t,32),a[0]&=248,a[31]&=127,a[31]|=64;var y=e+64;for(o=0;o>7&&V(r[0],c,r[0]),X(r[3],r[0],r[1])}(u,t))return-1;for(o=0;o/dev/null && browserify test/browser/init.js test/*.quick.js | uglifyjs -c -m -o test/browser/_bundle-quick.js 2>/dev/null", + "test": "npm run test-node-all", + "bench": "node test/benchmark/bench.js", + "lint": "eslint nacl.js nacl-fast.js test/*.js test/benchmark/*.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/dchest/tweetnacl-js.git" + }, + "keywords": [ + "crypto", + "cryptography", + "curve25519", + "ed25519", + "encrypt", + "hash", + "key", + "nacl", + "poly1305", + "public", + "salsa20", + "signatures" + ], + "author": "TweetNaCl-js contributors", + "license": "Unlicense", + "bugs": { + "url": "https://github.com/dchest/tweetnacl-js/issues" + }, + "homepage": "https://tweetnacl.js.org", + "devDependencies": { + "browserify": "^16.2.3", + "eslint": "^6.8.0", + "faucet": "^0.0.1", + "tap-browser-color": "^0.1.2", + "tape": "^4.13.0", + "tweetnacl-util": "^0.15.0", + "uglify-js": "^3.7.5" + }, + "browser": { + "buffer": false, + "crypto": false + } +} diff --git a/node_modules/wrappy/LICENSE b/node_modules/wrappy/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/node_modules/wrappy/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/wrappy/README.md b/node_modules/wrappy/README.md new file mode 100644 index 0000000..98eab25 --- /dev/null +++ b/node_modules/wrappy/README.md @@ -0,0 +1,36 @@ +# wrappy + +Callback wrapping utility + +## USAGE + +```javascript +var wrappy = require("wrappy") + +// var wrapper = wrappy(wrapperFunction) + +// make sure a cb is called only once +// See also: http://npm.im/once for this specific use case +var once = wrappy(function (cb) { + var called = false + return function () { + if (called) return + called = true + return cb.apply(this, arguments) + } +}) + +function printBoo () { + console.log('boo') +} +// has some rando property +printBoo.iAmBooPrinter = true + +var onlyPrintOnce = once(printBoo) + +onlyPrintOnce() // prints 'boo' +onlyPrintOnce() // does nothing + +// random property is retained! +assert.equal(onlyPrintOnce.iAmBooPrinter, true) +``` diff --git a/node_modules/wrappy/package.json b/node_modules/wrappy/package.json new file mode 100644 index 0000000..1307520 --- /dev/null +++ b/node_modules/wrappy/package.json @@ -0,0 +1,29 @@ +{ + "name": "wrappy", + "version": "1.0.2", + "description": "Callback wrapping utility", + "main": "wrappy.js", + "files": [ + "wrappy.js" + ], + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "^2.3.1" + }, + "scripts": { + "test": "tap --coverage test/*.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/npm/wrappy" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/wrappy/issues" + }, + "homepage": "https://github.com/npm/wrappy" +} diff --git a/node_modules/wrappy/wrappy.js b/node_modules/wrappy/wrappy.js new file mode 100644 index 0000000..bb7e7d6 --- /dev/null +++ b/node_modules/wrappy/wrappy.js @@ -0,0 +1,33 @@ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} diff --git a/node_modules/ws/LICENSE b/node_modules/ws/LICENSE new file mode 100644 index 0000000..a145cd1 --- /dev/null +++ b/node_modules/ws/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011 Einar Otto Stangvik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/ws/README.md b/node_modules/ws/README.md new file mode 100644 index 0000000..9c6e528 --- /dev/null +++ b/node_modules/ws/README.md @@ -0,0 +1,496 @@ +# ws: a Node.js WebSocket library + +[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws) +[![Build](https://img.shields.io/github/workflow/status/websockets/ws/CI/master?label=build&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster) +[![Windows x86 Build](https://img.shields.io/appveyor/ci/lpinca/ws/master.svg?logo=appveyor)](https://ci.appveyor.com/project/lpinca/ws) +[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/github/websockets/ws) + +ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and +server implementation. + +Passes the quite extensive Autobahn test suite: [server][server-report], +[client][client-report]. + +**Note**: This module does not work in the browser. The client in the docs is a +reference to a back end with the role of a client in the WebSocket +communication. Browser clients must use the native +[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) +object. To make the same code work seamlessly on Node.js and the browser, you +can use one of the many wrappers available on npm, like +[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws). + +## Table of Contents + +- [Protocol support](#protocol-support) +- [Installing](#installing) + - [Opt-in for performance and spec compliance](#opt-in-for-performance-and-spec-compliance) +- [API docs](#api-docs) +- [WebSocket compression](#websocket-compression) +- [Usage examples](#usage-examples) + - [Sending and receiving text data](#sending-and-receiving-text-data) + - [Sending binary data](#sending-binary-data) + - [Simple server](#simple-server) + - [External HTTP/S server](#external-https-server) + - [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server) + - [Client authentication](#client-authentication) + - [Server broadcast](#server-broadcast) + - [echo.websocket.org demo](#echowebsocketorg-demo) + - [Use the Node.js streams API](#use-the-nodejs-streams-api) + - [Other examples](#other-examples) +- [FAQ](#faq) + - [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client) + - [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections) + - [How to connect via a proxy?](#how-to-connect-via-a-proxy) +- [Changelog](#changelog) +- [License](#license) + +## Protocol support + +- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`) +- **HyBi drafts 13-17** (Current default, alternatively option + `protocolVersion: 13`) + +## Installing + +``` +npm install ws +``` + +### Opt-in for performance + +There are 2 optional modules that can be installed along side with the ws +module. These modules are binary addons which improve certain operations. +Prebuilt binaries are available for the most popular platforms so you don't +necessarily need to have a C++ compiler installed on your machine. + +- `npm install --save-optional bufferutil`: Allows to efficiently perform + operations such as masking and unmasking the data payload of the WebSocket + frames. +- `npm install --save-optional utf-8-validate`: Allows to efficiently check if a + message contains valid UTF-8. + +## API docs + +See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and +utility functions. + +## WebSocket compression + +ws supports the [permessage-deflate extension][permessage-deflate] which enables +the client and server to negotiate a compression algorithm and its parameters, +and then selectively apply it to the data payloads of each WebSocket message. + +The extension is disabled by default on the server and enabled by default on the +client. It adds a significant overhead in terms of performance and memory +consumption so we suggest to enable it only if it is really needed. + +Note that Node.js has a variety of issues with high-performance compression, +where increased concurrency, especially on Linux, can lead to [catastrophic +memory fragmentation][node-zlib-bug] and slow performance. If you intend to use +permessage-deflate in production, it is worthwhile to set up a test +representative of your workload and ensure Node.js/zlib will handle it with +acceptable performance and memory usage. + +Tuning of permessage-deflate can be done via the options defined below. You can +also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly +into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs]. + +See [the docs][ws-server-options] for more options. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ + port: 8080, + perMessageDeflate: { + zlibDeflateOptions: { + // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024 // Size (in bytes) below which messages + // should not be compressed. + } +}); +``` + +The client will only use the extension if it is supported and enabled on the +server. To always disable the extension on the client set the +`perMessageDeflate` option to `false`. + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path', { + perMessageDeflate: false +}); +``` + +## Usage examples + +### Sending and receiving text data + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + ws.send('something'); +}); + +ws.on('message', function incoming(data) { + console.log(data); +}); +``` + +### Sending binary data + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + const array = new Float32Array(5); + + for (var i = 0; i < array.length; ++i) { + array[i] = i / 2; + } + + ws.send(array); +}); +``` + +### Simple server + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + console.log('received: %s', message); + }); + + ws.send('something'); +}); +``` + +### External HTTP/S server + +```js +const fs = require('fs'); +const https = require('https'); +const WebSocket = require('ws'); + +const server = https.createServer({ + cert: fs.readFileSync('/path/to/cert.pem'), + key: fs.readFileSync('/path/to/key.pem') +}); +const wss = new WebSocket.Server({ server }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + console.log('received: %s', message); + }); + + ws.send('something'); +}); + +server.listen(8080); +``` + +### Multiple servers sharing a single HTTP/S server + +```js +const http = require('http'); +const WebSocket = require('ws'); +const url = require('url'); + +const server = http.createServer(); +const wss1 = new WebSocket.Server({ noServer: true }); +const wss2 = new WebSocket.Server({ noServer: true }); + +wss1.on('connection', function connection(ws) { + // ... +}); + +wss2.on('connection', function connection(ws) { + // ... +}); + +server.on('upgrade', function upgrade(request, socket, head) { + const pathname = url.parse(request.url).pathname; + + if (pathname === '/foo') { + wss1.handleUpgrade(request, socket, head, function done(ws) { + wss1.emit('connection', ws, request); + }); + } else if (pathname === '/bar') { + wss2.handleUpgrade(request, socket, head, function done(ws) { + wss2.emit('connection', ws, request); + }); + } else { + socket.destroy(); + } +}); + +server.listen(8080); +``` + +### Client authentication + +```js +const http = require('http'); +const WebSocket = require('ws'); + +const server = http.createServer(); +const wss = new WebSocket.Server({ noServer: true }); + +wss.on('connection', function connection(ws, request, client) { + ws.on('message', function message(msg) { + console.log(`Received message ${msg} from user ${client}`); + }); +}); + +server.on('upgrade', function upgrade(request, socket, head) { + // This function is not defined on purpose. Implement it with your own logic. + authenticate(request, (err, client) => { + if (err || !client) { + socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); + socket.destroy(); + return; + } + + wss.handleUpgrade(request, socket, head, function done(ws) { + wss.emit('connection', ws, request, client); + }); + }); +}); + +server.listen(8080); +``` + +Also see the provided [example][session-parse-example] using `express-session`. + +### Server broadcast + +A client WebSocket broadcasting to all connected WebSocket clients, including +itself. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(data) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data); + } + }); + }); +}); +``` + +A client WebSocket broadcasting to every other connected WebSocket clients, +excluding itself. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(data) { + wss.clients.forEach(function each(client) { + if (client !== ws && client.readyState === WebSocket.OPEN) { + client.send(data); + } + }); + }); +}); +``` + +### echo.websocket.org demo + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('wss://echo.websocket.org/', { + origin: 'https://websocket.org' +}); + +ws.on('open', function open() { + console.log('connected'); + ws.send(Date.now()); +}); + +ws.on('close', function close() { + console.log('disconnected'); +}); + +ws.on('message', function incoming(data) { + console.log(`Roundtrip time: ${Date.now() - data} ms`); + + setTimeout(function timeout() { + ws.send(Date.now()); + }, 500); +}); +``` + +### Use the Node.js streams API + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('wss://echo.websocket.org/', { + origin: 'https://websocket.org' +}); + +const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' }); + +duplex.pipe(process.stdout); +process.stdin.pipe(duplex); +``` + +### Other examples + +For a full example with a browser client communicating with a ws server, see the +examples folder. + +Otherwise, see the test cases. + +## FAQ + +### How to get the IP address of the client? + +The remote IP address can be obtained from the raw socket. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws, req) { + const ip = req.socket.remoteAddress; +}); +``` + +When the server runs behind a proxy like NGINX, the de-facto standard is to use +the `X-Forwarded-For` header. + +```js +wss.on('connection', function connection(ws, req) { + const ip = req.headers['x-forwarded-for'].split(/\s*,\s*/)[0]; +}); +``` + +### How to detect and close broken connections? + +Sometimes the link between the server and the client can be interrupted in a way +that keeps both the server and the client unaware of the broken state of the +connection (e.g. when pulling the cord). + +In these cases ping messages can be used as a means to verify that the remote +endpoint is still responsive. + +```js +const WebSocket = require('ws'); + +function noop() {} + +function heartbeat() { + this.isAlive = true; +} + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.isAlive = true; + ws.on('pong', heartbeat); +}); + +const interval = setInterval(function ping() { + wss.clients.forEach(function each(ws) { + if (ws.isAlive === false) return ws.terminate(); + + ws.isAlive = false; + ws.ping(noop); + }); +}, 30000); + +wss.on('close', function close() { + clearInterval(interval); +}); +``` + +Pong messages are automatically sent in response to ping messages as required by +the spec. + +Just like the server example above your clients might as well lose connection +without knowing it. You might want to add a ping listener on your clients to +prevent that. A simple implementation would be: + +```js +const WebSocket = require('ws'); + +function heartbeat() { + clearTimeout(this.pingTimeout); + + // Use `WebSocket#terminate()`, which immediately destroys the connection, + // instead of `WebSocket#close()`, which waits for the close timer. + // Delay should be equal to the interval at which your server + // sends out pings plus a conservative assumption of the latency. + this.pingTimeout = setTimeout(() => { + this.terminate(); + }, 30000 + 1000); +} + +const client = new WebSocket('wss://echo.websocket.org/'); + +client.on('open', heartbeat); +client.on('ping', heartbeat); +client.on('close', function clear() { + clearTimeout(this.pingTimeout); +}); +``` + +### How to connect via a proxy? + +Use a custom `http.Agent` implementation like [https-proxy-agent][] or +[socks-proxy-agent][]. + +## Changelog + +We're using the GitHub [releases][changelog] for changelog entries. + +## License + +[MIT](LICENSE) + +[changelog]: https://github.com/websockets/ws/releases +[client-report]: http://websockets.github.io/ws/autobahn/clients/ +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[node-zlib-bug]: https://github.com/nodejs/node/issues/8871 +[node-zlib-deflaterawdocs]: + https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options +[permessage-deflate]: https://tools.ietf.org/html/rfc7692 +[server-report]: http://websockets.github.io/ws/autobahn/servers/ +[session-parse-example]: ./examples/express-session-parse +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[ws-server-options]: + https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback diff --git a/node_modules/ws/browser.js b/node_modules/ws/browser.js new file mode 100644 index 0000000..ca4f628 --- /dev/null +++ b/node_modules/ws/browser.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = function () { + throw new Error( + 'ws does not work in the browser. Browser clients must use the native ' + + 'WebSocket object' + ); +}; diff --git a/node_modules/ws/index.js b/node_modules/ws/index.js new file mode 100644 index 0000000..722c786 --- /dev/null +++ b/node_modules/ws/index.js @@ -0,0 +1,10 @@ +'use strict'; + +const WebSocket = require('./lib/websocket'); + +WebSocket.createWebSocketStream = require('./lib/stream'); +WebSocket.Server = require('./lib/websocket-server'); +WebSocket.Receiver = require('./lib/receiver'); +WebSocket.Sender = require('./lib/sender'); + +module.exports = WebSocket; diff --git a/node_modules/ws/lib/buffer-util.js b/node_modules/ws/lib/buffer-util.js new file mode 100644 index 0000000..6fd84c3 --- /dev/null +++ b/node_modules/ws/lib/buffer-util.js @@ -0,0 +1,129 @@ +'use strict'; + +const { EMPTY_BUFFER } = require('./constants'); + +/** + * Merges an array of buffers into a new buffer. + * + * @param {Buffer[]} list The array of buffers to concat + * @param {Number} totalLength The total length of buffers in the list + * @return {Buffer} The resulting buffer + * @public + */ +function concat(list, totalLength) { + if (list.length === 0) return EMPTY_BUFFER; + if (list.length === 1) return list[0]; + + const target = Buffer.allocUnsafe(totalLength); + let offset = 0; + + for (let i = 0; i < list.length; i++) { + const buf = list[i]; + target.set(buf, offset); + offset += buf.length; + } + + if (offset < totalLength) return target.slice(0, offset); + + return target; +} + +/** + * Masks a buffer using the given mask. + * + * @param {Buffer} source The buffer to mask + * @param {Buffer} mask The mask to use + * @param {Buffer} output The buffer where to store the result + * @param {Number} offset The offset at which to start writing + * @param {Number} length The number of bytes to mask. + * @public + */ +function _mask(source, mask, output, offset, length) { + for (let i = 0; i < length; i++) { + output[offset + i] = source[i] ^ mask[i & 3]; + } +} + +/** + * Unmasks a buffer using the given mask. + * + * @param {Buffer} buffer The buffer to unmask + * @param {Buffer} mask The mask to use + * @public + */ +function _unmask(buffer, mask) { + // Required until https://github.com/nodejs/node/issues/9006 is resolved. + const length = buffer.length; + for (let i = 0; i < length; i++) { + buffer[i] ^= mask[i & 3]; + } +} + +/** + * Converts a buffer to an `ArrayBuffer`. + * + * @param {Buffer} buf The buffer to convert + * @return {ArrayBuffer} Converted buffer + * @public + */ +function toArrayBuffer(buf) { + if (buf.byteLength === buf.buffer.byteLength) { + return buf.buffer; + } + + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); +} + +/** + * Converts `data` to a `Buffer`. + * + * @param {*} data The data to convert + * @return {Buffer} The buffer + * @throws {TypeError} + * @public + */ +function toBuffer(data) { + toBuffer.readOnly = true; + + if (Buffer.isBuffer(data)) return data; + + let buf; + + if (data instanceof ArrayBuffer) { + buf = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength); + } else { + buf = Buffer.from(data); + toBuffer.readOnly = false; + } + + return buf; +} + +try { + const bufferUtil = require('bufferutil'); + const bu = bufferUtil.BufferUtil || bufferUtil; + + module.exports = { + concat, + mask(source, mask, output, offset, length) { + if (length < 48) _mask(source, mask, output, offset, length); + else bu.mask(source, mask, output, offset, length); + }, + toArrayBuffer, + toBuffer, + unmask(buffer, mask) { + if (buffer.length < 32) _unmask(buffer, mask); + else bu.unmask(buffer, mask); + } + }; +} catch (e) /* istanbul ignore next */ { + module.exports = { + concat, + mask: _mask, + toArrayBuffer, + toBuffer, + unmask: _unmask + }; +} diff --git a/node_modules/ws/lib/constants.js b/node_modules/ws/lib/constants.js new file mode 100644 index 0000000..4082981 --- /dev/null +++ b/node_modules/ws/lib/constants.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'], + GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', + kStatusCode: Symbol('status-code'), + kWebSocket: Symbol('websocket'), + EMPTY_BUFFER: Buffer.alloc(0), + NOOP: () => {} +}; diff --git a/node_modules/ws/lib/event-target.js b/node_modules/ws/lib/event-target.js new file mode 100644 index 0000000..a6fbe72 --- /dev/null +++ b/node_modules/ws/lib/event-target.js @@ -0,0 +1,184 @@ +'use strict'; + +/** + * Class representing an event. + * + * @private + */ +class Event { + /** + * Create a new `Event`. + * + * @param {String} type The name of the event + * @param {Object} target A reference to the target to which the event was + * dispatched + */ + constructor(type, target) { + this.target = target; + this.type = type; + } +} + +/** + * Class representing a message event. + * + * @extends Event + * @private + */ +class MessageEvent extends Event { + /** + * Create a new `MessageEvent`. + * + * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data + * @param {WebSocket} target A reference to the target to which the event was + * dispatched + */ + constructor(data, target) { + super('message', target); + + this.data = data; + } +} + +/** + * Class representing a close event. + * + * @extends Event + * @private + */ +class CloseEvent extends Event { + /** + * Create a new `CloseEvent`. + * + * @param {Number} code The status code explaining why the connection is being + * closed + * @param {String} reason A human-readable string explaining why the + * connection is closing + * @param {WebSocket} target A reference to the target to which the event was + * dispatched + */ + constructor(code, reason, target) { + super('close', target); + + this.wasClean = target._closeFrameReceived && target._closeFrameSent; + this.reason = reason; + this.code = code; + } +} + +/** + * Class representing an open event. + * + * @extends Event + * @private + */ +class OpenEvent extends Event { + /** + * Create a new `OpenEvent`. + * + * @param {WebSocket} target A reference to the target to which the event was + * dispatched + */ + constructor(target) { + super('open', target); + } +} + +/** + * Class representing an error event. + * + * @extends Event + * @private + */ +class ErrorEvent extends Event { + /** + * Create a new `ErrorEvent`. + * + * @param {Object} error The error that generated this event + * @param {WebSocket} target A reference to the target to which the event was + * dispatched + */ + constructor(error, target) { + super('error', target); + + this.message = error.message; + this.error = error; + } +} + +/** + * This provides methods for emulating the `EventTarget` interface. It's not + * meant to be used directly. + * + * @mixin + */ +const EventTarget = { + /** + * Register an event listener. + * + * @param {String} type A string representing the event type to listen for + * @param {Function} listener The listener to add + * @param {Object} [options] An options object specifies characteristics about + * the event listener + * @param {Boolean} [options.once=false] A `Boolean`` indicating that the + * listener should be invoked at most once after being added. If `true`, + * the listener would be automatically removed when invoked. + * @public + */ + addEventListener(type, listener, options) { + if (typeof listener !== 'function') return; + + function onMessage(data) { + listener.call(this, new MessageEvent(data, this)); + } + + function onClose(code, message) { + listener.call(this, new CloseEvent(code, message, this)); + } + + function onError(error) { + listener.call(this, new ErrorEvent(error, this)); + } + + function onOpen() { + listener.call(this, new OpenEvent(this)); + } + + const method = options && options.once ? 'once' : 'on'; + + if (type === 'message') { + onMessage._listener = listener; + this[method](type, onMessage); + } else if (type === 'close') { + onClose._listener = listener; + this[method](type, onClose); + } else if (type === 'error') { + onError._listener = listener; + this[method](type, onError); + } else if (type === 'open') { + onOpen._listener = listener; + this[method](type, onOpen); + } else { + this[method](type, listener); + } + }, + + /** + * Remove an event listener. + * + * @param {String} type A string representing the event type to remove + * @param {Function} listener The listener to remove + * @public + */ + removeEventListener(type, listener) { + const listeners = this.listeners(type); + + for (let i = 0; i < listeners.length; i++) { + if (listeners[i] === listener || listeners[i]._listener === listener) { + this.removeListener(type, listeners[i]); + } + } + } +}; + +module.exports = EventTarget; diff --git a/node_modules/ws/lib/extension.js b/node_modules/ws/lib/extension.js new file mode 100644 index 0000000..87a4213 --- /dev/null +++ b/node_modules/ws/lib/extension.js @@ -0,0 +1,223 @@ +'use strict'; + +// +// Allowed token characters: +// +// '!', '#', '$', '%', '&', ''', '*', '+', '-', +// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~' +// +// tokenChars[32] === 0 // ' ' +// tokenChars[33] === 1 // '!' +// tokenChars[34] === 0 // '"' +// ... +// +// prettier-ignore +const tokenChars = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127 +]; + +/** + * Adds an offer to the map of extension offers or a parameter to the map of + * parameters. + * + * @param {Object} dest The map of extension offers or parameters + * @param {String} name The extension or parameter name + * @param {(Object|Boolean|String)} elem The extension parameters or the + * parameter value + * @private + */ +function push(dest, name, elem) { + if (dest[name] === undefined) dest[name] = [elem]; + else dest[name].push(elem); +} + +/** + * Parses the `Sec-WebSocket-Extensions` header into an object. + * + * @param {String} header The field value of the header + * @return {Object} The parsed object + * @public + */ +function parse(header) { + const offers = Object.create(null); + + if (header === undefined || header === '') return offers; + + let params = Object.create(null); + let mustUnescape = false; + let isEscaping = false; + let inQuotes = false; + let extensionName; + let paramName; + let start = -1; + let end = -1; + let i = 0; + + for (; i < header.length; i++) { + const code = header.charCodeAt(i); + + if (extensionName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x20 /* ' ' */ || code === 0x09 /* '\t' */) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + const name = header.slice(start, end); + if (code === 0x2c) { + push(offers, name, params); + params = Object.create(null); + } else { + extensionName = name; + } + + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (paramName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x20 || code === 0x09) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + push(params, header.slice(start, end), true); + if (code === 0x2c) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + + start = end = -1; + } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) { + paramName = header.slice(start, i); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else { + // + // The value of a quoted-string after unescaping must conform to the + // token ABNF, so only token characters are valid. + // Ref: https://tools.ietf.org/html/rfc6455#section-9.1 + // + if (isEscaping) { + if (tokenChars[code] !== 1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (start === -1) start = i; + else if (!mustUnescape) mustUnescape = true; + isEscaping = false; + } else if (inQuotes) { + if (tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x22 /* '"' */ && start !== -1) { + inQuotes = false; + end = i; + } else if (code === 0x5c /* '\' */) { + isEscaping = true; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) { + inQuotes = true; + } else if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (start !== -1 && (code === 0x20 || code === 0x09)) { + if (end === -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + let value = header.slice(start, end); + if (mustUnescape) { + value = value.replace(/\\/g, ''); + mustUnescape = false; + } + push(params, paramName, value); + if (code === 0x2c) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + + paramName = undefined; + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + } + + if (start === -1 || inQuotes) { + throw new SyntaxError('Unexpected end of input'); + } + + if (end === -1) end = i; + const token = header.slice(start, end); + if (extensionName === undefined) { + push(offers, token, params); + } else { + if (paramName === undefined) { + push(params, token, true); + } else if (mustUnescape) { + push(params, paramName, token.replace(/\\/g, '')); + } else { + push(params, paramName, token); + } + push(offers, extensionName, params); + } + + return offers; +} + +/** + * Builds the `Sec-WebSocket-Extensions` header field value. + * + * @param {Object} extensions The map of extensions and parameters to format + * @return {String} A string representing the given object + * @public + */ +function format(extensions) { + return Object.keys(extensions) + .map((extension) => { + let configurations = extensions[extension]; + if (!Array.isArray(configurations)) configurations = [configurations]; + return configurations + .map((params) => { + return [extension] + .concat( + Object.keys(params).map((k) => { + let values = params[k]; + if (!Array.isArray(values)) values = [values]; + return values + .map((v) => (v === true ? k : `${k}=${v}`)) + .join('; '); + }) + ) + .join('; '); + }) + .join(', '); + }) + .join(', '); +} + +module.exports = { format, parse }; diff --git a/node_modules/ws/lib/limiter.js b/node_modules/ws/lib/limiter.js new file mode 100644 index 0000000..3fd3578 --- /dev/null +++ b/node_modules/ws/lib/limiter.js @@ -0,0 +1,55 @@ +'use strict'; + +const kDone = Symbol('kDone'); +const kRun = Symbol('kRun'); + +/** + * A very simple job queue with adjustable concurrency. Adapted from + * https://github.com/STRML/async-limiter + */ +class Limiter { + /** + * Creates a new `Limiter`. + * + * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed + * to run concurrently + */ + constructor(concurrency) { + this[kDone] = () => { + this.pending--; + this[kRun](); + }; + this.concurrency = concurrency || Infinity; + this.jobs = []; + this.pending = 0; + } + + /** + * Adds a job to the queue. + * + * @param {Function} job The job to run + * @public + */ + add(job) { + this.jobs.push(job); + this[kRun](); + } + + /** + * Removes a job from the queue and runs it if possible. + * + * @private + */ + [kRun]() { + if (this.pending === this.concurrency) return; + + if (this.jobs.length) { + const job = this.jobs.shift(); + + this.pending++; + job(this[kDone]); + } + } +} + +module.exports = Limiter; diff --git a/node_modules/ws/lib/permessage-deflate.js b/node_modules/ws/lib/permessage-deflate.js new file mode 100644 index 0000000..a8974b9 --- /dev/null +++ b/node_modules/ws/lib/permessage-deflate.js @@ -0,0 +1,517 @@ +'use strict'; + +const zlib = require('zlib'); + +const bufferUtil = require('./buffer-util'); +const Limiter = require('./limiter'); +const { kStatusCode, NOOP } = require('./constants'); + +const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]); +const kPerMessageDeflate = Symbol('permessage-deflate'); +const kTotalLength = Symbol('total-length'); +const kCallback = Symbol('callback'); +const kBuffers = Symbol('buffers'); +const kError = Symbol('error'); + +// +// We limit zlib concurrency, which prevents severe memory fragmentation +// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913 +// and https://github.com/websockets/ws/issues/1202 +// +// Intentionally global; it's the global thread pool that's an issue. +// +let zlibLimiter; + +/** + * permessage-deflate implementation. + */ +class PerMessageDeflate { + /** + * Creates a PerMessageDeflate instance. + * + * @param {Object} [options] Configuration options + * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept + * disabling of server context takeover + * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/ + * acknowledge disabling of client context takeover + * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the + * use of a custom server window size + * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support + * for, or request, a custom client window size + * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on + * deflate + * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on + * inflate + * @param {Number} [options.threshold=1024] Size (in bytes) below which + * messages should not be compressed + * @param {Number} [options.concurrencyLimit=10] The number of concurrent + * calls to zlib + * @param {Boolean} [isServer=false] Create the instance in either server or + * client mode + * @param {Number} [maxPayload=0] The maximum allowed message length + */ + constructor(options, isServer, maxPayload) { + this._maxPayload = maxPayload | 0; + this._options = options || {}; + this._threshold = + this._options.threshold !== undefined ? this._options.threshold : 1024; + this._isServer = !!isServer; + this._deflate = null; + this._inflate = null; + + this.params = null; + + if (!zlibLimiter) { + const concurrency = + this._options.concurrencyLimit !== undefined + ? this._options.concurrencyLimit + : 10; + zlibLimiter = new Limiter(concurrency); + } + } + + /** + * @type {String} + */ + static get extensionName() { + return 'permessage-deflate'; + } + + /** + * Create an extension negotiation offer. + * + * @return {Object} Extension parameters + * @public + */ + offer() { + const params = {}; + + if (this._options.serverNoContextTakeover) { + params.server_no_context_takeover = true; + } + if (this._options.clientNoContextTakeover) { + params.client_no_context_takeover = true; + } + if (this._options.serverMaxWindowBits) { + params.server_max_window_bits = this._options.serverMaxWindowBits; + } + if (this._options.clientMaxWindowBits) { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } else if (this._options.clientMaxWindowBits == null) { + params.client_max_window_bits = true; + } + + return params; + } + + /** + * Accept an extension negotiation offer/response. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Object} Accepted configuration + * @public + */ + accept(configurations) { + configurations = this.normalizeParams(configurations); + + this.params = this._isServer + ? this.acceptAsServer(configurations) + : this.acceptAsClient(configurations); + + return this.params; + } + + /** + * Releases all resources used by the extension. + * + * @public + */ + cleanup() { + if (this._inflate) { + this._inflate.close(); + this._inflate = null; + } + + if (this._deflate) { + const callback = this._deflate[kCallback]; + + this._deflate.close(); + this._deflate = null; + + if (callback) { + callback( + new Error( + 'The deflate stream was closed while data was being processed' + ) + ); + } + } + } + + /** + * Accept an extension negotiation offer. + * + * @param {Array} offers The extension negotiation offers + * @return {Object} Accepted configuration + * @private + */ + acceptAsServer(offers) { + const opts = this._options; + const accepted = offers.find((params) => { + if ( + (opts.serverNoContextTakeover === false && + params.server_no_context_takeover) || + (params.server_max_window_bits && + (opts.serverMaxWindowBits === false || + (typeof opts.serverMaxWindowBits === 'number' && + opts.serverMaxWindowBits > params.server_max_window_bits))) || + (typeof opts.clientMaxWindowBits === 'number' && + !params.client_max_window_bits) + ) { + return false; + } + + return true; + }); + + if (!accepted) { + throw new Error('None of the extension offers can be accepted'); + } + + if (opts.serverNoContextTakeover) { + accepted.server_no_context_takeover = true; + } + if (opts.clientNoContextTakeover) { + accepted.client_no_context_takeover = true; + } + if (typeof opts.serverMaxWindowBits === 'number') { + accepted.server_max_window_bits = opts.serverMaxWindowBits; + } + if (typeof opts.clientMaxWindowBits === 'number') { + accepted.client_max_window_bits = opts.clientMaxWindowBits; + } else if ( + accepted.client_max_window_bits === true || + opts.clientMaxWindowBits === false + ) { + delete accepted.client_max_window_bits; + } + + return accepted; + } + + /** + * Accept the extension negotiation response. + * + * @param {Array} response The extension negotiation response + * @return {Object} Accepted configuration + * @private + */ + acceptAsClient(response) { + const params = response[0]; + + if ( + this._options.clientNoContextTakeover === false && + params.client_no_context_takeover + ) { + throw new Error('Unexpected parameter "client_no_context_takeover"'); + } + + if (!params.client_max_window_bits) { + if (typeof this._options.clientMaxWindowBits === 'number') { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } + } else if ( + this._options.clientMaxWindowBits === false || + (typeof this._options.clientMaxWindowBits === 'number' && + params.client_max_window_bits > this._options.clientMaxWindowBits) + ) { + throw new Error( + 'Unexpected or invalid parameter "client_max_window_bits"' + ); + } + + return params; + } + + /** + * Normalize parameters. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Array} The offers/response with normalized parameters + * @private + */ + normalizeParams(configurations) { + configurations.forEach((params) => { + Object.keys(params).forEach((key) => { + let value = params[key]; + + if (value.length > 1) { + throw new Error(`Parameter "${key}" must have only a single value`); + } + + value = value[0]; + + if (key === 'client_max_window_bits') { + if (value !== true) { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if (!this._isServer) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else if (key === 'server_max_window_bits') { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if ( + key === 'client_no_context_takeover' || + key === 'server_no_context_takeover' + ) { + if (value !== true) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else { + throw new Error(`Unknown parameter "${key}"`); + } + + params[key] = value; + }); + }); + + return configurations; + } + + /** + * Decompress data. Concurrency limited. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + decompress(data, fin, callback) { + zlibLimiter.add((done) => { + this._decompress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Compress data. Concurrency limited. + * + * @param {Buffer} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + compress(data, fin, callback) { + zlibLimiter.add((done) => { + this._compress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Decompress data. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _decompress(data, fin, callback) { + const endpoint = this._isServer ? 'client' : 'server'; + + if (!this._inflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = + typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._inflate = zlib.createInflateRaw({ + ...this._options.zlibInflateOptions, + windowBits + }); + this._inflate[kPerMessageDeflate] = this; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + this._inflate.on('error', inflateOnError); + this._inflate.on('data', inflateOnData); + } + + this._inflate[kCallback] = callback; + + this._inflate.write(data); + if (fin) this._inflate.write(TRAILER); + + this._inflate.flush(() => { + const err = this._inflate[kError]; + + if (err) { + this._inflate.close(); + this._inflate = null; + callback(err); + return; + } + + const data = bufferUtil.concat( + this._inflate[kBuffers], + this._inflate[kTotalLength] + ); + + if (this._inflate._readableState.endEmitted) { + this._inflate.close(); + this._inflate = null; + } else { + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._inflate.reset(); + } + } + + callback(null, data); + }); + } + + /** + * Compress data. + * + * @param {Buffer} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _compress(data, fin, callback) { + const endpoint = this._isServer ? 'server' : 'client'; + + if (!this._deflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = + typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._deflate = zlib.createDeflateRaw({ + ...this._options.zlibDeflateOptions, + windowBits + }); + + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + + // + // An `'error'` event is emitted, only on Node.js < 10.0.0, if the + // `zlib.DeflateRaw` instance is closed while data is being processed. + // This can happen if `PerMessageDeflate#cleanup()` is called at the wrong + // time due to an abnormal WebSocket closure. + // + this._deflate.on('error', NOOP); + this._deflate.on('data', deflateOnData); + } + + this._deflate[kCallback] = callback; + + this._deflate.write(data); + this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { + if (!this._deflate) { + // + // The deflate stream was closed while data was being processed. + // + return; + } + + let data = bufferUtil.concat( + this._deflate[kBuffers], + this._deflate[kTotalLength] + ); + + if (fin) data = data.slice(0, data.length - 4); + + // + // Ensure that the callback will not be called again in + // `PerMessageDeflate#cleanup()`. + // + this._deflate[kCallback] = null; + + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._deflate.reset(); + } + + callback(null, data); + }); + } +} + +module.exports = PerMessageDeflate; + +/** + * The listener of the `zlib.DeflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function deflateOnData(chunk) { + this[kBuffers].push(chunk); + this[kTotalLength] += chunk.length; +} + +/** + * The listener of the `zlib.InflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function inflateOnData(chunk) { + this[kTotalLength] += chunk.length; + + if ( + this[kPerMessageDeflate]._maxPayload < 1 || + this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload + ) { + this[kBuffers].push(chunk); + return; + } + + this[kError] = new RangeError('Max payload size exceeded'); + this[kError][kStatusCode] = 1009; + this.removeListener('data', inflateOnData); + this.reset(); +} + +/** + * The listener of the `zlib.InflateRaw` stream `'error'` event. + * + * @param {Error} err The emitted error + * @private + */ +function inflateOnError(err) { + // + // There is no need to call `Zlib#close()` as the handle is automatically + // closed when an error is emitted. + // + this[kPerMessageDeflate]._inflate = null; + err[kStatusCode] = 1007; + this[kCallback](err); +} diff --git a/node_modules/ws/lib/receiver.js b/node_modules/ws/lib/receiver.js new file mode 100644 index 0000000..65a5ab4 --- /dev/null +++ b/node_modules/ws/lib/receiver.js @@ -0,0 +1,507 @@ +'use strict'; + +const { Writable } = require('stream'); + +const PerMessageDeflate = require('./permessage-deflate'); +const { + BINARY_TYPES, + EMPTY_BUFFER, + kStatusCode, + kWebSocket +} = require('./constants'); +const { concat, toArrayBuffer, unmask } = require('./buffer-util'); +const { isValidStatusCode, isValidUTF8 } = require('./validation'); + +const GET_INFO = 0; +const GET_PAYLOAD_LENGTH_16 = 1; +const GET_PAYLOAD_LENGTH_64 = 2; +const GET_MASK = 3; +const GET_DATA = 4; +const INFLATING = 5; + +/** + * HyBi Receiver implementation. + * + * @extends stream.Writable + */ +class Receiver extends Writable { + /** + * Creates a Receiver instance. + * + * @param {String} [binaryType=nodebuffer] The type for binary data + * @param {Object} [extensions] An object containing the negotiated extensions + * @param {Boolean} [isServer=false] Specifies whether to operate in client or + * server mode + * @param {Number} [maxPayload=0] The maximum allowed message length + */ + constructor(binaryType, extensions, isServer, maxPayload) { + super(); + + this._binaryType = binaryType || BINARY_TYPES[0]; + this[kWebSocket] = undefined; + this._extensions = extensions || {}; + this._isServer = !!isServer; + this._maxPayload = maxPayload | 0; + + this._bufferedBytes = 0; + this._buffers = []; + + this._compressed = false; + this._payloadLength = 0; + this._mask = undefined; + this._fragmented = 0; + this._masked = false; + this._fin = false; + this._opcode = 0; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragments = []; + + this._state = GET_INFO; + this._loop = false; + } + + /** + * Implements `Writable.prototype._write()`. + * + * @param {Buffer} chunk The chunk of data to write + * @param {String} encoding The character encoding of `chunk` + * @param {Function} cb Callback + * @private + */ + _write(chunk, encoding, cb) { + if (this._opcode === 0x08 && this._state == GET_INFO) return cb(); + + this._bufferedBytes += chunk.length; + this._buffers.push(chunk); + this.startLoop(cb); + } + + /** + * Consumes `n` bytes from the buffered data. + * + * @param {Number} n The number of bytes to consume + * @return {Buffer} The consumed bytes + * @private + */ + consume(n) { + this._bufferedBytes -= n; + + if (n === this._buffers[0].length) return this._buffers.shift(); + + if (n < this._buffers[0].length) { + const buf = this._buffers[0]; + this._buffers[0] = buf.slice(n); + return buf.slice(0, n); + } + + const dst = Buffer.allocUnsafe(n); + + do { + const buf = this._buffers[0]; + const offset = dst.length - n; + + if (n >= buf.length) { + dst.set(this._buffers.shift(), offset); + } else { + dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset); + this._buffers[0] = buf.slice(n); + } + + n -= buf.length; + } while (n > 0); + + return dst; + } + + /** + * Starts the parsing loop. + * + * @param {Function} cb Callback + * @private + */ + startLoop(cb) { + let err; + this._loop = true; + + do { + switch (this._state) { + case GET_INFO: + err = this.getInfo(); + break; + case GET_PAYLOAD_LENGTH_16: + err = this.getPayloadLength16(); + break; + case GET_PAYLOAD_LENGTH_64: + err = this.getPayloadLength64(); + break; + case GET_MASK: + this.getMask(); + break; + case GET_DATA: + err = this.getData(cb); + break; + default: + // `INFLATING` + this._loop = false; + return; + } + } while (this._loop); + + cb(err); + } + + /** + * Reads the first two bytes of a frame. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getInfo() { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + const buf = this.consume(2); + + if ((buf[0] & 0x30) !== 0x00) { + this._loop = false; + return error(RangeError, 'RSV2 and RSV3 must be clear', true, 1002); + } + + const compressed = (buf[0] & 0x40) === 0x40; + + if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + this._fin = (buf[0] & 0x80) === 0x80; + this._opcode = buf[0] & 0x0f; + this._payloadLength = buf[1] & 0x7f; + + if (this._opcode === 0x00) { + if (compressed) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + if (!this._fragmented) { + this._loop = false; + return error(RangeError, 'invalid opcode 0', true, 1002); + } + + this._opcode = this._fragmented; + } else if (this._opcode === 0x01 || this._opcode === 0x02) { + if (this._fragmented) { + this._loop = false; + return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); + } + + this._compressed = compressed; + } else if (this._opcode > 0x07 && this._opcode < 0x0b) { + if (!this._fin) { + this._loop = false; + return error(RangeError, 'FIN must be set', true, 1002); + } + + if (compressed) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + if (this._payloadLength > 0x7d) { + this._loop = false; + return error( + RangeError, + `invalid payload length ${this._payloadLength}`, + true, + 1002 + ); + } + } else { + this._loop = false; + return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); + } + + if (!this._fin && !this._fragmented) this._fragmented = this._opcode; + this._masked = (buf[1] & 0x80) === 0x80; + + if (this._isServer) { + if (!this._masked) { + this._loop = false; + return error(RangeError, 'MASK must be set', true, 1002); + } + } else if (this._masked) { + this._loop = false; + return error(RangeError, 'MASK must be clear', true, 1002); + } + + if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; + else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; + else return this.haveLength(); + } + + /** + * Gets extended payload length (7+16). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength16() { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + this._payloadLength = this.consume(2).readUInt16BE(0); + return this.haveLength(); + } + + /** + * Gets extended payload length (7+64). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength64() { + if (this._bufferedBytes < 8) { + this._loop = false; + return; + } + + const buf = this.consume(8); + const num = buf.readUInt32BE(0); + + // + // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned + // if payload length is greater than this number. + // + if (num > Math.pow(2, 53 - 32) - 1) { + this._loop = false; + return error( + RangeError, + 'Unsupported WebSocket frame: payload length > 2^53 - 1', + false, + 1009 + ); + } + + this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4); + return this.haveLength(); + } + + /** + * Payload length has been read. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + haveLength() { + if (this._payloadLength && this._opcode < 0x08) { + this._totalPayloadLength += this._payloadLength; + if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { + this._loop = false; + return error(RangeError, 'Max payload size exceeded', false, 1009); + } + } + + if (this._masked) this._state = GET_MASK; + else this._state = GET_DATA; + } + + /** + * Reads mask bytes. + * + * @private + */ + getMask() { + if (this._bufferedBytes < 4) { + this._loop = false; + return; + } + + this._mask = this.consume(4); + this._state = GET_DATA; + } + + /** + * Reads data bytes. + * + * @param {Function} cb Callback + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + getData(cb) { + let data = EMPTY_BUFFER; + + if (this._payloadLength) { + if (this._bufferedBytes < this._payloadLength) { + this._loop = false; + return; + } + + data = this.consume(this._payloadLength); + if (this._masked) unmask(data, this._mask); + } + + if (this._opcode > 0x07) return this.controlMessage(data); + + if (this._compressed) { + this._state = INFLATING; + this.decompress(data, cb); + return; + } + + if (data.length) { + // + // This message is not compressed so its lenght is the sum of the payload + // length of all fragments. + // + this._messageLength = this._totalPayloadLength; + this._fragments.push(data); + } + + return this.dataMessage(); + } + + /** + * Decompresses data. + * + * @param {Buffer} data Compressed data + * @param {Function} cb Callback + * @private + */ + decompress(data, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + perMessageDeflate.decompress(data, this._fin, (err, buf) => { + if (err) return cb(err); + + if (buf.length) { + this._messageLength += buf.length; + if (this._messageLength > this._maxPayload && this._maxPayload > 0) { + return cb( + error(RangeError, 'Max payload size exceeded', false, 1009) + ); + } + + this._fragments.push(buf); + } + + const er = this.dataMessage(); + if (er) return cb(er); + + this.startLoop(cb); + }); + } + + /** + * Handles a data message. + * + * @return {(Error|undefined)} A possible error + * @private + */ + dataMessage() { + if (this._fin) { + const messageLength = this._messageLength; + const fragments = this._fragments; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragmented = 0; + this._fragments = []; + + if (this._opcode === 2) { + let data; + + if (this._binaryType === 'nodebuffer') { + data = concat(fragments, messageLength); + } else if (this._binaryType === 'arraybuffer') { + data = toArrayBuffer(concat(fragments, messageLength)); + } else { + data = fragments; + } + + this.emit('message', data); + } else { + const buf = concat(fragments, messageLength); + + if (!isValidUTF8(buf)) { + this._loop = false; + return error(Error, 'invalid UTF-8 sequence', true, 1007); + } + + this.emit('message', buf.toString()); + } + } + + this._state = GET_INFO; + } + + /** + * Handles a control message. + * + * @param {Buffer} data Data to handle + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + controlMessage(data) { + if (this._opcode === 0x08) { + this._loop = false; + + if (data.length === 0) { + this.emit('conclude', 1005, ''); + this.end(); + } else if (data.length === 1) { + return error(RangeError, 'invalid payload length 1', true, 1002); + } else { + const code = data.readUInt16BE(0); + + if (!isValidStatusCode(code)) { + return error(RangeError, `invalid status code ${code}`, true, 1002); + } + + const buf = data.slice(2); + + if (!isValidUTF8(buf)) { + return error(Error, 'invalid UTF-8 sequence', true, 1007); + } + + this.emit('conclude', code, buf.toString()); + this.end(); + } + } else if (this._opcode === 0x09) { + this.emit('ping', data); + } else { + this.emit('pong', data); + } + + this._state = GET_INFO; + } +} + +module.exports = Receiver; + +/** + * Builds an error object. + * + * @param {(Error|RangeError)} ErrorCtor The error constructor + * @param {String} message The error message + * @param {Boolean} prefix Specifies whether or not to add a default prefix to + * `message` + * @param {Number} statusCode The status code + * @return {(Error|RangeError)} The error + * @private + */ +function error(ErrorCtor, message, prefix, statusCode) { + const err = new ErrorCtor( + prefix ? `Invalid WebSocket frame: ${message}` : message + ); + + Error.captureStackTrace(err, error); + err[kStatusCode] = statusCode; + return err; +} diff --git a/node_modules/ws/lib/sender.js b/node_modules/ws/lib/sender.js new file mode 100644 index 0000000..ad71e19 --- /dev/null +++ b/node_modules/ws/lib/sender.js @@ -0,0 +1,405 @@ +'use strict'; + +const { randomFillSync } = require('crypto'); + +const PerMessageDeflate = require('./permessage-deflate'); +const { EMPTY_BUFFER } = require('./constants'); +const { isValidStatusCode } = require('./validation'); +const { mask: applyMask, toBuffer } = require('./buffer-util'); + +const mask = Buffer.alloc(4); + +/** + * HyBi Sender implementation. + */ +class Sender { + /** + * Creates a Sender instance. + * + * @param {net.Socket} socket The connection socket + * @param {Object} [extensions] An object containing the negotiated extensions + */ + constructor(socket, extensions) { + this._extensions = extensions || {}; + this._socket = socket; + + this._firstFragment = true; + this._compress = false; + + this._bufferedBytes = 0; + this._deflating = false; + this._queue = []; + } + + /** + * Frames a piece of data according to the HyBi WebSocket protocol. + * + * @param {Buffer} data The data to frame + * @param {Object} options Options object + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @return {Buffer[]} The framed data as a list of `Buffer` instances + * @public + */ + static frame(data, options) { + const merge = options.mask && options.readOnly; + let offset = options.mask ? 6 : 2; + let payloadLength = data.length; + + if (data.length >= 65536) { + offset += 8; + payloadLength = 127; + } else if (data.length > 125) { + offset += 2; + payloadLength = 126; + } + + const target = Buffer.allocUnsafe(merge ? data.length + offset : offset); + + target[0] = options.fin ? options.opcode | 0x80 : options.opcode; + if (options.rsv1) target[0] |= 0x40; + + target[1] = payloadLength; + + if (payloadLength === 126) { + target.writeUInt16BE(data.length, 2); + } else if (payloadLength === 127) { + target.writeUInt32BE(0, 2); + target.writeUInt32BE(data.length, 6); + } + + if (!options.mask) return [target, data]; + + randomFillSync(mask, 0, 4); + + target[1] |= 0x80; + target[offset - 4] = mask[0]; + target[offset - 3] = mask[1]; + target[offset - 2] = mask[2]; + target[offset - 1] = mask[3]; + + if (merge) { + applyMask(data, mask, target, offset, data.length); + return [target]; + } + + applyMask(data, mask, data, 0, data.length); + return [target, data]; + } + + /** + * Sends a close message to the other peer. + * + * @param {Number} [code] The status code component of the body + * @param {String} [data] The message component of the body + * @param {Boolean} [mask=false] Specifies whether or not to mask the message + * @param {Function} [cb] Callback + * @public + */ + close(code, data, mask, cb) { + let buf; + + if (code === undefined) { + buf = EMPTY_BUFFER; + } else if (typeof code !== 'number' || !isValidStatusCode(code)) { + throw new TypeError('First argument must be a valid error code number'); + } else if (data === undefined || data === '') { + buf = Buffer.allocUnsafe(2); + buf.writeUInt16BE(code, 0); + } else { + const length = Buffer.byteLength(data); + + if (length > 123) { + throw new RangeError('The message must not be greater than 123 bytes'); + } + + buf = Buffer.allocUnsafe(2 + length); + buf.writeUInt16BE(code, 0); + buf.write(data, 2); + } + + if (this._deflating) { + this.enqueue([this.doClose, buf, mask, cb]); + } else { + this.doClose(buf, mask, cb); + } + } + + /** + * Frames and sends a close message. + * + * @param {Buffer} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @private + */ + doClose(data, mask, cb) { + this.sendFrame( + Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x08, + mask, + readOnly: false + }), + cb + ); + } + + /** + * Sends a ping message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + ping(data, mask, cb) { + const buf = toBuffer(data); + + if (buf.length > 125) { + throw new RangeError('The data size must not be greater than 125 bytes'); + } + + if (this._deflating) { + this.enqueue([this.doPing, buf, mask, toBuffer.readOnly, cb]); + } else { + this.doPing(buf, mask, toBuffer.readOnly, cb); + } + } + + /** + * Frames and sends a ping message. + * + * @param {Buffer} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Boolean} [readOnly=false] Specifies whether `data` can be modified + * @param {Function} [cb] Callback + * @private + */ + doPing(data, mask, readOnly, cb) { + this.sendFrame( + Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x09, + mask, + readOnly + }), + cb + ); + } + + /** + * Sends a pong message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + pong(data, mask, cb) { + const buf = toBuffer(data); + + if (buf.length > 125) { + throw new RangeError('The data size must not be greater than 125 bytes'); + } + + if (this._deflating) { + this.enqueue([this.doPong, buf, mask, toBuffer.readOnly, cb]); + } else { + this.doPong(buf, mask, toBuffer.readOnly, cb); + } + } + + /** + * Frames and sends a pong message. + * + * @param {Buffer} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Boolean} [readOnly=false] Specifies whether `data` can be modified + * @param {Function} [cb] Callback + * @private + */ + doPong(data, mask, readOnly, cb) { + this.sendFrame( + Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x0a, + mask, + readOnly + }), + cb + ); + } + + /** + * Sends a data message to the other peer. + * + * @param {*} data The message to send + * @param {Object} options Options object + * @param {Boolean} [options.compress=false] Specifies whether or not to + * compress `data` + * @param {Boolean} [options.binary=false] Specifies whether `data` is binary + * or text + * @param {Boolean} [options.fin=false] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Function} [cb] Callback + * @public + */ + send(data, options, cb) { + const buf = toBuffer(data); + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + let opcode = options.binary ? 2 : 1; + let rsv1 = options.compress; + + if (this._firstFragment) { + this._firstFragment = false; + if (rsv1 && perMessageDeflate) { + rsv1 = buf.length >= perMessageDeflate._threshold; + } + this._compress = rsv1; + } else { + rsv1 = false; + opcode = 0; + } + + if (options.fin) this._firstFragment = true; + + if (perMessageDeflate) { + const opts = { + fin: options.fin, + rsv1, + opcode, + mask: options.mask, + readOnly: toBuffer.readOnly + }; + + if (this._deflating) { + this.enqueue([this.dispatch, buf, this._compress, opts, cb]); + } else { + this.dispatch(buf, this._compress, opts, cb); + } + } else { + this.sendFrame( + Sender.frame(buf, { + fin: options.fin, + rsv1: false, + opcode, + mask: options.mask, + readOnly: toBuffer.readOnly + }), + cb + ); + } + } + + /** + * Dispatches a data message. + * + * @param {Buffer} data The message to send + * @param {Boolean} [compress=false] Specifies whether or not to compress + * `data` + * @param {Object} options Options object + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @param {Function} [cb] Callback + * @private + */ + dispatch(data, compress, options, cb) { + if (!compress) { + this.sendFrame(Sender.frame(data, options), cb); + return; + } + + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + this._bufferedBytes += data.length; + this._deflating = true; + perMessageDeflate.compress(data, options.fin, (_, buf) => { + if (this._socket.destroyed) { + const err = new Error( + 'The socket was closed while data was being compressed' + ); + + if (typeof cb === 'function') cb(err); + + for (let i = 0; i < this._queue.length; i++) { + const callback = this._queue[i][4]; + + if (typeof callback === 'function') callback(err); + } + + return; + } + + this._bufferedBytes -= data.length; + this._deflating = false; + options.readOnly = false; + this.sendFrame(Sender.frame(buf, options), cb); + this.dequeue(); + }); + } + + /** + * Executes queued send operations. + * + * @private + */ + dequeue() { + while (!this._deflating && this._queue.length) { + const params = this._queue.shift(); + + this._bufferedBytes -= params[1].length; + Reflect.apply(params[0], this, params.slice(1)); + } + } + + /** + * Enqueues a send operation. + * + * @param {Array} params Send operation parameters. + * @private + */ + enqueue(params) { + this._bufferedBytes += params[1].length; + this._queue.push(params); + } + + /** + * Sends a frame. + * + * @param {Buffer[]} list The frame to send + * @param {Function} [cb] Callback + * @private + */ + sendFrame(list, cb) { + if (list.length === 2) { + this._socket.cork(); + this._socket.write(list[0]); + this._socket.write(list[1], cb); + this._socket.uncork(); + } else { + this._socket.write(list[0], cb); + } + } +} + +module.exports = Sender; diff --git a/node_modules/ws/lib/stream.js b/node_modules/ws/lib/stream.js new file mode 100644 index 0000000..604cf36 --- /dev/null +++ b/node_modules/ws/lib/stream.js @@ -0,0 +1,165 @@ +'use strict'; + +const { Duplex } = require('stream'); + +/** + * Emits the `'close'` event on a stream. + * + * @param {stream.Duplex} The stream. + * @private + */ +function emitClose(stream) { + stream.emit('close'); +} + +/** + * The listener of the `'end'` event. + * + * @private + */ +function duplexOnEnd() { + if (!this.destroyed && this._writableState.finished) { + this.destroy(); + } +} + +/** + * The listener of the `'error'` event. + * + * @param {Error} err The error + * @private + */ +function duplexOnError(err) { + this.removeListener('error', duplexOnError); + this.destroy(); + if (this.listenerCount('error') === 0) { + // Do not suppress the throwing behavior. + this.emit('error', err); + } +} + +/** + * Wraps a `WebSocket` in a duplex stream. + * + * @param {WebSocket} ws The `WebSocket` to wrap + * @param {Object} [options] The options for the `Duplex` constructor + * @return {stream.Duplex} The duplex stream + * @public + */ +function createWebSocketStream(ws, options) { + let resumeOnReceiverDrain = true; + + function receiverOnDrain() { + if (resumeOnReceiverDrain) ws._socket.resume(); + } + + if (ws.readyState === ws.CONNECTING) { + ws.once('open', function open() { + ws._receiver.removeAllListeners('drain'); + ws._receiver.on('drain', receiverOnDrain); + }); + } else { + ws._receiver.removeAllListeners('drain'); + ws._receiver.on('drain', receiverOnDrain); + } + + const duplex = new Duplex({ + ...options, + autoDestroy: false, + emitClose: false, + objectMode: false, + writableObjectMode: false + }); + + ws.on('message', function message(msg) { + if (!duplex.push(msg)) { + resumeOnReceiverDrain = false; + ws._socket.pause(); + } + }); + + ws.once('error', function error(err) { + if (duplex.destroyed) return; + + duplex.destroy(err); + }); + + ws.once('close', function close() { + if (duplex.destroyed) return; + + duplex.push(null); + }); + + duplex._destroy = function (err, callback) { + if (ws.readyState === ws.CLOSED) { + callback(err); + process.nextTick(emitClose, duplex); + return; + } + + let called = false; + + ws.once('error', function error(err) { + called = true; + callback(err); + }); + + ws.once('close', function close() { + if (!called) callback(err); + process.nextTick(emitClose, duplex); + }); + ws.terminate(); + }; + + duplex._final = function (callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once('open', function open() { + duplex._final(callback); + }); + return; + } + + // If the value of the `_socket` property is `null` it means that `ws` is a + // client websocket and the handshake failed. In fact, when this happens, a + // socket is never assigned to the websocket. Wait for the `'error'` event + // that will be emitted by the websocket. + if (ws._socket === null) return; + + if (ws._socket._writableState.finished) { + callback(); + if (duplex._readableState.endEmitted) duplex.destroy(); + } else { + ws._socket.once('finish', function finish() { + // `duplex` is not destroyed here because the `'end'` event will be + // emitted on `duplex` after this `'finish'` event. The EOF signaling + // `null` chunk is, in fact, pushed when the websocket emits `'close'`. + callback(); + }); + ws.close(); + } + }; + + duplex._read = function () { + if (ws.readyState === ws.OPEN && !resumeOnReceiverDrain) { + resumeOnReceiverDrain = true; + if (!ws._receiver._writableState.needDrain) ws._socket.resume(); + } + }; + + duplex._write = function (chunk, encoding, callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once('open', function open() { + duplex._write(chunk, encoding, callback); + }); + return; + } + + ws.send(chunk, callback); + }; + + duplex.on('end', duplexOnEnd); + duplex.on('error', duplexOnError); + return duplex; +} + +module.exports = createWebSocketStream; diff --git a/node_modules/ws/lib/validation.js b/node_modules/ws/lib/validation.js new file mode 100644 index 0000000..d8693fd --- /dev/null +++ b/node_modules/ws/lib/validation.js @@ -0,0 +1,104 @@ +'use strict'; + +/** + * Checks if a status code is allowed in a close frame. + * + * @param {Number} code The status code + * @return {Boolean} `true` if the status code is valid, else `false` + * @public + */ +function isValidStatusCode(code) { + return ( + (code >= 1000 && + code <= 1014 && + code !== 1004 && + code !== 1005 && + code !== 1006) || + (code >= 3000 && code <= 4999) + ); +} + +/** + * Checks if a given buffer contains only correct UTF-8. + * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by + * Markus Kuhn. + * + * @param {Buffer} buf The buffer to check + * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false` + * @public + */ +function _isValidUTF8(buf) { + const len = buf.length; + let i = 0; + + while (i < len) { + if (buf[i] < 0x80) { + // 0xxxxxxx + i++; + } else if ((buf[i] & 0xe0) === 0xc0) { + // 110xxxxx 10xxxxxx + if ( + i + 1 === len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i] & 0xfe) === 0xc0 // Overlong + ) { + return false; + } else { + i += 2; + } + } else if ((buf[i] & 0xf0) === 0xe0) { + // 1110xxxx 10xxxxxx 10xxxxxx + if ( + i + 2 >= len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i + 2] & 0xc0) !== 0x80 || + (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong + (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF) + ) { + return false; + } else { + i += 3; + } + } else if ((buf[i] & 0xf8) === 0xf0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + if ( + i + 3 >= len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i + 2] & 0xc0) !== 0x80 || + (buf[i + 3] & 0xc0) !== 0x80 || + (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong + (buf[i] === 0xf4 && buf[i + 1] > 0x8f) || + buf[i] > 0xf4 // > U+10FFFF + ) { + return false; + } else { + i += 4; + } + } else { + return false; + } + } + + return true; +} + +try { + let isValidUTF8 = require('utf-8-validate'); + + /* istanbul ignore if */ + if (typeof isValidUTF8 === 'object') { + isValidUTF8 = isValidUTF8.Validation.isValidUTF8; // utf-8-validate@<3.0.0 + } + + module.exports = { + isValidStatusCode, + isValidUTF8(buf) { + return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf); + } + }; +} catch (e) /* istanbul ignore next */ { + module.exports = { + isValidStatusCode, + isValidUTF8: _isValidUTF8 + }; +} diff --git a/node_modules/ws/lib/websocket-server.js b/node_modules/ws/lib/websocket-server.js new file mode 100644 index 0000000..b99ad05 --- /dev/null +++ b/node_modules/ws/lib/websocket-server.js @@ -0,0 +1,406 @@ +'use strict'; + +const EventEmitter = require('events'); +const { createHash } = require('crypto'); +const { createServer, STATUS_CODES } = require('http'); + +const PerMessageDeflate = require('./permessage-deflate'); +const WebSocket = require('./websocket'); +const { format, parse } = require('./extension'); +const { GUID, kWebSocket } = require('./constants'); + +const keyRegex = /^[+/0-9A-Za-z]{22}==$/; + +/** + * Class representing a WebSocket server. + * + * @extends EventEmitter + */ +class WebSocketServer extends EventEmitter { + /** + * Create a `WebSocketServer` instance. + * + * @param {Object} options Configuration options + * @param {Number} [options.backlog=511] The maximum length of the queue of + * pending connections + * @param {Boolean} [options.clientTracking=true] Specifies whether or not to + * track clients + * @param {Function} [options.handleProtocols] A hook to handle protocols + * @param {String} [options.host] The hostname where to bind the server + * @param {Number} [options.maxPayload=104857600] The maximum allowed message + * size + * @param {Boolean} [options.noServer=false] Enable no server mode + * @param {String} [options.path] Accept only connections matching this path + * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable + * permessage-deflate + * @param {Number} [options.port] The port where to bind the server + * @param {http.Server} [options.server] A pre-created HTTP/S server to use + * @param {Function} [options.verifyClient] A hook to reject connections + * @param {Function} [callback] A listener for the `listening` event + */ + constructor(options, callback) { + super(); + + options = { + maxPayload: 100 * 1024 * 1024, + perMessageDeflate: false, + handleProtocols: null, + clientTracking: true, + verifyClient: null, + noServer: false, + backlog: null, // use default (511 as implemented in net.js) + server: null, + host: null, + path: null, + port: null, + ...options + }; + + if (options.port == null && !options.server && !options.noServer) { + throw new TypeError( + 'One of the "port", "server", or "noServer" options must be specified' + ); + } + + if (options.port != null) { + this._server = createServer((req, res) => { + const body = STATUS_CODES[426]; + + res.writeHead(426, { + 'Content-Length': body.length, + 'Content-Type': 'text/plain' + }); + res.end(body); + }); + this._server.listen( + options.port, + options.host, + options.backlog, + callback + ); + } else if (options.server) { + this._server = options.server; + } + + if (this._server) { + const emitConnection = this.emit.bind(this, 'connection'); + + this._removeListeners = addListeners(this._server, { + listening: this.emit.bind(this, 'listening'), + error: this.emit.bind(this, 'error'), + upgrade: (req, socket, head) => { + this.handleUpgrade(req, socket, head, emitConnection); + } + }); + } + + if (options.perMessageDeflate === true) options.perMessageDeflate = {}; + if (options.clientTracking) this.clients = new Set(); + this.options = options; + } + + /** + * Returns the bound address, the address family name, and port of the server + * as reported by the operating system if listening on an IP socket. + * If the server is listening on a pipe or UNIX domain socket, the name is + * returned as a string. + * + * @return {(Object|String|null)} The address of the server + * @public + */ + address() { + if (this.options.noServer) { + throw new Error('The server is operating in "noServer" mode'); + } + + if (!this._server) return null; + return this._server.address(); + } + + /** + * Close the server. + * + * @param {Function} [cb] Callback + * @public + */ + close(cb) { + if (cb) this.once('close', cb); + + // + // Terminate all associated clients. + // + if (this.clients) { + for (const client of this.clients) client.terminate(); + } + + const server = this._server; + + if (server) { + this._removeListeners(); + this._removeListeners = this._server = null; + + // + // Close the http server if it was internally created. + // + if (this.options.port != null) { + server.close(() => this.emit('close')); + return; + } + } + + process.nextTick(emitClose, this); + } + + /** + * See if a given request should be handled by this server instance. + * + * @param {http.IncomingMessage} req Request object to inspect + * @return {Boolean} `true` if the request is valid, else `false` + * @public + */ + shouldHandle(req) { + if (this.options.path) { + const index = req.url.indexOf('?'); + const pathname = index !== -1 ? req.url.slice(0, index) : req.url; + + if (pathname !== this.options.path) return false; + } + + return true; + } + + /** + * Handle a HTTP Upgrade request. + * + * @param {http.IncomingMessage} req The request object + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @public + */ + handleUpgrade(req, socket, head, cb) { + socket.on('error', socketOnError); + + const key = + req.headers['sec-websocket-key'] !== undefined + ? req.headers['sec-websocket-key'].trim() + : false; + const version = +req.headers['sec-websocket-version']; + const extensions = {}; + + if ( + req.method !== 'GET' || + req.headers.upgrade.toLowerCase() !== 'websocket' || + !key || + !keyRegex.test(key) || + (version !== 8 && version !== 13) || + !this.shouldHandle(req) + ) { + return abortHandshake(socket, 400); + } + + if (this.options.perMessageDeflate) { + const perMessageDeflate = new PerMessageDeflate( + this.options.perMessageDeflate, + true, + this.options.maxPayload + ); + + try { + const offers = parse(req.headers['sec-websocket-extensions']); + + if (offers[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); + extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + } catch (err) { + return abortHandshake(socket, 400); + } + } + + // + // Optionally call external client verification handler. + // + if (this.options.verifyClient) { + const info = { + origin: + req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`], + secure: !!(req.socket.authorized || req.socket.encrypted), + req + }; + + if (this.options.verifyClient.length === 2) { + this.options.verifyClient(info, (verified, code, message, headers) => { + if (!verified) { + return abortHandshake(socket, code || 401, message, headers); + } + + this.completeUpgrade(key, extensions, req, socket, head, cb); + }); + return; + } + + if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); + } + + this.completeUpgrade(key, extensions, req, socket, head, cb); + } + + /** + * Upgrade the connection to WebSocket. + * + * @param {String} key The value of the `Sec-WebSocket-Key` header + * @param {Object} extensions The accepted extensions + * @param {http.IncomingMessage} req The request object + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @throws {Error} If called more than once with the same socket + * @private + */ + completeUpgrade(key, extensions, req, socket, head, cb) { + // + // Destroy the socket if the client has already sent a FIN packet. + // + if (!socket.readable || !socket.writable) return socket.destroy(); + + if (socket[kWebSocket]) { + throw new Error( + 'server.handleUpgrade() was called more than once with the same ' + + 'socket, possibly due to a misconfiguration' + ); + } + + const digest = createHash('sha1') + .update(key + GUID) + .digest('base64'); + + const headers = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: Upgrade', + `Sec-WebSocket-Accept: ${digest}` + ]; + + const ws = new WebSocket(null); + let protocol = req.headers['sec-websocket-protocol']; + + if (protocol) { + protocol = protocol.trim().split(/ *, */); + + // + // Optionally call external protocol selection handler. + // + if (this.options.handleProtocols) { + protocol = this.options.handleProtocols(protocol, req); + } else { + protocol = protocol[0]; + } + + if (protocol) { + headers.push(`Sec-WebSocket-Protocol: ${protocol}`); + ws._protocol = protocol; + } + } + + if (extensions[PerMessageDeflate.extensionName]) { + const params = extensions[PerMessageDeflate.extensionName].params; + const value = format({ + [PerMessageDeflate.extensionName]: [params] + }); + headers.push(`Sec-WebSocket-Extensions: ${value}`); + ws._extensions = extensions; + } + + // + // Allow external modification/inspection of handshake headers. + // + this.emit('headers', headers, req); + + socket.write(headers.concat('\r\n').join('\r\n')); + socket.removeListener('error', socketOnError); + + ws.setSocket(socket, head, this.options.maxPayload); + + if (this.clients) { + this.clients.add(ws); + ws.on('close', () => this.clients.delete(ws)); + } + + cb(ws, req); + } +} + +module.exports = WebSocketServer; + +/** + * Add event listeners on an `EventEmitter` using a map of + * pairs. + * + * @param {EventEmitter} server The event emitter + * @param {Object.} map The listeners to add + * @return {Function} A function that will remove the added listeners when + * called + * @private + */ +function addListeners(server, map) { + for (const event of Object.keys(map)) server.on(event, map[event]); + + return function removeListeners() { + for (const event of Object.keys(map)) { + server.removeListener(event, map[event]); + } + }; +} + +/** + * Emit a `'close'` event on an `EventEmitter`. + * + * @param {EventEmitter} server The event emitter + * @private + */ +function emitClose(server) { + server.emit('close'); +} + +/** + * Handle premature socket errors. + * + * @private + */ +function socketOnError() { + this.destroy(); +} + +/** + * Close the connection when preconditions are not fulfilled. + * + * @param {net.Socket} socket The socket of the upgrade request + * @param {Number} code The HTTP response status code + * @param {String} [message] The HTTP response body + * @param {Object} [headers] Additional HTTP response headers + * @private + */ +function abortHandshake(socket, code, message, headers) { + if (socket.writable) { + message = message || STATUS_CODES[code]; + headers = { + Connection: 'close', + 'Content-Type': 'text/html', + 'Content-Length': Buffer.byteLength(message), + ...headers + }; + + socket.write( + `HTTP/1.1 ${code} ${STATUS_CODES[code]}\r\n` + + Object.keys(headers) + .map((h) => `${h}: ${headers[h]}`) + .join('\r\n') + + '\r\n\r\n' + + message + ); + } + + socket.removeListener('error', socketOnError); + socket.destroy(); +} diff --git a/node_modules/ws/lib/websocket.js b/node_modules/ws/lib/websocket.js new file mode 100644 index 0000000..5392381 --- /dev/null +++ b/node_modules/ws/lib/websocket.js @@ -0,0 +1,943 @@ +'use strict'; + +const EventEmitter = require('events'); +const https = require('https'); +const http = require('http'); +const net = require('net'); +const tls = require('tls'); +const { randomBytes, createHash } = require('crypto'); +const { URL } = require('url'); + +const PerMessageDeflate = require('./permessage-deflate'); +const Receiver = require('./receiver'); +const Sender = require('./sender'); +const { + BINARY_TYPES, + EMPTY_BUFFER, + GUID, + kStatusCode, + kWebSocket, + NOOP +} = require('./constants'); +const { addEventListener, removeEventListener } = require('./event-target'); +const { format, parse } = require('./extension'); +const { toBuffer } = require('./buffer-util'); + +const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; +const protocolVersions = [8, 13]; +const closeTimeout = 30 * 1000; + +/** + * Class representing a WebSocket. + * + * @extends EventEmitter + */ +class WebSocket extends EventEmitter { + /** + * Create a new `WebSocket`. + * + * @param {(String|url.URL)} address The URL to which to connect + * @param {(String|String[])} [protocols] The subprotocols + * @param {Object} [options] Connection options + */ + constructor(address, protocols, options) { + super(); + + this._binaryType = BINARY_TYPES[0]; + this._closeCode = 1006; + this._closeFrameReceived = false; + this._closeFrameSent = false; + this._closeMessage = ''; + this._closeTimer = null; + this._extensions = {}; + this._protocol = ''; + this._readyState = WebSocket.CONNECTING; + this._receiver = null; + this._sender = null; + this._socket = null; + + if (address !== null) { + this._bufferedAmount = 0; + this._isServer = false; + this._redirects = 0; + + if (Array.isArray(protocols)) { + protocols = protocols.join(', '); + } else if (typeof protocols === 'object' && protocols !== null) { + options = protocols; + protocols = undefined; + } + + initAsClient(this, address, protocols, options); + } else { + this._isServer = true; + } + } + + /** + * This deviates from the WHATWG interface since ws doesn't support the + * required default "blob" type (instead we define a custom "nodebuffer" + * type). + * + * @type {String} + */ + get binaryType() { + return this._binaryType; + } + + set binaryType(type) { + if (!BINARY_TYPES.includes(type)) return; + + this._binaryType = type; + + // + // Allow to change `binaryType` on the fly. + // + if (this._receiver) this._receiver._binaryType = type; + } + + /** + * @type {Number} + */ + get bufferedAmount() { + if (!this._socket) return this._bufferedAmount; + + return this._socket._writableState.length + this._sender._bufferedBytes; + } + + /** + * @type {String} + */ + get extensions() { + return Object.keys(this._extensions).join(); + } + + /** + * @type {String} + */ + get protocol() { + return this._protocol; + } + + /** + * @type {Number} + */ + get readyState() { + return this._readyState; + } + + /** + * @type {String} + */ + get url() { + return this._url; + } + + /** + * Set up the socket and the internal resources. + * + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Number} [maxPayload=0] The maximum allowed message size + * @private + */ + setSocket(socket, head, maxPayload) { + const receiver = new Receiver( + this.binaryType, + this._extensions, + this._isServer, + maxPayload + ); + + this._sender = new Sender(socket, this._extensions); + this._receiver = receiver; + this._socket = socket; + + receiver[kWebSocket] = this; + socket[kWebSocket] = this; + + receiver.on('conclude', receiverOnConclude); + receiver.on('drain', receiverOnDrain); + receiver.on('error', receiverOnError); + receiver.on('message', receiverOnMessage); + receiver.on('ping', receiverOnPing); + receiver.on('pong', receiverOnPong); + + socket.setTimeout(0); + socket.setNoDelay(); + + if (head.length > 0) socket.unshift(head); + + socket.on('close', socketOnClose); + socket.on('data', socketOnData); + socket.on('end', socketOnEnd); + socket.on('error', socketOnError); + + this._readyState = WebSocket.OPEN; + this.emit('open'); + } + + /** + * Emit the `'close'` event. + * + * @private + */ + emitClose() { + if (!this._socket) { + this._readyState = WebSocket.CLOSED; + this.emit('close', this._closeCode, this._closeMessage); + return; + } + + if (this._extensions[PerMessageDeflate.extensionName]) { + this._extensions[PerMessageDeflate.extensionName].cleanup(); + } + + this._receiver.removeAllListeners(); + this._readyState = WebSocket.CLOSED; + this.emit('close', this._closeCode, this._closeMessage); + } + + /** + * Start a closing handshake. + * + * +----------+ +-----------+ +----------+ + * - - -|ws.close()|-->|close frame|-->|ws.close()|- - - + * | +----------+ +-----------+ +----------+ | + * +----------+ +-----------+ | + * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING + * +----------+ +-----------+ | + * | | | +---+ | + * +------------------------+-->|fin| - - - - + * | +---+ | +---+ + * - - - - -|fin|<---------------------+ + * +---+ + * + * @param {Number} [code] Status code explaining why the connection is closing + * @param {String} [data] A string explaining why the connection is closing + * @public + */ + close(code, data) { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + return abortHandshake(this, this._req, msg); + } + + if (this.readyState === WebSocket.CLOSING) { + if (this._closeFrameSent && this._closeFrameReceived) this._socket.end(); + return; + } + + this._readyState = WebSocket.CLOSING; + this._sender.close(code, data, !this._isServer, (err) => { + // + // This error is handled by the `'error'` listener on the socket. We only + // want to know if the close frame has been sent here. + // + if (err) return; + + this._closeFrameSent = true; + if (this._closeFrameReceived) this._socket.end(); + }); + + // + // Specify a timeout for the closing handshake to complete. + // + this._closeTimer = setTimeout( + this._socket.destroy.bind(this._socket), + closeTimeout + ); + } + + /** + * Send a ping. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the ping is sent + * @public + */ + ping(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + if (mask === undefined) mask = !this._isServer; + this._sender.ping(data || EMPTY_BUFFER, mask, cb); + } + + /** + * Send a pong. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the pong is sent + * @public + */ + pong(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + if (mask === undefined) mask = !this._isServer; + this._sender.pong(data || EMPTY_BUFFER, mask, cb); + } + + /** + * Send a data message. + * + * @param {*} data The message to send + * @param {Object} [options] Options object + * @param {Boolean} [options.compress] Specifies whether or not to compress + * `data` + * @param {Boolean} [options.binary] Specifies whether `data` is binary or + * text + * @param {Boolean} [options.fin=true] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when data is written out + * @public + */ + send(data, options, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof options === 'function') { + cb = options; + options = {}; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + const opts = { + binary: typeof data !== 'string', + mask: !this._isServer, + compress: true, + fin: true, + ...options + }; + + if (!this._extensions[PerMessageDeflate.extensionName]) { + opts.compress = false; + } + + this._sender.send(data || EMPTY_BUFFER, opts, cb); + } + + /** + * Forcibly close the connection. + * + * @public + */ + terminate() { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + return abortHandshake(this, this._req, msg); + } + + if (this._socket) { + this._readyState = WebSocket.CLOSING; + this._socket.destroy(); + } + } +} + +readyStates.forEach((readyState, i) => { + const descriptor = { enumerable: true, value: i }; + + Object.defineProperty(WebSocket.prototype, readyState, descriptor); + Object.defineProperty(WebSocket, readyState, descriptor); +}); + +[ + 'binaryType', + 'bufferedAmount', + 'extensions', + 'protocol', + 'readyState', + 'url' +].forEach((property) => { + Object.defineProperty(WebSocket.prototype, property, { enumerable: true }); +}); + +// +// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes. +// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface +// +['open', 'error', 'close', 'message'].forEach((method) => { + Object.defineProperty(WebSocket.prototype, `on${method}`, { + configurable: true, + enumerable: true, + /** + * Return the listener of the event. + * + * @return {(Function|undefined)} The event listener or `undefined` + * @public + */ + get() { + const listeners = this.listeners(method); + for (let i = 0; i < listeners.length; i++) { + if (listeners[i]._listener) return listeners[i]._listener; + } + + return undefined; + }, + /** + * Add a listener for the event. + * + * @param {Function} listener The listener to add + * @public + */ + set(listener) { + const listeners = this.listeners(method); + for (let i = 0; i < listeners.length; i++) { + // + // Remove only the listeners added via `addEventListener`. + // + if (listeners[i]._listener) this.removeListener(method, listeners[i]); + } + this.addEventListener(method, listener); + } + }); +}); + +WebSocket.prototype.addEventListener = addEventListener; +WebSocket.prototype.removeEventListener = removeEventListener; + +module.exports = WebSocket; + +/** + * Initialize a WebSocket client. + * + * @param {WebSocket} websocket The client to initialize + * @param {(String|url.URL)} address The URL to which to connect + * @param {String} [protocols] The subprotocols + * @param {Object} [options] Connection options + * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable + * permessage-deflate + * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the + * handshake request + * @param {Number} [options.protocolVersion=13] Value of the + * `Sec-WebSocket-Version` header + * @param {String} [options.origin] Value of the `Origin` or + * `Sec-WebSocket-Origin` header + * @param {Number} [options.maxPayload=104857600] The maximum allowed message + * size + * @param {Boolean} [options.followRedirects=false] Whether or not to follow + * redirects + * @param {Number} [options.maxRedirects=10] The maximum number of redirects + * allowed + * @private + */ +function initAsClient(websocket, address, protocols, options) { + const opts = { + protocolVersion: protocolVersions[1], + maxPayload: 100 * 1024 * 1024, + perMessageDeflate: true, + followRedirects: false, + maxRedirects: 10, + ...options, + createConnection: undefined, + socketPath: undefined, + hostname: undefined, + protocol: undefined, + timeout: undefined, + method: undefined, + host: undefined, + path: undefined, + port: undefined + }; + + if (!protocolVersions.includes(opts.protocolVersion)) { + throw new RangeError( + `Unsupported protocol version: ${opts.protocolVersion} ` + + `(supported versions: ${protocolVersions.join(', ')})` + ); + } + + let parsedUrl; + + if (address instanceof URL) { + parsedUrl = address; + websocket._url = address.href; + } else { + parsedUrl = new URL(address); + websocket._url = address; + } + + const isUnixSocket = parsedUrl.protocol === 'ws+unix:'; + + if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) { + throw new Error(`Invalid URL: ${websocket.url}`); + } + + const isSecure = + parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:'; + const defaultPort = isSecure ? 443 : 80; + const key = randomBytes(16).toString('base64'); + const get = isSecure ? https.get : http.get; + let perMessageDeflate; + + opts.createConnection = isSecure ? tlsConnect : netConnect; + opts.defaultPort = opts.defaultPort || defaultPort; + opts.port = parsedUrl.port || defaultPort; + opts.host = parsedUrl.hostname.startsWith('[') + ? parsedUrl.hostname.slice(1, -1) + : parsedUrl.hostname; + opts.headers = { + 'Sec-WebSocket-Version': opts.protocolVersion, + 'Sec-WebSocket-Key': key, + Connection: 'Upgrade', + Upgrade: 'websocket', + ...opts.headers + }; + opts.path = parsedUrl.pathname + parsedUrl.search; + opts.timeout = opts.handshakeTimeout; + + if (opts.perMessageDeflate) { + perMessageDeflate = new PerMessageDeflate( + opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, + false, + opts.maxPayload + ); + opts.headers['Sec-WebSocket-Extensions'] = format({ + [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + }); + } + if (protocols) { + opts.headers['Sec-WebSocket-Protocol'] = protocols; + } + if (opts.origin) { + if (opts.protocolVersion < 13) { + opts.headers['Sec-WebSocket-Origin'] = opts.origin; + } else { + opts.headers.Origin = opts.origin; + } + } + if (parsedUrl.username || parsedUrl.password) { + opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; + } + + if (isUnixSocket) { + const parts = opts.path.split(':'); + + opts.socketPath = parts[0]; + opts.path = parts[1]; + } + + let req = (websocket._req = get(opts)); + + if (opts.timeout) { + req.on('timeout', () => { + abortHandshake(websocket, req, 'Opening handshake has timed out'); + }); + } + + req.on('error', (err) => { + if (req === null || req.aborted) return; + + req = websocket._req = null; + websocket._readyState = WebSocket.CLOSING; + websocket.emit('error', err); + websocket.emitClose(); + }); + + req.on('response', (res) => { + const location = res.headers.location; + const statusCode = res.statusCode; + + if ( + location && + opts.followRedirects && + statusCode >= 300 && + statusCode < 400 + ) { + if (++websocket._redirects > opts.maxRedirects) { + abortHandshake(websocket, req, 'Maximum redirects exceeded'); + return; + } + + req.abort(); + + const addr = new URL(location, address); + + initAsClient(websocket, addr, protocols, options); + } else if (!websocket.emit('unexpected-response', req, res)) { + abortHandshake( + websocket, + req, + `Unexpected server response: ${res.statusCode}` + ); + } + }); + + req.on('upgrade', (res, socket, head) => { + websocket.emit('upgrade', res); + + // + // The user may have closed the connection from a listener of the `upgrade` + // event. + // + if (websocket.readyState !== WebSocket.CONNECTING) return; + + req = websocket._req = null; + + const digest = createHash('sha1') + .update(key + GUID) + .digest('base64'); + + if (res.headers['sec-websocket-accept'] !== digest) { + abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header'); + return; + } + + const serverProt = res.headers['sec-websocket-protocol']; + const protList = (protocols || '').split(/, */); + let protError; + + if (!protocols && serverProt) { + protError = 'Server sent a subprotocol but none was requested'; + } else if (protocols && !serverProt) { + protError = 'Server sent no subprotocol'; + } else if (serverProt && !protList.includes(serverProt)) { + protError = 'Server sent an invalid subprotocol'; + } + + if (protError) { + abortHandshake(websocket, socket, protError); + return; + } + + if (serverProt) websocket._protocol = serverProt; + + if (perMessageDeflate) { + try { + const extensions = parse(res.headers['sec-websocket-extensions']); + + if (extensions[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); + websocket._extensions[ + PerMessageDeflate.extensionName + ] = perMessageDeflate; + } + } catch (err) { + abortHandshake( + websocket, + socket, + 'Invalid Sec-WebSocket-Extensions header' + ); + return; + } + } + + websocket.setSocket(socket, head, opts.maxPayload); + }); +} + +/** + * Create a `net.Socket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {net.Socket} The newly created socket used to start the connection + * @private + */ +function netConnect(options) { + options.path = options.socketPath; + return net.connect(options); +} + +/** + * Create a `tls.TLSSocket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {tls.TLSSocket} The newly created socket used to start the connection + * @private + */ +function tlsConnect(options) { + options.path = undefined; + + if (!options.servername && options.servername !== '') { + options.servername = net.isIP(options.host) ? '' : options.host; + } + + return tls.connect(options); +} + +/** + * Abort the handshake and emit an error. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {(http.ClientRequest|net.Socket)} stream The request to abort or the + * socket to destroy + * @param {String} message The error message + * @private + */ +function abortHandshake(websocket, stream, message) { + websocket._readyState = WebSocket.CLOSING; + + const err = new Error(message); + Error.captureStackTrace(err, abortHandshake); + + if (stream.setHeader) { + stream.abort(); + + if (stream.socket && !stream.socket.destroyed) { + // + // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if + // called after the request completed. See + // https://github.com/websockets/ws/issues/1869. + // + stream.socket.destroy(); + } + + stream.once('abort', websocket.emitClose.bind(websocket)); + websocket.emit('error', err); + } else { + stream.destroy(err); + stream.once('error', websocket.emit.bind(websocket, 'error')); + stream.once('close', websocket.emitClose.bind(websocket)); + } +} + +/** + * Handle cases where the `ping()`, `pong()`, or `send()` methods are called + * when the `readyState` attribute is `CLOSING` or `CLOSED`. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {*} [data] The data to send + * @param {Function} [cb] Callback + * @private + */ +function sendAfterClose(websocket, data, cb) { + if (data) { + const length = toBuffer(data).length; + + // + // The `_bufferedAmount` property is used only when the peer is a client and + // the opening handshake fails. Under these circumstances, in fact, the + // `setSocket()` method is not called, so the `_socket` and `_sender` + // properties are set to `null`. + // + if (websocket._socket) websocket._sender._bufferedBytes += length; + else websocket._bufferedAmount += length; + } + + if (cb) { + const err = new Error( + `WebSocket is not open: readyState ${websocket.readyState} ` + + `(${readyStates[websocket.readyState]})` + ); + cb(err); + } +} + +/** + * The listener of the `Receiver` `'conclude'` event. + * + * @param {Number} code The status code + * @param {String} reason The reason for closing + * @private + */ +function receiverOnConclude(code, reason) { + const websocket = this[kWebSocket]; + + websocket._socket.removeListener('data', socketOnData); + websocket._socket.resume(); + + websocket._closeFrameReceived = true; + websocket._closeMessage = reason; + websocket._closeCode = code; + + if (code === 1005) websocket.close(); + else websocket.close(code, reason); +} + +/** + * The listener of the `Receiver` `'drain'` event. + * + * @private + */ +function receiverOnDrain() { + this[kWebSocket]._socket.resume(); +} + +/** + * The listener of the `Receiver` `'error'` event. + * + * @param {(RangeError|Error)} err The emitted error + * @private + */ +function receiverOnError(err) { + const websocket = this[kWebSocket]; + + websocket._socket.removeListener('data', socketOnData); + + websocket._readyState = WebSocket.CLOSING; + websocket._closeCode = err[kStatusCode]; + websocket.emit('error', err); + websocket._socket.destroy(); +} + +/** + * The listener of the `Receiver` `'finish'` event. + * + * @private + */ +function receiverOnFinish() { + this[kWebSocket].emitClose(); +} + +/** + * The listener of the `Receiver` `'message'` event. + * + * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The message + * @private + */ +function receiverOnMessage(data) { + this[kWebSocket].emit('message', data); +} + +/** + * The listener of the `Receiver` `'ping'` event. + * + * @param {Buffer} data The data included in the ping frame + * @private + */ +function receiverOnPing(data) { + const websocket = this[kWebSocket]; + + websocket.pong(data, !websocket._isServer, NOOP); + websocket.emit('ping', data); +} + +/** + * The listener of the `Receiver` `'pong'` event. + * + * @param {Buffer} data The data included in the pong frame + * @private + */ +function receiverOnPong(data) { + this[kWebSocket].emit('pong', data); +} + +/** + * The listener of the `net.Socket` `'close'` event. + * + * @private + */ +function socketOnClose() { + const websocket = this[kWebSocket]; + + this.removeListener('close', socketOnClose); + this.removeListener('end', socketOnEnd); + + websocket._readyState = WebSocket.CLOSING; + + // + // The close frame might not have been received or the `'end'` event emitted, + // for example, if the socket was destroyed due to an error. Ensure that the + // `receiver` stream is closed after writing any remaining buffered data to + // it. If the readable side of the socket is in flowing mode then there is no + // buffered data as everything has been already written and `readable.read()` + // will return `null`. If instead, the socket is paused, any possible buffered + // data will be read as a single chunk and emitted synchronously in a single + // `'data'` event. + // + websocket._socket.read(); + websocket._receiver.end(); + + this.removeListener('data', socketOnData); + this[kWebSocket] = undefined; + + clearTimeout(websocket._closeTimer); + + if ( + websocket._receiver._writableState.finished || + websocket._receiver._writableState.errorEmitted + ) { + websocket.emitClose(); + } else { + websocket._receiver.on('error', receiverOnFinish); + websocket._receiver.on('finish', receiverOnFinish); + } +} + +/** + * The listener of the `net.Socket` `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function socketOnData(chunk) { + if (!this[kWebSocket]._receiver.write(chunk)) { + this.pause(); + } +} + +/** + * The listener of the `net.Socket` `'end'` event. + * + * @private + */ +function socketOnEnd() { + const websocket = this[kWebSocket]; + + websocket._readyState = WebSocket.CLOSING; + websocket._receiver.end(); + this.end(); +} + +/** + * The listener of the `net.Socket` `'error'` event. + * + * @private + */ +function socketOnError() { + const websocket = this[kWebSocket]; + + this.removeListener('error', socketOnError); + this.on('error', NOOP); + + if (websocket) { + websocket._readyState = WebSocket.CLOSING; + this.destroy(); + } +} diff --git a/node_modules/ws/package.json b/node_modules/ws/package.json new file mode 100644 index 0000000..c2d63af --- /dev/null +++ b/node_modules/ws/package.json @@ -0,0 +1,56 @@ +{ + "name": "ws", + "version": "7.4.5", + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", + "keywords": [ + "HyBi", + "Push", + "RFC-6455", + "WebSocket", + "WebSockets", + "real-time" + ], + "homepage": "https://github.com/websockets/ws", + "bugs": "https://github.com/websockets/ws/issues", + "repository": "websockets/ws", + "author": "Einar Otto Stangvik (http://2x.io)", + "license": "MIT", + "main": "index.js", + "browser": "browser.js", + "engines": { + "node": ">=8.3.0" + }, + "files": [ + "browser.js", + "index.js", + "lib/*.js" + ], + "scripts": { + "test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js", + "integration": "mocha --throw-deprecation test/*.integration.js", + "lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + }, + "devDependencies": { + "benchmark": "^2.1.4", + "bufferutil": "^4.0.1", + "eslint": "^7.2.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-prettier": "^3.0.1", + "mocha": "^7.0.0", + "nyc": "^15.0.0", + "prettier": "^2.0.5", + "utf-8-validate": "^5.0.2" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..843c2ce --- /dev/null +++ b/package-lock.json @@ -0,0 +1,777 @@ +{ + "name": "PharmaBot", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "discord.js": "^12.5.1", + "got": "^11.8.2" + } + }, + "node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + }, + "node_modules/@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", + "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==" + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", + "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/prism-media": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", + "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==", + "peerDependencies": { + "@discordjs/opus": "^0.5.0", + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve-alpn": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", + "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==" + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "@sindresorhus/is": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" + }, + "@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + }, + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", + "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==" + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + }, + "cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "requires": { + "json-buffer": "3.0.1" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + }, + "mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "requires": { + "mime-db": "1.47.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", + "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==" + }, + "prism-media": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", + "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==", + "requires": {} + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, + "resolve-alpn": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", + "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==" + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "requires": {} + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fb990d9 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "PharmaBot", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "node index.js" + }, + "repository": { + "type": "git", + "url": "http://10.10.4.20:3000/HarrisonDubois/discordbot.git" + }, + "author": "Expand", + "license": "ISC", + "dependencies": { + "discord.js": "^12.5.1", + "got": "^11.8.2" + } +}