├── .eslintrc.cjs ├── .github └── workflows │ └── run-tests.yml ├── .gitignore ├── CHANGELOG.md ├── README.md ├── lib ├── internal │ ├── channels.js │ ├── chats.js │ ├── devices.js │ ├── encryption.js │ ├── ephemerals.js │ ├── pushes.js │ ├── stream.js │ ├── subscriptions.js │ ├── texts.js │ └── users.js └── pushbullet.js ├── package-lock.json ├── package.json └── test ├── channels.js ├── chats.js ├── devices.js ├── ephemerals.js ├── pushes.js ├── subscriptions.js ├── texts.js └── users.js /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root : true, 3 | parserOptions : { 4 | ecmaVersion : 'latest', 5 | sourceType : 'module' 6 | }, 7 | env : { 8 | node : true, 9 | es6 : true 10 | }, 11 | extends : 'eslint:recommended', 12 | rules : { 13 | 'array-bracket-spacing' : [ 14 | 'error', 15 | 'always', 16 | { 17 | objectsInArrays : false, 18 | arraysInArrays : false 19 | } 20 | ], 21 | 'brace-style' : [ 22 | 'error', 23 | 'stroustrup', 24 | { 25 | allowSingleLine : true 26 | } 27 | ], 28 | 'comma-dangle' : [ 29 | 'error', 30 | 'never' 31 | ], 32 | 'eol-last' : [ 33 | 'error', 34 | 'always' 35 | ], 36 | eqeqeq : [ 37 | 'error', 38 | 'always' 39 | ], 40 | indent : [ 41 | 'error', 42 | 'tab', 43 | { 44 | SwitchCase : 1 45 | } 46 | ], 47 | 'key-spacing' : [ 48 | 'error', 49 | { 50 | beforeColon : true, 51 | afterColon : true, 52 | align : 'colon' 53 | } 54 | ], 55 | 'linebreak-style' : [ 56 | 'error', 57 | 'unix' 58 | ], 59 | 'no-trailing-spaces' : [ 60 | 'error' 61 | ], 62 | 'quote-props' : [ 63 | 'error', 64 | 'as-needed' 65 | ], 66 | quotes : [ 67 | 'error', 68 | 'single', 69 | { 70 | avoidEscape : true 71 | } 72 | ], 73 | semi : [ 74 | 'error', 75 | 'always' 76 | ], 77 | 'space-infix-ops' : [ 78 | 'error' 79 | ] 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: [14.x, 16.x, 17.x] 11 | 12 | steps: 13 | - name: Git checkout 14 | uses: actions/checkout@v1 15 | 16 | - name: npm ci 17 | run: | 18 | npm ci 19 | 20 | - name: npm run-script lint 21 | run: | 22 | npm run-script lint 23 | 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v1 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | 29 | - name: npm run-script test 30 | run: | 31 | npm run-script test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | ### 3.0.0 4 | 5 | **Note that this major version release contains backwards incompatible changes.** 6 | 7 | - Callback functionality has been removed. Callbacks can still be used by using `util.callbackify()`. 8 | - `request` has been replaced by `node-fetch`. Full API responses are returned by function calls. 9 | - Add support for for text API. 10 | - Deprecate `sendSMS()`, this is deprecated in the API and is replaced by `createText()`. 11 | - Add `createChannel()`. 12 | 13 | ### 2.4.0 14 | 15 | - Reconnect to websocket stream if disconnected. 16 | 17 | ### 2.3.0 18 | 19 | - Switch to `ws` module for the websocket stream. 20 | - Fix `close` on stream connection to actually close. 21 | - Add `fullResponses` option to return response objects from requests. 22 | 23 | ### 2.2.0 24 | 25 | - Add promise support. 26 | 27 | ### 2.1.0 28 | 29 | - Add end to end encryption support. 30 | - Support the `body` parameter for the `link` push type. 31 | 32 | ### 2.0.0 33 | 34 | **Note that this major version release contains backwards incompatible changes.** 35 | 36 | - Remove support for deprecated `list` and `address` push types. 37 | - Add `deleteAllPushes` function. 38 | - Use `Access-Token` header for authentication. 39 | - Remove Contacts functions. 40 | - Rename `updatePush` to `dismissPush`. 41 | - Add `updateDevice` function. 42 | - Change signature of `createDevice` to take an Object of device options. 43 | - Add `muteSubscription` and `unmuteSubscription` functions. 44 | - Default `devices` to active only. 45 | - Default `subscriptions` to active only. 46 | - Add chats functions. 47 | - Add ephemerals support for sending SMS messages, clipboard messages and dismissals. 48 | 49 | ### 1.4.3 50 | 51 | - Check file existence before trying to push. 52 | 53 | ### 1.4.2 54 | 55 | - Fix error message handling. 56 | 57 | ### 1.4.1 58 | 59 | - Fix usage of `file`. 60 | 61 | ### 1.4.0 62 | 63 | - Add support for subscriptions API. 64 | - Update `updatePush` so that lists can be updated. 65 | - Add support for more target types. 66 | - Fix missing parameter in `contacts` function. 67 | 68 | ### 1.3.0 69 | 70 | - Add options parameter to `contacts`, `devices` and `history` to control responses. 71 | 72 | ### 1.2.0 73 | 74 | - Add `createContact` function. 75 | - Add `updatePush` function. 76 | 77 | ### 1.1.0 78 | 79 | - Add `createDevice` function. 80 | 81 | ### 1.0.0 82 | 83 | - Upgrade to and support version 2 of the API. 84 | 85 | ### 0.5.0 86 | 87 | - Set request defaults locally so multiple instances can be used. 88 | 89 | ### 0.4.0 90 | 91 | - Support and prefer using device IDENs over device IDs. 92 | 93 | ### 0.3.0 94 | 95 | - Use JSON post body rather than form encoding. Fixes empty lists. 96 | 97 | ### 0.2.0 98 | 99 | - Update API URL 100 | 101 | ### 0.1.0 102 | 103 | - Initial release 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PushBullet API 2 | 3 | A Node.js module for using the [PushBullet REST API](https://www.pushbullet.com/api). 4 | 5 | ## Usage 6 | 7 | This module is very simple to use. All you need is your PushBullet API key and you can begin pushing. 8 | 9 | ```javascript 10 | let PushBullet = require('pushbullet'); 11 | let pusher = new PushBullet('YOUR-API-KEY'); 12 | 13 | let response = await pusher.devices(); 14 | 15 | let response = await pusher.note(deviceParams, noteTitle, noteBody); 16 | ``` 17 | 18 | ### Target devices 19 | 20 | The push functions (`note`, `link`, `file`) have a `deviceParams` parameter which can be several types: 21 | 22 | - If it is a string containing an '@' it is treated as an email address. 23 | - If it is a string not containing an '@' it is treated as a device iden. 24 | - If it is a number it is treated as a device id. 25 | - If it is an object it is assumed to have one of the 'target parameters' as defined on https://docs.pushbullet.com/v2/pushes/ as an attribute. It can also have an optional `source_device_iden` attribute. If the object is empty, `{}`, then the push is sent to all devices. 26 | 27 | ### Async/Await 28 | 29 | Version 2 of the module supported callback and promise based execution. Version 3 uses async/await. Callbacks can still be used by utilising `util.callbackify()`. 30 | 31 | ```javascript 32 | let response = await pusher.devices(); 33 | console.log(await response.json()); 34 | ``` 35 | 36 | ## API 37 | 38 | ### new PushBullet(apiKey) 39 | 40 | Creates a new PushBullet object. 41 | 42 | The `apiKey` parameter is the string API key provided by PushBullet. 43 | 44 | ### PushBullet.me(); 45 | 46 | Get the current user's information. 47 | 48 | ```javascript 49 | await pusher.me(); 50 | ``` 51 | 52 | ### PushBullet.devices([options]) 53 | 54 | Retrieves a list of pushable devices. 55 | 56 | The `options` parameter can use two attributes `cursor` and`limit` 57 | to control the data returned. 58 | 59 | - `active` is used to restrict the results to only active devices. 60 | - `cursor` is used to select the page if the results have been paginated. 61 | - `limit` is used to limit the number of objects in the reponse. 62 | 63 | ```javascript 64 | let options = { 65 | limit: 10 66 | }; 67 | 68 | await pusher.devices(options); 69 | ``` 70 | 71 | ### PushBullet.createDevice(deviceOptions) 72 | 73 | Creates a new device. 74 | 75 | ```javascript 76 | let deviceOptions = { 77 | nickname: 'node-app' 78 | }; 79 | 80 | await pusher.createDevice(deviceOptions); 81 | ``` 82 | 83 | ### PushBullet.updateDevice(deviceIden, deviceOptions) 84 | 85 | Creates a new device. 86 | 87 | ```javascript 88 | let deviceOptions = { 89 | nickname: 'node-app' 90 | }; 91 | 92 | await pusher.updateDevice(deviceIden, deviceOptions); 93 | ``` 94 | 95 | ### PushBullet.deleteDevice(deviceIden) 96 | 97 | Delete a device. 98 | 99 | ```javascript 100 | await pusher.deleteDevice('u1qSJddxeKwOGuGW'); 101 | ``` 102 | 103 | ### PushBullet.note(deviceParams, noteTitle, noteBody) 104 | 105 | Push a note to the specified device. 106 | 107 | ```javascript 108 | await pusher.note('u1qSJddxeKwOGuGW', 'New Note', 'Note body text'); 109 | ``` 110 | 111 | ### PushBullet.link(deviceParams, name, url, body) 112 | 113 | Push a link to the specified device. 114 | 115 | ```javascript 116 | await pusher.link('u1qSJddxeKwOGuGW', 'GitHub', 'https://github.com/', 'Note body text'); 117 | ``` 118 | 119 | ### PushBullet.file(deviceParams, filePath, message) 120 | 121 | Push a file to the specified device. 122 | 123 | ```javascript 124 | await pusher.file('u1qSJddxeKwOGuGW', '/path/to/file', 'Important file!'); 125 | ``` 126 | 127 | ### PushBullet.dismissPush(pushIden) 128 | 129 | Dismiss a push. 130 | 131 | ```javascript 132 | await pusher.dismissPush('udhrSpjAewzdwpCC'); 133 | ``` 134 | 135 | ### PushBullet.deletePush(pushIden) 136 | 137 | Delete a push. 138 | 139 | ```javascript 140 | await pusher.deletePush('udhrSpjAewzdwpCC'); 141 | ``` 142 | 143 | ### PushBullet.deleteAllPushes(callback) 144 | 145 | Delete all pushes associated with the current account. 146 | 147 | ```javascript 148 | await pusher.deleteAllPushes(function(error, response) {}); 149 | ``` 150 | 151 | ### PushBullet.history([options]) 152 | 153 | Get the push history. 154 | 155 | The `options` parameter can use three attributes `cursor`, `limit` and 156 | `modified_after` to control the data returned. 157 | 158 | - `active` is used to only select undeleted pushes. Defaults to true if not specified. 159 | - `cursor` is used to select the page if the results have been paginated. 160 | - `limit` is used to limit the number of objects in the reponse. 161 | - `modified_after` should be a timestamp. Defaults to 0 if not specified. 162 | 163 | ```javascript 164 | let options = { 165 | limit: 10, 166 | modified_after: 1400000000.00000 167 | }; 168 | 169 | await pusher.history(options) 170 | ``` 171 | 172 | ### PushBullet.subscriptions([options]) 173 | 174 | Get a list of current subscriptions. 175 | 176 | The `options` parameter can use two attributes `cursor` and`limit` 177 | to control the data returned. 178 | 179 | - `active` is used to restrict the results to only active devices. 180 | - `cursor` is used to select the page if the results have been paginated. 181 | - `limit` is used to limit the number of objects in the reponse. 182 | 183 | ```javascript 184 | let options = { 185 | limit: 10 186 | }; 187 | 188 | await pusher.subscriptions(options); 189 | ``` 190 | 191 | ### PushBullet.subscribe(channelTag) 192 | 193 | Subscribe to a channel. 194 | 195 | ```javascript 196 | await pusher.subscribe('jblow'); 197 | ``` 198 | 199 | ### PushBullet.unsubscribe(subscriptionIden) 200 | 201 | Subscribe to a channel. 202 | 203 | ```javascript 204 | await pusher.unsubscribe('udprOsjAsLtNTRAG'); 205 | ``` 206 | 207 | ### PushBullet.muteSubscription(subscriptionIden) 208 | 209 | Mute a subscription. 210 | 211 | ```javascript 212 | await pusher.muteSubscription('udprOsjAsLtNTRAG'); 213 | ``` 214 | 215 | ### PushBullet.unmuteSubscription(subscriptionIden) 216 | 217 | Unmute a subscription. 218 | 219 | ```javascript 220 | await pusher.unmuteSubscription('udprOsjAsLtNTRAG'); 221 | ``` 222 | 223 | ### PushBullet.channelInfo(channelTag) 224 | 225 | Get information about a channel. 226 | 227 | ```javascript 228 | await pusher.channelInfo('jblow'); 229 | ``` 230 | 231 | ### PushBullet.chats([options]) 232 | 233 | Get a list of current chats. 234 | 235 | The `options` parameter can use two attributes `cursor` and`limit` 236 | to control the data returned. 237 | 238 | - `active` is used to restrict the results to only active devices. 239 | - `cursor` is used to select the page if the results have been paginated. 240 | - `limit` is used to limit the number of objects in the reponse. 241 | 242 | ```javascript 243 | let options = { 244 | limit: 10 245 | }; 246 | 247 | await pusher.chats(options); 248 | ``` 249 | 250 | ### PushBullet.createChat(email) 251 | 252 | Create a new chat. 253 | 254 | ```javascript 255 | await pusher.createChat('a@b.com'); 256 | ``` 257 | 258 | ### PushBullet.deleteChat(chatIden) 259 | 260 | Delete a chat. 261 | 262 | ```javascript 263 | await pusher.deleteChat('udprOsjAsLtNTRAG'); 264 | ``` 265 | 266 | ### PushBullet.muteChat(chatIden) 267 | 268 | Mute a chat. 269 | 270 | ```javascript 271 | await pusher.muteChat('udprOsjAsLtNTRAG'); 272 | ``` 273 | 274 | ### PushBullet.unmuteChat(chatIden) 275 | 276 | Unmute a chat. 277 | 278 | ```javascript 279 | await pusher.unmuteChat('udprOsjAsLtNTRAG'); 280 | ``` 281 | 282 | ### PushBullet.createText(deviceIden, addresses, message, [options]) 283 | 284 | Create a new text. 285 | 286 | The `options` parameter can be used to add additional information to the text request. 287 | 288 | - `file_url` is a URL of a file to send with the text. 289 | - `file_type` is the mime type of the file being sent. Required if `file_url` is used. 290 | 291 | Other options are available, see https://docs.pushbullet.com/#text 292 | 293 | ```javascript 294 | await pusher.createText('udprOsjAsLtNTRAG', '+13035551212', 'Test Message', {}); 295 | ``` 296 | 297 | ### PushBullet.updateText(textIden, options) 298 | 299 | Update a chat. 300 | 301 | `options` is an object representing the text attributes to update. 302 | See https://docs.pushbullet.com/#text for the available attributes and structure. 303 | 304 | ```javascript 305 | await pusher.updateText('udprOsjAsLtNTRAG', {}); 306 | ``` 307 | 308 | ### PushBullet.deleteText(textIden) 309 | 310 | Delete a text. 311 | 312 | ```javascript 313 | await pusher.deleteText('udprOsjAsLtNTRAG'); 314 | ``` 315 | 316 | ### PushBullet.sendSMS(options) 317 | 318 | Send an SMS through a device. 319 | 320 | ```javascript 321 | let options = { 322 | source_user_iden: 'ujpah72o0', // The user iden of the user sending this message 323 | target_device_iden: 'ujpah72o0sjAoRtnM0jc', // The iden of the device corresponding to the phone that should send the SMS 324 | conversation_iden: '+1 303 555 1212', // Phone number to send the SMS to 325 | message: 'Hello!' // The SMS message to send 326 | }; 327 | 328 | await pusher.sendSMS(options); 329 | ``` 330 | 331 | ### PushBullet.sendClipboard(options) 332 | 333 | Send clipboard content. 334 | 335 | ```javascript 336 | let options = { 337 | source_user_iden: "ujpah72o0", // The iden of the user sending this message 338 | source_device_iden: "ujpah72o0sjAoRtnM0jc", // The iden of the device sending this message 339 | body: "http://www.google.com", // The text to copy to the clipboard 340 | }; 341 | 342 | await pusher.sendClipboard(options); 343 | ``` 344 | 345 | ### PushBullet.dismissEphemeral(options) 346 | 347 | Dismiss an ephemeral. 348 | 349 | ```javascript 350 | let options = { 351 | package_name: 'com.pushbullet.android', // Set to the package_name field from the mirrored notification 352 | notification_id: '-8', // Set to the notification_id field from the mirrored notification 353 | notification_tag: null, // Set to the notification_tag field from the mirrored notification 354 | source_user_iden: 'ujpah72o0', // Set to the source_user_iden field from the mirrored notification 355 | }; 356 | 357 | await pusher.dismissEphemeral(options); 358 | ``` 359 | 360 | ### PushBullet.stream() 361 | 362 | Returns a new stream listener which will emit events from the stream. 363 | 364 | ```javascript 365 | let stream = pusher.stream(); 366 | ``` 367 | 368 | #### connect() 369 | 370 | Connects to the stream. 371 | 372 | ```javascript 373 | stream.connect(); 374 | ``` 375 | 376 | #### close() 377 | 378 | Disconnects from the stream. 379 | 380 | ```javascript 381 | stream.close(); 382 | ``` 383 | 384 | #### Events 385 | 386 | ##### connect 387 | 388 | Emitted when the stream has connected. 389 | 390 | ```javascript 391 | stream.on('connect', function() { 392 | // stream has connected 393 | }); 394 | ``` 395 | 396 | ##### close 397 | 398 | Emitted when the stream has disconnected. 399 | 400 | ```javascript 401 | stream.on('close', function() { 402 | // stream has disconnected 403 | }); 404 | ``` 405 | 406 | ##### error 407 | 408 | Emitted when there is a connection or streaming error. 409 | 410 | ```javascript 411 | stream.on('error', function(error) { 412 | // stream error 413 | }); 414 | ``` 415 | 416 | ##### message 417 | 418 | Emitted when a message is received from the stream. `message` will be emitted for all messages 419 | but you can listen for specific messages with `nop`, `tickle` and `push`. 420 | 421 | ```javascript 422 | stream.on('message', function(message) { 423 | // message received 424 | }); 425 | ``` 426 | 427 | ##### nop 428 | 429 | Emitted when the keep-alive 'no-operation' message is received. 430 | 431 | ```javascript 432 | stream.on('nop', function() { 433 | // nop message received 434 | }); 435 | ``` 436 | 437 | ##### tickle 438 | 439 | Emitted when the `tickle` message is received. 440 | 441 | ```javascript 442 | stream.on('tickle', function(type) { 443 | // tickle message received 444 | }); 445 | ``` 446 | 447 | ##### push 448 | 449 | Emited when the `push` message is received. 450 | 451 | ```javascript 452 | stream.on('push', function(push) { 453 | // push message received 454 | }); 455 | ``` 456 | 457 | ### PushBullet.enableEncryption(encryptionPassword, userIden) 458 | 459 | Enables End-to-End encryption. 460 | 461 | ```javascript 462 | let response = await pusher.me(); 463 | let user = await response.json(); 464 | 465 | pusher.enableEncryption('YOUR-END-TO-END-PASSWORD', user.iden); 466 | 467 | let stream = pusher.stream(); 468 | 469 | stream.on('message', function(message) { 470 | console.log(message); // message is decrypted automatically 471 | }); 472 | 473 | stream.connect(); 474 | 475 | let options = { 476 | source_user_iden: 'ujpah72o0', 477 | target_device_iden: 'ujpah72o0sjAoRtnM0jc', 478 | conversation_iden: '+1 303 555 1212', 479 | message: 'Hello!' 480 | }; 481 | 482 | await pusher.sendSMS(options); // options are encrypted automatically 483 | ``` 484 | -------------------------------------------------------------------------------- /lib/internal/channels.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Create a new channel. 5 | * 6 | * @param {Object} channelOptions Object of channel options. 7 | * @returns {Promise} 8 | */ 9 | PushBullet.prototype.createChannel = async function createChannel(channelOptions) { 10 | return this.makeRequest('post', PushBullet.CHANNELS_END_POINT, { json : channelOptions }); 11 | }; 12 | 13 | /** 14 | * Get information about a channel. 15 | * 16 | * @param {String} channelTag The tag of the channel to get information about. 17 | * @returns {Promise} 18 | */ 19 | PushBullet.prototype.channelInfo = async function channelInfo(channelTag) { 20 | const options = { 21 | qs : { 22 | tag : channelTag 23 | } 24 | }; 25 | 26 | return this.makeRequest('get', PushBullet.CHANNEL_INFO_END_POINT, options); 27 | }; 28 | -------------------------------------------------------------------------------- /lib/internal/chats.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Get a list of current chats. 5 | * 6 | * @param {Object} options Optional options object. 7 | * @returns {Promise} 8 | */ 9 | PushBullet.prototype.chats = async function chats(options) { 10 | options = options ? options : {}; 11 | 12 | if (options.active === undefined) { 13 | options.active = true; 14 | } 15 | 16 | return this.getList(PushBullet.CHATS_END_POINT, options); 17 | }; 18 | 19 | /** 20 | * Create a new chat. 21 | * 22 | * @param {String} channelTag Email of the person to create the chat with. 23 | * @returns {Promise} 24 | */ 25 | PushBullet.prototype.createChat = async function createChat(email) { 26 | const options = { 27 | json : { 28 | email : email 29 | } 30 | }; 31 | 32 | return this.makeRequest('post', PushBullet.CHATS_END_POINT, options); 33 | }; 34 | 35 | /** 36 | * Mute a chat. 37 | * 38 | * @param {String} chatIden The iden of the chat to mute. 39 | * @returns {Promise} 40 | */ 41 | PushBullet.prototype.muteChat = async function muteChat(chatIden) { 42 | return this.updateChat(chatIden, { muted : true }); 43 | }; 44 | 45 | /** 46 | * Unmute chat. 47 | * 48 | * @param {String} chatIden The iden of the chat to unmute. 49 | * @returns {Promise} 50 | */ 51 | PushBullet.prototype.unmuteChat = async function unmuteChat(chatIden) { 52 | return this.updateChat(chatIden, { muted : false }); 53 | }; 54 | 55 | /** 56 | * Update a chat. 57 | * 58 | * @param {String} chatIden The iden of the chat to ubsubscribe from. 59 | * @param {Object} updates Updates to make to chat. 60 | * @returns {Promise} 61 | */ 62 | PushBullet.prototype.updateChat = async function updateChat(chatIden, updates) { 63 | const options = { 64 | json : updates 65 | }; 66 | 67 | return this.makeRequest('post', PushBullet.CHATS_END_POINT + '/' + chatIden, options); 68 | }; 69 | 70 | /** 71 | * Delete a chat. 72 | * 73 | * @param {String} chatIden The iden of the chat to delete. 74 | * @returns {Promise} 75 | */ 76 | PushBullet.prototype.deleteChat = async function deleteChat(chatIden) { 77 | return this.makeRequest('delete', PushBullet.CHATS_END_POINT + '/' + chatIden, null); 78 | }; 79 | -------------------------------------------------------------------------------- /lib/internal/devices.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Get a list of devices which can be pushed to. 5 | * 6 | * The `options` parameter can use two attributes `cursor` and `limit` 7 | * to control the data returned. 8 | * 9 | * - `active` is used to restrict the results to only active devices. 10 | * - `cursor` is used to select the page if the results have been paginated. 11 | * - `limit` is used to limit the number of objects in the reponse. 12 | * 13 | * @param {Object} options Optional options object. 14 | * @returns {Promise} 15 | */ 16 | PushBullet.prototype.devices = async function devices(options) { 17 | options = options ? options : {}; 18 | 19 | if (options.active === undefined) { 20 | options.active = true; 21 | } 22 | 23 | return this.getList(PushBullet.DEVICES_END_POINT, options); 24 | }; 25 | 26 | /** 27 | * Create a new device. 28 | * 29 | * @param {Object} deviceOptions Object of device options. 30 | * @returns {Promise} 31 | */ 32 | PushBullet.prototype.createDevice = async function createDevice(deviceOptions) { 33 | const options = { 34 | json : deviceOptions 35 | }; 36 | 37 | return this.makeRequest('post', PushBullet.DEVICES_END_POINT, options); 38 | }; 39 | 40 | /** 41 | * Update a device. 42 | * 43 | * @param {String} deviceIden The iden of the device to update. 44 | * @param {Object} deviceOptions Object of device options. 45 | * @returns {Promise} 46 | */ 47 | PushBullet.prototype.updateDevice = async function updateDevice(deviceIden, deviceOptions) { 48 | const options = { 49 | json : deviceOptions 50 | }; 51 | 52 | return this.makeRequest('post', PushBullet.DEVICES_END_POINT + '/' + deviceIden, options); 53 | }; 54 | 55 | /** 56 | * Delete a device. 57 | * 58 | * @param {String} deviceIden Device IDEN of the device to delete. 59 | * @returns {Promise} 60 | */ 61 | PushBullet.prototype.deleteDevice = async function deleteDevice(deviceIden) { 62 | return this.makeRequest('delete', PushBullet.DEVICES_END_POINT + '/' + deviceIden, {}); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/internal/encryption.js: -------------------------------------------------------------------------------- 1 | import forge from 'node-forge'; 2 | 3 | /** 4 | * Encryption module for the PushBullet API. 5 | * 6 | * The encryption key is created from a user-supplied password and passed through PBKDF2. 7 | */ 8 | export default class Encryption { 9 | /** 10 | * @param {String} encryptionPassword End-to-End encryption password set by the user. 11 | * @param {String} userIden The iden of the user (aquired e.g. by the /me request). 12 | */ 13 | constructor(encryptionPassword, userIden) { 14 | const derivedKeyLength = 32; 15 | const iterations = 30000; 16 | const pseudorandomFunction = forge.md.sha256.create(); 17 | const encryptionKey = forge.pkcs5.pbkdf2(encryptionPassword, userIden, iterations, derivedKeyLength, pseudorandomFunction); 18 | 19 | this.encryptionKey = encryptionKey; 20 | } 21 | 22 | /** 23 | * Decodes a base-64 encoded string. 24 | * 25 | * @param {String} input A base-64 encoded message to be decoded. 26 | * @returns {Buffer} Decoded string in a binary form. 27 | */ 28 | atob(input) { 29 | return new Buffer.from(input, 'base64').toString('binary'); 30 | } 31 | 32 | /** 33 | * Encodes a string in base-64. 34 | * 35 | * @param {String} input A binary string to be encoded. 36 | * @returns {Buffer} Base-64 encoded string. 37 | */ 38 | btoa(input) { 39 | return new Buffer.from(input, 'binary').toString('base64'); 40 | } 41 | 42 | /** 43 | * Encrypts a message. 44 | * 45 | * @param {String} message A message to encrypt. 46 | * @returns {String} Encrypted message 47 | */ 48 | encrypt(message) { 49 | const key = this.encryptionKey; 50 | 51 | const initializationVector = forge.random.getBytes(12); 52 | const cipher = forge.cipher.createCipher('AES-GCM', key); 53 | cipher.start({ iv : initializationVector }); 54 | cipher.update(forge.util.createBuffer(forge.util.encodeUtf8(message))); 55 | cipher.finish(); 56 | 57 | const tag = cipher.mode.tag.getBytes(); 58 | const encryptedMessage = cipher.output.getBytes(); 59 | 60 | const result = this.btoa('1' + tag + initializationVector + encryptedMessage); 61 | 62 | return result; 63 | } 64 | 65 | /** 66 | * Decrypts a message. 67 | * 68 | * @param {String} message A message to decrypt. 69 | * @return {String} Decrypted message. 70 | */ 71 | decrypt(message) { 72 | const binaryMessage = this.atob(message); 73 | const key = this.encryptionKey; 74 | const version = binaryMessage.substr(0, 1); 75 | const tag = binaryMessage.substr(1, 16); 76 | const initializationVector = binaryMessage.substr(17, 12); 77 | const encryptedMessage = binaryMessage.substr(29); 78 | 79 | if (version !== '1') { 80 | throw new Error('Invalid cipher version'); 81 | } 82 | 83 | const decipher = forge.cipher.createDecipher('AES-GCM', key); 84 | decipher.start({ 85 | iv : initializationVector, 86 | tag : tag 87 | }); 88 | decipher.update(forge.util.createBuffer(encryptedMessage)); 89 | decipher.finish(); 90 | 91 | const result = decipher.output.toString('utf8'); 92 | return result; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/internal/ephemerals.js: -------------------------------------------------------------------------------- 1 | import clone from 'clone'; 2 | import PushBullet from '../pushbullet.js'; 3 | import util from 'util'; 4 | 5 | /** 6 | * Send an SMS. 7 | * 8 | * The options require source_user_iden, target_device_iden, conversation_iden and message. 9 | * See https://docs.pushbullet.com/#send-sms for details. 10 | * 11 | * @param {Object} smsOptions SMS options. 12 | * @returns {Promise} 13 | */ 14 | PushBullet.prototype.sendSMS = util.deprecate(async function sendSMS(smsOptions) { 15 | const options = clone(smsOptions); 16 | 17 | options.package_name = 'com.pushbullet.android'; 18 | options.type = 'messaging_extension_reply'; 19 | 20 | return this.sendEphemeral(options); 21 | }, 'sendSMS() is deprecated, use createText() instead.'); 22 | 23 | /** 24 | * Send clipboard content. 25 | * 26 | * The options require body, source_user_iden and source_device_iden. 27 | * See https://docs.pushbullet.com/#universal-copypaste for details. 28 | * 29 | * @param {Object} clipOptions Clipboard options. 30 | * @returns {Promise} 31 | */ 32 | PushBullet.prototype.sendClipboard = async function sendClipboard(clipOptions) { 33 | const options = clone(clipOptions); 34 | 35 | options.type = 'clip'; 36 | 37 | return this.sendEphemeral(options); 38 | }; 39 | 40 | /** 41 | * Dismiss an ephemeral. 42 | * 43 | * The options require package_name, notification_id, notification_tag and source_user_iden. 44 | * See https://docs.pushbullet.com/#dismissal-ephemeral for details. 45 | * 46 | * @param {Object} ephemeralOptions Ephemeral dismissal options. 47 | * @returns {Promise} 48 | */ 49 | PushBullet.prototype.dismissEphemeral = async function dismissEphemeral(ephemeralOptions) { 50 | const options = clone(ephemeralOptions); 51 | 52 | options.type = 'dismissal'; 53 | 54 | return this.sendEphemeral(options); 55 | }; 56 | 57 | /** 58 | * Send an ephemeral. 59 | * 60 | * @param {Object} ephemeralOptions Ephemeral options. 61 | * @returns {Promise} 62 | */ 63 | PushBullet.prototype.sendEphemeral = async function sendEphemeral(ephemeralOptions) { 64 | if (this.encryption) { 65 | const encryptedOptions = this.encryption.encrypt(JSON.stringify(ephemeralOptions)); 66 | ephemeralOptions = { 67 | ciphertext : encryptedOptions, 68 | encrypted : true 69 | }; 70 | } 71 | 72 | const options = { 73 | json : { 74 | type : 'push', 75 | push : ephemeralOptions 76 | } 77 | }; 78 | 79 | return this.makeRequest('post', PushBullet.EPHEMERALS_END_POINT, options); 80 | }; 81 | -------------------------------------------------------------------------------- /lib/internal/pushes.js: -------------------------------------------------------------------------------- 1 | import fetch, { FormData } from 'node-fetch'; 2 | import fs from 'fs'; 3 | import mime from 'mime'; 4 | import path from 'path'; 5 | import PushBullet from '../pushbullet.js'; 6 | 7 | /** 8 | * Push a note to a device. 9 | * 10 | * @param {String} deviceParams Push device parameters. See push(). 11 | * @param {String} title Title of note. 12 | * @param {String} body Body of note. 13 | * @returns {Promise} 14 | */ 15 | PushBullet.prototype.note = async function note(deviceParams, title, body) { 16 | const pushParameters = { 17 | type : 'note', 18 | title : title, 19 | body : body 20 | }; 21 | 22 | return this.push(deviceParams, pushParameters); 23 | }; 24 | 25 | /** 26 | * Push a link to a device. 27 | * 28 | * @param {String} deviceParams Push device parameters. See push(). 29 | * @param {String} title Name of address. 30 | * @param {String} url URL to push. 31 | * @param {String} body A message associated with the link. 32 | * @returns {Promise} 33 | */ 34 | PushBullet.prototype.link = async function link(deviceParams, title, url, body) { 35 | return this.push(deviceParams, { 36 | type : 'link', 37 | title : title, 38 | url : url, 39 | body : body 40 | }); 41 | }; 42 | 43 | /** 44 | * Push a file to a device. 45 | * 46 | * @param {String} deviceParams Push device parameters. See push(). 47 | * @param {String} filePath Path to file. 48 | * @param {String} body A message to go with the file. 49 | * @returns {Promise} 50 | */ 51 | PushBullet.prototype.file = async function file(deviceParams, filePath, body) { 52 | const fileName = path.basename(filePath); 53 | const fileType = mime.getType(filePath); 54 | 55 | const uploadRequestResponse = await fetch(PushBullet.UPLOAD_END_POINT, { 56 | method : 'post', 57 | body : JSON.stringify({ 58 | file_name : fileName, 59 | file_type : fileType 60 | }), 61 | headers : { 62 | 'Content-Type' : 'application/json', 63 | 'Access-Token' : this.apiKey 64 | } 65 | }); 66 | 67 | const uploadRequestResponseJson = await uploadRequestResponse.json(); 68 | 69 | const formData = new FormData(); 70 | formData.append('file', fs.createReadStream(filePath)); 71 | 72 | const uploadFileResponse = await fetch(uploadRequestResponseJson.upload_url, { 73 | method : 'post', 74 | body : formData 75 | }); 76 | 77 | if (uploadFileResponse.status !== 204) { 78 | throw new Error('file upload error'); 79 | } 80 | 81 | return this.push(deviceParams, { 82 | type : 'file', 83 | file_name : fileName, 84 | file_type : fileType, 85 | file_url : uploadRequestResponseJson.file_url, 86 | body : body 87 | }); 88 | }; 89 | 90 | /** 91 | * Push 'something' to a device. 92 | * 93 | * @param {Mixed} deviceParams Device parameters. 94 | * @param {Object} bullet Request parameters as described on https://docs.pushbullet.com/#create-push 95 | * @returns {Promise} 96 | */ 97 | PushBullet.prototype.push = async function push(deviceParams, bullet) { 98 | // If deviceParams is a string it could be a contact email or device iden. 99 | if (typeof deviceParams === 'string') { 100 | if (deviceParams.indexOf('@') !== -1) { 101 | bullet.email = deviceParams; 102 | } 103 | else { 104 | bullet.device_iden = deviceParams; 105 | } 106 | } 107 | // If it's a number it's an old style device id. 108 | else if (typeof deviceParams === 'number') { 109 | bullet.device_id = deviceParams; 110 | } 111 | // If it's an object assume it defines a property of 112 | // - device_id 113 | // - device_iden 114 | // - email 115 | // - channel_tag 116 | // - client_iden 117 | // and optionally source_device_iden 118 | else if (typeof deviceParams === 'object') { 119 | for (let param in deviceParams) { 120 | bullet[param] = deviceParams[param]; 121 | } 122 | } 123 | 124 | return this.makeRequest('post', PushBullet.PUSH_END_POINT, { json : bullet }); 125 | }; 126 | 127 | /** 128 | * Get the push history. 129 | * 130 | * The `options` parameter can use three attributes `cursor`, `limit` 131 | * and `modified_after` to control the data returned. 132 | * 133 | * - `active` is used to only select undeleted pushes. 134 | * - `cursor` is used to select the page if the results have been paginated. 135 | * - `limit` is used to limit the number of objects in the reponse. 136 | * - `modified_after` should be a timestamp. 137 | * 138 | * @param {Object} options Optional options object. 139 | * @returns {Promise} 140 | */ 141 | PushBullet.prototype.history = async function history(options) { 142 | options = options ? options : {}; 143 | 144 | if (options.active === undefined) { 145 | options.active = true; 146 | } 147 | 148 | if (options.modified_after === undefined) { 149 | options.modified_after = 0; 150 | } 151 | 152 | return this.getList(PushBullet.PUSH_END_POINT, options); 153 | }; 154 | 155 | /** 156 | * Dismiss a push. 157 | * 158 | * @param {String} pushIden Push IDEN of the push to update. 159 | * @param {Object} updates Updates to make to push. 160 | * @returns {Promise} 161 | */ 162 | PushBullet.prototype.dismissPush = async function dismissPush(pushIden) { 163 | return this.updatePush(pushIden, { dismissed : true }); 164 | }; 165 | 166 | /** 167 | * Update a push. 168 | * 169 | * @param {String} pushIden Push IDEN of the push to update. 170 | * @param {Object} updates Updates to make to push. 171 | * @returns {Promise} 172 | */ 173 | PushBullet.prototype.updatePush = async function updatePush(pushIden, updates) { 174 | updates = updates ? updates : {}; 175 | 176 | const options = { 177 | json : updates 178 | }; 179 | 180 | return this.makeRequest('post', PushBullet.PUSH_END_POINT + '/' + pushIden, options); 181 | }; 182 | 183 | /** 184 | * Delete a push. 185 | * 186 | * @param {String} pushIden Push IDEN of the push to delete. 187 | * @returns {Promise} 188 | */ 189 | PushBullet.prototype.deletePush = async function deletePush(pushIden) { 190 | return this.makeRequest('delete', PushBullet.PUSH_END_POINT + '/' + pushIden, null); 191 | }; 192 | 193 | /** 194 | * Delete all pushes belonging to the current user. 195 | * 196 | * @returns {Promise} 197 | */ 198 | PushBullet.prototype.deleteAllPushes = async function deleteAllPushes() { 199 | return this.makeRequest('delete', PushBullet.PUSH_END_POINT, {}); 200 | }; 201 | -------------------------------------------------------------------------------- /lib/internal/stream.js: -------------------------------------------------------------------------------- 1 | import events from 'events'; 2 | import WebSocket from 'ws'; 3 | 4 | const STREAM_BASE = 'wss://stream.pushbullet.com/websocket'; 5 | 6 | /** 7 | * Event emitter for the Pushbullet streaming API. 8 | */ 9 | export default class Stream extends events.EventEmitter { 10 | /** 11 | * 12 | * @param {String} apiKey PushBullet API key. 13 | * @param {Encryption} encryption Encryption instance. 14 | */ 15 | constructor(apiKey, encryption) { 16 | super(); 17 | 18 | this.apiKey = apiKey; 19 | this.encryption = encryption; 20 | } 21 | 22 | /** 23 | * Connect to the stream. 24 | */ 25 | connect() { 26 | this.client = new WebSocket(STREAM_BASE + '/' + this.apiKey); 27 | 28 | this.client.on('open', () => { 29 | this.heartbeat(); 30 | this.emit('connect'); 31 | }); 32 | 33 | this.client.on('close', () => { 34 | clearTimeout(this.pingTimeout); 35 | this.emit('close'); 36 | }); 37 | 38 | this.client.on('error', (error) => { 39 | this.emit('error', error); 40 | }); 41 | 42 | this.client.on('message', (message) => { 43 | const data = JSON.parse(message); 44 | if (this.encryption && data.type === 'push' && data.push.encrypted) { 45 | const decipheredMessage = this.encryption.decrypt(data.push.ciphertext); 46 | data.push = JSON.parse(decipheredMessage); 47 | } 48 | this.emit('message', data); 49 | if (data.type === 'nop') { 50 | this.heartbeat(); 51 | this.emit('nop'); 52 | } 53 | else if (data.type === 'tickle') { 54 | this.emit('tickle', data.subtype); 55 | } 56 | else if (data.type === 'push') { 57 | this.emit('push', data.push); 58 | } 59 | }); 60 | } 61 | 62 | /** 63 | * Disconnect from the stream. 64 | */ 65 | close() { 66 | this.client.close(); 67 | } 68 | 69 | /** 70 | * Reconnect to stream if a 'nop' message hasn't been seen for 30 seconds. 71 | */ 72 | heartbeat() { 73 | clearTimeout(this.pingTimeout); 74 | 75 | // Use `WebSocket#terminate()` and not `WebSocket#close()`. Delay is 76 | // equal to the interval at which the server sends 'nop' messages plus a 77 | // conservative assumption of the latency. 78 | this.pingTimeout = setTimeout(() => { 79 | this.client.terminate(); 80 | this.connect(); 81 | }, 30000 + 1000); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/internal/subscriptions.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Get a list of current subscriptions. 5 | * 6 | * @param {Object} options Optional options object. 7 | * @returns {Promise} 8 | */ 9 | PushBullet.prototype.subscriptions = async function subscriptions(options) { 10 | options = options ? options : {}; 11 | 12 | if (options.active === undefined) { 13 | options.active = true; 14 | } 15 | 16 | return this.getList(PushBullet.SUBS_END_POINT, options); 17 | }; 18 | 19 | /** 20 | * Subscribe to a channel. 21 | * 22 | * @param {String} channelTag The tag of the channel to subscribe to. 23 | * @returns {Promise} 24 | */ 25 | PushBullet.prototype.subscribe = async function subscribe(channelTag) { 26 | const options = { 27 | json : { 28 | channel_tag : channelTag 29 | } 30 | }; 31 | 32 | return this.makeRequest('post', PushBullet.SUBS_END_POINT, options); 33 | }; 34 | 35 | /** 36 | * Unsubscribe from a channel. 37 | * 38 | * @param {String} subscriptionIden The iden of the subscription to ubsubscribe from. 39 | * @returns {Promise} 40 | */ 41 | PushBullet.prototype.unsubscribe = async function unsubscribe(subscriptionIden) { 42 | return this.makeRequest('delete', PushBullet.SUBS_END_POINT + '/' + subscriptionIden, null); 43 | }; 44 | 45 | /** 46 | * Mute a subscription. 47 | * 48 | * @param {String} subscriptionIden The iden of the subscription to mute. 49 | * @returns {Promise} 50 | */ 51 | PushBullet.prototype.muteSubscription = async function muteSubscription(subscriptionIden) { 52 | return this.updateSubscription(subscriptionIden, { muted : true }); 53 | }; 54 | 55 | /** 56 | * Unmute subscription. 57 | * 58 | * @param {String} subscriptionIden The iden of the subscription to unmute. 59 | * @returns {Promise} 60 | */ 61 | PushBullet.prototype.unmuteSubscription = async function unmuteSubscription(subscriptionIden) { 62 | return this.updateSubscription(subscriptionIden, { muted : false }); 63 | }; 64 | 65 | /** 66 | * Update a subscription. 67 | * 68 | * @param {String} subscriptionIden The iden of the subscription to ubsubscribe from. 69 | * @param {Object} updates Updates to make to subscription. 70 | * @returns {Promise} 71 | */ 72 | PushBullet.prototype.updateSubscription = async function updateSubscription(subscriptionIden, updates) { 73 | const options = { 74 | json : updates 75 | }; 76 | 77 | return this.makeRequest('post', PushBullet.SUBS_END_POINT + '/' + subscriptionIden, options); 78 | }; 79 | -------------------------------------------------------------------------------- /lib/internal/texts.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Create a new text. 5 | * 6 | * See https://docs.pushbullet.com/#text for additional options that can be set. 7 | * 8 | * @param {String} deviceIden Device IDEN of the device which can send SMS messages. 9 | * @param {Array} addresses String or array of strings of recipient phone numbers. 10 | * @param {String} message Message text to be sent. 11 | * @param {Object} textOptions Additional text options. 12 | * @returns {Promise} 13 | */ 14 | PushBullet.prototype.createText = async function createText(deviceIden, addresses, message, textOptions) { 15 | const options = { 16 | data : { 17 | target_device_iden : deviceIden, 18 | addresses : Array.isArray(addresses) ? addresses : [ addresses ], 19 | message : message 20 | } 21 | }; 22 | 23 | if (textOptions.guid) { 24 | options.data.guid = textOptions.guid; 25 | } 26 | if (textOptions.status) { 27 | options.data.status = textOptions.status; 28 | } 29 | if (textOptions.file_type) { 30 | options.data.file_type = textOptions.file_type; 31 | } 32 | if (textOptions.file_url) { 33 | options.file_url = textOptions.file_url; 34 | } 35 | if (textOptions.skip_file_delete) { 36 | options.skip_file_delete = textOptions.skip_file_delete; 37 | } 38 | 39 | return this.makeRequest('post', PushBullet.TEXTS_END_POINT, { json : options }); 40 | }; 41 | 42 | /** 43 | * Update text. 44 | * 45 | * See https://docs.pushbullet.com/#text for valid attributes. 46 | * 47 | * @param {String} textIden The iden of the text to update. 48 | * @param {Object} textOptions Text attributes to apply updates to. 49 | * @returns {Promise} 50 | */ 51 | PushBullet.prototype.updateText = async function updateText(textIden, textOptions) { 52 | return this.makeRequest('post', PushBullet.TEXTS_END_POINT + '/' + textIden, { json : textOptions }); 53 | }; 54 | 55 | /** 56 | * Delete a text. 57 | * 58 | * @param {String} textIden The iden of the text to update. 59 | * @returns {Promise} 60 | */ 61 | PushBullet.prototype.deleteText = async function deleteText(textIden) { 62 | return this.makeRequest('delete', PushBullet.TEXTS_END_POINT + '/' + textIden, {}); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/internal/users.js: -------------------------------------------------------------------------------- 1 | import PushBullet from '../pushbullet.js'; 2 | 3 | /** 4 | * Get information for the current user. 5 | * 6 | * @returns {Promise} 7 | */ 8 | PushBullet.prototype.me = async function me() { 9 | return this.makeRequest('get', PushBullet.USERS_END_POINT + '/me', null); 10 | }; 11 | -------------------------------------------------------------------------------- /lib/pushbullet.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import Encryption from './internal/encryption.js'; 3 | import Stream from './internal/stream.js'; 4 | 5 | /** 6 | * PushBullet API abstraction module. 7 | * 8 | * @param {String} apiKey PushBullet API key. 9 | */ 10 | export default function PushBullet(apiKey) { 11 | if ( ! apiKey) { 12 | throw new Error('API Key is required'); 13 | } 14 | 15 | this.apiKey = apiKey; 16 | } 17 | 18 | PushBullet.API_BASE = 'https://api.pushbullet.com/v2'; 19 | PushBullet.CHANNEL_INFO_END_POINT = PushBullet.API_BASE + '/channel-info'; 20 | PushBullet.CHANNELS_END_POINT = PushBullet.API_BASE + '/channels'; 21 | PushBullet.CHATS_END_POINT = PushBullet.API_BASE + '/chats'; 22 | PushBullet.DEVICES_END_POINT = PushBullet.API_BASE + '/devices'; 23 | PushBullet.EPHEMERALS_END_POINT = PushBullet.API_BASE + '/ephemerals'; 24 | PushBullet.PUSH_END_POINT = PushBullet.API_BASE + '/pushes'; 25 | PushBullet.SUBS_END_POINT = PushBullet.API_BASE + '/subscriptions'; 26 | PushBullet.TEXTS_END_POINT = PushBullet.API_BASE + '/texts'; 27 | PushBullet.UPLOAD_END_POINT = PushBullet.API_BASE + '/upload-request'; 28 | PushBullet.USERS_END_POINT = PushBullet.API_BASE + '/users'; 29 | 30 | /** 31 | * Enables End-to-End encryption. 32 | * 33 | * @param {String} encryptionPassword End-to-End encryption password set by the user. 34 | * @param {String} userIden The iden of the user (aquired e.g. by the /me request). 35 | */ 36 | PushBullet.prototype.enableEncryption = function enableEncryption(encryptionPassword, userIden) { 37 | this.encryption = new Encryption(encryptionPassword, userIden); 38 | }; 39 | 40 | /** 41 | * Return a new stream listener. 42 | * 43 | * @return {Stream} Stream listener. 44 | */ 45 | PushBullet.prototype.stream = function stream() { 46 | return new Stream(this.apiKey, this.encryption); 47 | }; 48 | 49 | /** 50 | * Performs a GET request to an end point. 51 | * 52 | * Options passed are added to the end point as a query string. 53 | * 54 | * @param {String} endPoint URL to send GET request to. 55 | * @param {Object} options Key/value options used as query string parameters. 56 | * @returns {Promise} 57 | */ 58 | PushBullet.prototype.getList = async function getList(endPoint, options) { 59 | options = options ? options : {}; 60 | 61 | const parameters = {}; 62 | 63 | const optionKeys = Object.keys(options); 64 | 65 | if (optionKeys.length > 0) { 66 | parameters.qs = {}; 67 | 68 | optionKeys.forEach(function(key) { 69 | parameters.qs[key] = options[key]; 70 | }); 71 | } 72 | 73 | return this.makeRequest('get', endPoint, parameters); 74 | }; 75 | 76 | /** 77 | * Makes the request to the PushBullet API. 78 | * 79 | * @param {String} verb The http verb that is being made 80 | * @param {String} endPoint The api endpoint 81 | * @param {Object} options The options to be sent with the request 82 | * @returns {Promise} 83 | */ 84 | PushBullet.prototype.makeRequest = async function makeRequest(verb, endPoint, options) { 85 | const fetchInit = { 86 | method : verb, 87 | headers : { 88 | 'Access-Token' : this.apiKey 89 | } 90 | }; 91 | 92 | if (options && options.qs) { 93 | const url = new URL(endPoint); 94 | Object.keys(options.qs).forEach(function(key) { 95 | url.searchParams.append(key, options.qs[key]); 96 | }); 97 | endPoint = url.toString(); 98 | } 99 | 100 | if (options && options.json) { 101 | fetchInit.body = JSON.stringify(options.json); 102 | fetchInit.headers['Content-Type'] = 'application/json'; 103 | } 104 | 105 | return fetch(endPoint, fetchInit); 106 | }; 107 | 108 | import './internal/channels.js'; 109 | import './internal/chats.js'; 110 | import './internal/devices.js'; 111 | import './internal/ephemerals.js'; 112 | import './internal/pushes.js'; 113 | import './internal/subscriptions.js'; 114 | import './internal/texts.js'; 115 | import './internal/users.js'; 116 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pushbullet", 3 | "version": "3.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "pushbullet", 9 | "version": "3.0.0", 10 | "license": "BSD", 11 | "dependencies": { 12 | "clone": "^2.1.2", 13 | "mime": "^3.0.0", 14 | "node-fetch": "^3.2.0", 15 | "node-forge": "^1.2.1", 16 | "ws": "^8.4.2" 17 | }, 18 | "devDependencies": { 19 | "chai": "^4.3.6", 20 | "eslint": "^8.8.0", 21 | "mocha": "^9.2.0", 22 | "nock": "^13.2.3" 23 | } 24 | }, 25 | "node_modules/@eslint/eslintrc": { 26 | "version": "1.0.5", 27 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", 28 | "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", 29 | "dev": true, 30 | "dependencies": { 31 | "ajv": "^6.12.4", 32 | "debug": "^4.3.2", 33 | "espree": "^9.2.0", 34 | "globals": "^13.9.0", 35 | "ignore": "^4.0.6", 36 | "import-fresh": "^3.2.1", 37 | "js-yaml": "^4.1.0", 38 | "minimatch": "^3.0.4", 39 | "strip-json-comments": "^3.1.1" 40 | }, 41 | "engines": { 42 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 43 | } 44 | }, 45 | "node_modules/@eslint/eslintrc/node_modules/ignore": { 46 | "version": "4.0.6", 47 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 48 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 49 | "dev": true, 50 | "engines": { 51 | "node": ">= 4" 52 | } 53 | }, 54 | "node_modules/@humanwhocodes/config-array": { 55 | "version": "0.9.3", 56 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", 57 | "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", 58 | "dev": true, 59 | "dependencies": { 60 | "@humanwhocodes/object-schema": "^1.2.1", 61 | "debug": "^4.1.1", 62 | "minimatch": "^3.0.4" 63 | }, 64 | "engines": { 65 | "node": ">=10.10.0" 66 | } 67 | }, 68 | "node_modules/@humanwhocodes/object-schema": { 69 | "version": "1.2.1", 70 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 71 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 72 | "dev": true 73 | }, 74 | "node_modules/@ungap/promise-all-settled": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 77 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 78 | "dev": true 79 | }, 80 | "node_modules/acorn": { 81 | "version": "8.7.0", 82 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", 83 | "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", 84 | "dev": true, 85 | "bin": { 86 | "acorn": "bin/acorn" 87 | }, 88 | "engines": { 89 | "node": ">=0.4.0" 90 | } 91 | }, 92 | "node_modules/acorn-jsx": { 93 | "version": "5.3.2", 94 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 95 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 96 | "dev": true, 97 | "peerDependencies": { 98 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 99 | } 100 | }, 101 | "node_modules/ajv": { 102 | "version": "6.12.6", 103 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 104 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 105 | "dev": true, 106 | "dependencies": { 107 | "fast-deep-equal": "^3.1.1", 108 | "fast-json-stable-stringify": "^2.0.0", 109 | "json-schema-traverse": "^0.4.1", 110 | "uri-js": "^4.2.2" 111 | }, 112 | "funding": { 113 | "type": "github", 114 | "url": "https://github.com/sponsors/epoberezkin" 115 | } 116 | }, 117 | "node_modules/ansi-colors": { 118 | "version": "4.1.1", 119 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 120 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 121 | "dev": true, 122 | "engines": { 123 | "node": ">=6" 124 | } 125 | }, 126 | "node_modules/ansi-regex": { 127 | "version": "5.0.1", 128 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 129 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 130 | "dev": true, 131 | "engines": { 132 | "node": ">=8" 133 | } 134 | }, 135 | "node_modules/ansi-styles": { 136 | "version": "4.3.0", 137 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 138 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 139 | "dev": true, 140 | "dependencies": { 141 | "color-convert": "^2.0.1" 142 | }, 143 | "engines": { 144 | "node": ">=8" 145 | }, 146 | "funding": { 147 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 148 | } 149 | }, 150 | "node_modules/anymatch": { 151 | "version": "3.1.2", 152 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 153 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 154 | "dev": true, 155 | "dependencies": { 156 | "normalize-path": "^3.0.0", 157 | "picomatch": "^2.0.4" 158 | }, 159 | "engines": { 160 | "node": ">= 8" 161 | } 162 | }, 163 | "node_modules/argparse": { 164 | "version": "2.0.1", 165 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 166 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 167 | "dev": true 168 | }, 169 | "node_modules/assertion-error": { 170 | "version": "1.1.0", 171 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 172 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 173 | "dev": true, 174 | "engines": { 175 | "node": "*" 176 | } 177 | }, 178 | "node_modules/balanced-match": { 179 | "version": "1.0.0", 180 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 181 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 182 | "dev": true 183 | }, 184 | "node_modules/binary-extensions": { 185 | "version": "2.2.0", 186 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 187 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 188 | "dev": true, 189 | "engines": { 190 | "node": ">=8" 191 | } 192 | }, 193 | "node_modules/brace-expansion": { 194 | "version": "1.1.11", 195 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 196 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 197 | "dev": true, 198 | "dependencies": { 199 | "balanced-match": "^1.0.0", 200 | "concat-map": "0.0.1" 201 | } 202 | }, 203 | "node_modules/braces": { 204 | "version": "3.0.2", 205 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 206 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 207 | "dev": true, 208 | "dependencies": { 209 | "fill-range": "^7.0.1" 210 | }, 211 | "engines": { 212 | "node": ">=8" 213 | } 214 | }, 215 | "node_modules/browser-stdout": { 216 | "version": "1.3.1", 217 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 218 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 219 | "dev": true 220 | }, 221 | "node_modules/callsites": { 222 | "version": "3.1.0", 223 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 224 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 225 | "dev": true, 226 | "engines": { 227 | "node": ">=6" 228 | } 229 | }, 230 | "node_modules/camelcase": { 231 | "version": "6.3.0", 232 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 233 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 234 | "dev": true, 235 | "engines": { 236 | "node": ">=10" 237 | }, 238 | "funding": { 239 | "url": "https://github.com/sponsors/sindresorhus" 240 | } 241 | }, 242 | "node_modules/chai": { 243 | "version": "4.3.6", 244 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", 245 | "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", 246 | "dev": true, 247 | "dependencies": { 248 | "assertion-error": "^1.1.0", 249 | "check-error": "^1.0.2", 250 | "deep-eql": "^3.0.1", 251 | "get-func-name": "^2.0.0", 252 | "loupe": "^2.3.1", 253 | "pathval": "^1.1.1", 254 | "type-detect": "^4.0.5" 255 | }, 256 | "engines": { 257 | "node": ">=4" 258 | } 259 | }, 260 | "node_modules/chalk": { 261 | "version": "4.1.2", 262 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 263 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 264 | "dev": true, 265 | "dependencies": { 266 | "ansi-styles": "^4.1.0", 267 | "supports-color": "^7.1.0" 268 | }, 269 | "engines": { 270 | "node": ">=10" 271 | }, 272 | "funding": { 273 | "url": "https://github.com/chalk/chalk?sponsor=1" 274 | } 275 | }, 276 | "node_modules/check-error": { 277 | "version": "1.0.2", 278 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 279 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 280 | "dev": true, 281 | "engines": { 282 | "node": "*" 283 | } 284 | }, 285 | "node_modules/chokidar": { 286 | "version": "3.5.3", 287 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 288 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 289 | "dev": true, 290 | "funding": [ 291 | { 292 | "type": "individual", 293 | "url": "https://paulmillr.com/funding/" 294 | } 295 | ], 296 | "dependencies": { 297 | "anymatch": "~3.1.2", 298 | "braces": "~3.0.2", 299 | "glob-parent": "~5.1.2", 300 | "is-binary-path": "~2.1.0", 301 | "is-glob": "~4.0.1", 302 | "normalize-path": "~3.0.0", 303 | "readdirp": "~3.6.0" 304 | }, 305 | "engines": { 306 | "node": ">= 8.10.0" 307 | }, 308 | "optionalDependencies": { 309 | "fsevents": "~2.3.2" 310 | } 311 | }, 312 | "node_modules/chokidar/node_modules/glob-parent": { 313 | "version": "5.1.2", 314 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 315 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 316 | "dev": true, 317 | "dependencies": { 318 | "is-glob": "^4.0.1" 319 | }, 320 | "engines": { 321 | "node": ">= 6" 322 | } 323 | }, 324 | "node_modules/cliui": { 325 | "version": "7.0.4", 326 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 327 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 328 | "dev": true, 329 | "dependencies": { 330 | "string-width": "^4.2.0", 331 | "strip-ansi": "^6.0.0", 332 | "wrap-ansi": "^7.0.0" 333 | } 334 | }, 335 | "node_modules/clone": { 336 | "version": "2.1.2", 337 | "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", 338 | "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", 339 | "engines": { 340 | "node": ">=0.8" 341 | } 342 | }, 343 | "node_modules/color-convert": { 344 | "version": "2.0.1", 345 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 346 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 347 | "dev": true, 348 | "dependencies": { 349 | "color-name": "~1.1.4" 350 | }, 351 | "engines": { 352 | "node": ">=7.0.0" 353 | } 354 | }, 355 | "node_modules/color-name": { 356 | "version": "1.1.4", 357 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 358 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 359 | "dev": true 360 | }, 361 | "node_modules/concat-map": { 362 | "version": "0.0.1", 363 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 364 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 365 | "dev": true 366 | }, 367 | "node_modules/cross-spawn": { 368 | "version": "7.0.3", 369 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 370 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 371 | "dev": true, 372 | "dependencies": { 373 | "path-key": "^3.1.0", 374 | "shebang-command": "^2.0.0", 375 | "which": "^2.0.1" 376 | }, 377 | "engines": { 378 | "node": ">= 8" 379 | } 380 | }, 381 | "node_modules/data-uri-to-buffer": { 382 | "version": "4.0.0", 383 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", 384 | "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", 385 | "engines": { 386 | "node": ">= 12" 387 | } 388 | }, 389 | "node_modules/debug": { 390 | "version": "4.3.3", 391 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 392 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 393 | "dev": true, 394 | "dependencies": { 395 | "ms": "2.1.2" 396 | }, 397 | "engines": { 398 | "node": ">=6.0" 399 | }, 400 | "peerDependenciesMeta": { 401 | "supports-color": { 402 | "optional": true 403 | } 404 | } 405 | }, 406 | "node_modules/debug/node_modules/ms": { 407 | "version": "2.1.2", 408 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 409 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 410 | "dev": true 411 | }, 412 | "node_modules/decamelize": { 413 | "version": "4.0.0", 414 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 415 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 416 | "dev": true, 417 | "engines": { 418 | "node": ">=10" 419 | }, 420 | "funding": { 421 | "url": "https://github.com/sponsors/sindresorhus" 422 | } 423 | }, 424 | "node_modules/deep-eql": { 425 | "version": "3.0.1", 426 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 427 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 428 | "dev": true, 429 | "dependencies": { 430 | "type-detect": "^4.0.0" 431 | }, 432 | "engines": { 433 | "node": ">=0.12" 434 | } 435 | }, 436 | "node_modules/deep-is": { 437 | "version": "0.1.4", 438 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 439 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 440 | "dev": true 441 | }, 442 | "node_modules/diff": { 443 | "version": "5.0.0", 444 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 445 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 446 | "dev": true, 447 | "engines": { 448 | "node": ">=0.3.1" 449 | } 450 | }, 451 | "node_modules/doctrine": { 452 | "version": "3.0.0", 453 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 454 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 455 | "dev": true, 456 | "dependencies": { 457 | "esutils": "^2.0.2" 458 | }, 459 | "engines": { 460 | "node": ">=6.0.0" 461 | } 462 | }, 463 | "node_modules/emoji-regex": { 464 | "version": "8.0.0", 465 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 466 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 467 | "dev": true 468 | }, 469 | "node_modules/escalade": { 470 | "version": "3.1.1", 471 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 472 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 473 | "dev": true, 474 | "engines": { 475 | "node": ">=6" 476 | } 477 | }, 478 | "node_modules/escape-string-regexp": { 479 | "version": "4.0.0", 480 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 481 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 482 | "dev": true, 483 | "engines": { 484 | "node": ">=10" 485 | }, 486 | "funding": { 487 | "url": "https://github.com/sponsors/sindresorhus" 488 | } 489 | }, 490 | "node_modules/eslint": { 491 | "version": "8.8.0", 492 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", 493 | "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", 494 | "dev": true, 495 | "dependencies": { 496 | "@eslint/eslintrc": "^1.0.5", 497 | "@humanwhocodes/config-array": "^0.9.2", 498 | "ajv": "^6.10.0", 499 | "chalk": "^4.0.0", 500 | "cross-spawn": "^7.0.2", 501 | "debug": "^4.3.2", 502 | "doctrine": "^3.0.0", 503 | "escape-string-regexp": "^4.0.0", 504 | "eslint-scope": "^7.1.0", 505 | "eslint-utils": "^3.0.0", 506 | "eslint-visitor-keys": "^3.2.0", 507 | "espree": "^9.3.0", 508 | "esquery": "^1.4.0", 509 | "esutils": "^2.0.2", 510 | "fast-deep-equal": "^3.1.3", 511 | "file-entry-cache": "^6.0.1", 512 | "functional-red-black-tree": "^1.0.1", 513 | "glob-parent": "^6.0.1", 514 | "globals": "^13.6.0", 515 | "ignore": "^5.2.0", 516 | "import-fresh": "^3.0.0", 517 | "imurmurhash": "^0.1.4", 518 | "is-glob": "^4.0.0", 519 | "js-yaml": "^4.1.0", 520 | "json-stable-stringify-without-jsonify": "^1.0.1", 521 | "levn": "^0.4.1", 522 | "lodash.merge": "^4.6.2", 523 | "minimatch": "^3.0.4", 524 | "natural-compare": "^1.4.0", 525 | "optionator": "^0.9.1", 526 | "regexpp": "^3.2.0", 527 | "strip-ansi": "^6.0.1", 528 | "strip-json-comments": "^3.1.0", 529 | "text-table": "^0.2.0", 530 | "v8-compile-cache": "^2.0.3" 531 | }, 532 | "bin": { 533 | "eslint": "bin/eslint.js" 534 | }, 535 | "engines": { 536 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 537 | }, 538 | "funding": { 539 | "url": "https://opencollective.com/eslint" 540 | } 541 | }, 542 | "node_modules/eslint-scope": { 543 | "version": "7.1.0", 544 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", 545 | "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", 546 | "dev": true, 547 | "dependencies": { 548 | "esrecurse": "^4.3.0", 549 | "estraverse": "^5.2.0" 550 | }, 551 | "engines": { 552 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 553 | } 554 | }, 555 | "node_modules/eslint-utils": { 556 | "version": "3.0.0", 557 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 558 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 559 | "dev": true, 560 | "dependencies": { 561 | "eslint-visitor-keys": "^2.0.0" 562 | }, 563 | "engines": { 564 | "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" 565 | }, 566 | "funding": { 567 | "url": "https://github.com/sponsors/mysticatea" 568 | }, 569 | "peerDependencies": { 570 | "eslint": ">=5" 571 | } 572 | }, 573 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { 574 | "version": "2.1.0", 575 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 576 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 577 | "dev": true, 578 | "engines": { 579 | "node": ">=10" 580 | } 581 | }, 582 | "node_modules/eslint-visitor-keys": { 583 | "version": "3.2.0", 584 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", 585 | "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", 586 | "dev": true, 587 | "engines": { 588 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 589 | } 590 | }, 591 | "node_modules/espree": { 592 | "version": "9.3.0", 593 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", 594 | "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", 595 | "dev": true, 596 | "dependencies": { 597 | "acorn": "^8.7.0", 598 | "acorn-jsx": "^5.3.1", 599 | "eslint-visitor-keys": "^3.1.0" 600 | }, 601 | "engines": { 602 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 603 | } 604 | }, 605 | "node_modules/esquery": { 606 | "version": "1.4.0", 607 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 608 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 609 | "dev": true, 610 | "dependencies": { 611 | "estraverse": "^5.1.0" 612 | }, 613 | "engines": { 614 | "node": ">=0.10" 615 | } 616 | }, 617 | "node_modules/esrecurse": { 618 | "version": "4.3.0", 619 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 620 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 621 | "dev": true, 622 | "dependencies": { 623 | "estraverse": "^5.2.0" 624 | }, 625 | "engines": { 626 | "node": ">=4.0" 627 | } 628 | }, 629 | "node_modules/estraverse": { 630 | "version": "5.3.0", 631 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 632 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 633 | "dev": true, 634 | "engines": { 635 | "node": ">=4.0" 636 | } 637 | }, 638 | "node_modules/esutils": { 639 | "version": "2.0.3", 640 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 641 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 642 | "dev": true, 643 | "engines": { 644 | "node": ">=0.10.0" 645 | } 646 | }, 647 | "node_modules/fast-deep-equal": { 648 | "version": "3.1.3", 649 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 650 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 651 | "dev": true 652 | }, 653 | "node_modules/fast-json-stable-stringify": { 654 | "version": "2.1.0", 655 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 656 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 657 | "dev": true 658 | }, 659 | "node_modules/fast-levenshtein": { 660 | "version": "2.0.6", 661 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 662 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 663 | "dev": true 664 | }, 665 | "node_modules/fetch-blob": { 666 | "version": "3.1.4", 667 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", 668 | "integrity": "sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA==", 669 | "funding": [ 670 | { 671 | "type": "github", 672 | "url": "https://github.com/sponsors/jimmywarting" 673 | }, 674 | { 675 | "type": "paypal", 676 | "url": "https://paypal.me/jimmywarting" 677 | } 678 | ], 679 | "dependencies": { 680 | "node-domexception": "^1.0.0", 681 | "web-streams-polyfill": "^3.0.3" 682 | }, 683 | "engines": { 684 | "node": "^12.20 || >= 14.13" 685 | } 686 | }, 687 | "node_modules/file-entry-cache": { 688 | "version": "6.0.1", 689 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 690 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 691 | "dev": true, 692 | "dependencies": { 693 | "flat-cache": "^3.0.4" 694 | }, 695 | "engines": { 696 | "node": "^10.12.0 || >=12.0.0" 697 | } 698 | }, 699 | "node_modules/fill-range": { 700 | "version": "7.0.1", 701 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 702 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 703 | "dev": true, 704 | "dependencies": { 705 | "to-regex-range": "^5.0.1" 706 | }, 707 | "engines": { 708 | "node": ">=8" 709 | } 710 | }, 711 | "node_modules/find-up": { 712 | "version": "5.0.0", 713 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 714 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 715 | "dev": true, 716 | "dependencies": { 717 | "locate-path": "^6.0.0", 718 | "path-exists": "^4.0.0" 719 | }, 720 | "engines": { 721 | "node": ">=10" 722 | }, 723 | "funding": { 724 | "url": "https://github.com/sponsors/sindresorhus" 725 | } 726 | }, 727 | "node_modules/flat": { 728 | "version": "5.0.2", 729 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 730 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 731 | "dev": true, 732 | "bin": { 733 | "flat": "cli.js" 734 | } 735 | }, 736 | "node_modules/flat-cache": { 737 | "version": "3.0.4", 738 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 739 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 740 | "dev": true, 741 | "dependencies": { 742 | "flatted": "^3.1.0", 743 | "rimraf": "^3.0.2" 744 | }, 745 | "engines": { 746 | "node": "^10.12.0 || >=12.0.0" 747 | } 748 | }, 749 | "node_modules/flatted": { 750 | "version": "3.2.5", 751 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", 752 | "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", 753 | "dev": true 754 | }, 755 | "node_modules/formdata-polyfill": { 756 | "version": "4.0.10", 757 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 758 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 759 | "dependencies": { 760 | "fetch-blob": "^3.1.2" 761 | }, 762 | "engines": { 763 | "node": ">=12.20.0" 764 | } 765 | }, 766 | "node_modules/fs.realpath": { 767 | "version": "1.0.0", 768 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 769 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 770 | "dev": true 771 | }, 772 | "node_modules/fsevents": { 773 | "version": "2.3.2", 774 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 775 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 776 | "dev": true, 777 | "hasInstallScript": true, 778 | "optional": true, 779 | "os": [ 780 | "darwin" 781 | ], 782 | "engines": { 783 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 784 | } 785 | }, 786 | "node_modules/functional-red-black-tree": { 787 | "version": "1.0.1", 788 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 789 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 790 | "dev": true 791 | }, 792 | "node_modules/get-caller-file": { 793 | "version": "2.0.5", 794 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 795 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 796 | "dev": true, 797 | "engines": { 798 | "node": "6.* || 8.* || >= 10.*" 799 | } 800 | }, 801 | "node_modules/get-func-name": { 802 | "version": "2.0.0", 803 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 804 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 805 | "dev": true, 806 | "engines": { 807 | "node": "*" 808 | } 809 | }, 810 | "node_modules/glob": { 811 | "version": "7.2.0", 812 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 813 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 814 | "dev": true, 815 | "dependencies": { 816 | "fs.realpath": "^1.0.0", 817 | "inflight": "^1.0.4", 818 | "inherits": "2", 819 | "minimatch": "^3.0.4", 820 | "once": "^1.3.0", 821 | "path-is-absolute": "^1.0.0" 822 | }, 823 | "engines": { 824 | "node": "*" 825 | }, 826 | "funding": { 827 | "url": "https://github.com/sponsors/isaacs" 828 | } 829 | }, 830 | "node_modules/glob-parent": { 831 | "version": "6.0.2", 832 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 833 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 834 | "dev": true, 835 | "dependencies": { 836 | "is-glob": "^4.0.3" 837 | }, 838 | "engines": { 839 | "node": ">=10.13.0" 840 | } 841 | }, 842 | "node_modules/globals": { 843 | "version": "13.12.0", 844 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", 845 | "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", 846 | "dev": true, 847 | "dependencies": { 848 | "type-fest": "^0.20.2" 849 | }, 850 | "engines": { 851 | "node": ">=8" 852 | }, 853 | "funding": { 854 | "url": "https://github.com/sponsors/sindresorhus" 855 | } 856 | }, 857 | "node_modules/growl": { 858 | "version": "1.10.5", 859 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 860 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 861 | "dev": true, 862 | "engines": { 863 | "node": ">=4.x" 864 | } 865 | }, 866 | "node_modules/has-flag": { 867 | "version": "4.0.0", 868 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 869 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 870 | "dev": true, 871 | "engines": { 872 | "node": ">=8" 873 | } 874 | }, 875 | "node_modules/he": { 876 | "version": "1.2.0", 877 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 878 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 879 | "dev": true, 880 | "bin": { 881 | "he": "bin/he" 882 | } 883 | }, 884 | "node_modules/ignore": { 885 | "version": "5.2.0", 886 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", 887 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", 888 | "dev": true, 889 | "engines": { 890 | "node": ">= 4" 891 | } 892 | }, 893 | "node_modules/import-fresh": { 894 | "version": "3.3.0", 895 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 896 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 897 | "dev": true, 898 | "dependencies": { 899 | "parent-module": "^1.0.0", 900 | "resolve-from": "^4.0.0" 901 | }, 902 | "engines": { 903 | "node": ">=6" 904 | }, 905 | "funding": { 906 | "url": "https://github.com/sponsors/sindresorhus" 907 | } 908 | }, 909 | "node_modules/imurmurhash": { 910 | "version": "0.1.4", 911 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 912 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 913 | "dev": true, 914 | "engines": { 915 | "node": ">=0.8.19" 916 | } 917 | }, 918 | "node_modules/inflight": { 919 | "version": "1.0.6", 920 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 921 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 922 | "dev": true, 923 | "dependencies": { 924 | "once": "^1.3.0", 925 | "wrappy": "1" 926 | } 927 | }, 928 | "node_modules/inherits": { 929 | "version": "2.0.3", 930 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 931 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 932 | "dev": true 933 | }, 934 | "node_modules/is-binary-path": { 935 | "version": "2.1.0", 936 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 937 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 938 | "dev": true, 939 | "dependencies": { 940 | "binary-extensions": "^2.0.0" 941 | }, 942 | "engines": { 943 | "node": ">=8" 944 | } 945 | }, 946 | "node_modules/is-extglob": { 947 | "version": "2.1.1", 948 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 949 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 950 | "dev": true, 951 | "engines": { 952 | "node": ">=0.10.0" 953 | } 954 | }, 955 | "node_modules/is-fullwidth-code-point": { 956 | "version": "3.0.0", 957 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 958 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 959 | "dev": true, 960 | "engines": { 961 | "node": ">=8" 962 | } 963 | }, 964 | "node_modules/is-glob": { 965 | "version": "4.0.3", 966 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 967 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 968 | "dev": true, 969 | "dependencies": { 970 | "is-extglob": "^2.1.1" 971 | }, 972 | "engines": { 973 | "node": ">=0.10.0" 974 | } 975 | }, 976 | "node_modules/is-number": { 977 | "version": "7.0.0", 978 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 979 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 980 | "dev": true, 981 | "engines": { 982 | "node": ">=0.12.0" 983 | } 984 | }, 985 | "node_modules/is-plain-obj": { 986 | "version": "2.1.0", 987 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 988 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 989 | "dev": true, 990 | "engines": { 991 | "node": ">=8" 992 | } 993 | }, 994 | "node_modules/is-unicode-supported": { 995 | "version": "0.1.0", 996 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 997 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 998 | "dev": true, 999 | "engines": { 1000 | "node": ">=10" 1001 | }, 1002 | "funding": { 1003 | "url": "https://github.com/sponsors/sindresorhus" 1004 | } 1005 | }, 1006 | "node_modules/isexe": { 1007 | "version": "2.0.0", 1008 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1009 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1010 | "dev": true 1011 | }, 1012 | "node_modules/js-yaml": { 1013 | "version": "4.1.0", 1014 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1015 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1016 | "dev": true, 1017 | "dependencies": { 1018 | "argparse": "^2.0.1" 1019 | }, 1020 | "bin": { 1021 | "js-yaml": "bin/js-yaml.js" 1022 | } 1023 | }, 1024 | "node_modules/json-schema-traverse": { 1025 | "version": "0.4.1", 1026 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1027 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1028 | "dev": true 1029 | }, 1030 | "node_modules/json-stable-stringify-without-jsonify": { 1031 | "version": "1.0.1", 1032 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1033 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1034 | "dev": true 1035 | }, 1036 | "node_modules/json-stringify-safe": { 1037 | "version": "5.0.1", 1038 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1039 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 1040 | "dev": true 1041 | }, 1042 | "node_modules/levn": { 1043 | "version": "0.4.1", 1044 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1045 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1046 | "dev": true, 1047 | "dependencies": { 1048 | "prelude-ls": "^1.2.1", 1049 | "type-check": "~0.4.0" 1050 | }, 1051 | "engines": { 1052 | "node": ">= 0.8.0" 1053 | } 1054 | }, 1055 | "node_modules/locate-path": { 1056 | "version": "6.0.0", 1057 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1058 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1059 | "dev": true, 1060 | "dependencies": { 1061 | "p-locate": "^5.0.0" 1062 | }, 1063 | "engines": { 1064 | "node": ">=10" 1065 | }, 1066 | "funding": { 1067 | "url": "https://github.com/sponsors/sindresorhus" 1068 | } 1069 | }, 1070 | "node_modules/lodash.merge": { 1071 | "version": "4.6.2", 1072 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1073 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1074 | "dev": true 1075 | }, 1076 | "node_modules/lodash.set": { 1077 | "version": "4.3.2", 1078 | "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", 1079 | "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", 1080 | "dev": true 1081 | }, 1082 | "node_modules/log-symbols": { 1083 | "version": "4.1.0", 1084 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1085 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1086 | "dev": true, 1087 | "dependencies": { 1088 | "chalk": "^4.1.0", 1089 | "is-unicode-supported": "^0.1.0" 1090 | }, 1091 | "engines": { 1092 | "node": ">=10" 1093 | }, 1094 | "funding": { 1095 | "url": "https://github.com/sponsors/sindresorhus" 1096 | } 1097 | }, 1098 | "node_modules/loupe": { 1099 | "version": "2.3.1", 1100 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", 1101 | "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", 1102 | "dev": true, 1103 | "dependencies": { 1104 | "get-func-name": "^2.0.0" 1105 | } 1106 | }, 1107 | "node_modules/mime": { 1108 | "version": "3.0.0", 1109 | "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 1110 | "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 1111 | "bin": { 1112 | "mime": "cli.js" 1113 | }, 1114 | "engines": { 1115 | "node": ">=10.0.0" 1116 | } 1117 | }, 1118 | "node_modules/minimatch": { 1119 | "version": "3.0.4", 1120 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1121 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1122 | "dev": true, 1123 | "dependencies": { 1124 | "brace-expansion": "^1.1.7" 1125 | }, 1126 | "engines": { 1127 | "node": "*" 1128 | } 1129 | }, 1130 | "node_modules/mocha": { 1131 | "version": "9.2.0", 1132 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.0.tgz", 1133 | "integrity": "sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q==", 1134 | "dev": true, 1135 | "dependencies": { 1136 | "@ungap/promise-all-settled": "1.1.2", 1137 | "ansi-colors": "4.1.1", 1138 | "browser-stdout": "1.3.1", 1139 | "chokidar": "3.5.3", 1140 | "debug": "4.3.3", 1141 | "diff": "5.0.0", 1142 | "escape-string-regexp": "4.0.0", 1143 | "find-up": "5.0.0", 1144 | "glob": "7.2.0", 1145 | "growl": "1.10.5", 1146 | "he": "1.2.0", 1147 | "js-yaml": "4.1.0", 1148 | "log-symbols": "4.1.0", 1149 | "minimatch": "3.0.4", 1150 | "ms": "2.1.3", 1151 | "nanoid": "3.2.0", 1152 | "serialize-javascript": "6.0.0", 1153 | "strip-json-comments": "3.1.1", 1154 | "supports-color": "8.1.1", 1155 | "which": "2.0.2", 1156 | "workerpool": "6.2.0", 1157 | "yargs": "16.2.0", 1158 | "yargs-parser": "20.2.4", 1159 | "yargs-unparser": "2.0.0" 1160 | }, 1161 | "bin": { 1162 | "_mocha": "bin/_mocha", 1163 | "mocha": "bin/mocha" 1164 | }, 1165 | "engines": { 1166 | "node": ">= 12.0.0" 1167 | }, 1168 | "funding": { 1169 | "type": "opencollective", 1170 | "url": "https://opencollective.com/mochajs" 1171 | } 1172 | }, 1173 | "node_modules/mocha/node_modules/supports-color": { 1174 | "version": "8.1.1", 1175 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1176 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1177 | "dev": true, 1178 | "dependencies": { 1179 | "has-flag": "^4.0.0" 1180 | }, 1181 | "engines": { 1182 | "node": ">=10" 1183 | }, 1184 | "funding": { 1185 | "url": "https://github.com/chalk/supports-color?sponsor=1" 1186 | } 1187 | }, 1188 | "node_modules/ms": { 1189 | "version": "2.1.3", 1190 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1191 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1192 | "dev": true 1193 | }, 1194 | "node_modules/nanoid": { 1195 | "version": "3.2.0", 1196 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", 1197 | "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", 1198 | "dev": true, 1199 | "bin": { 1200 | "nanoid": "bin/nanoid.cjs" 1201 | }, 1202 | "engines": { 1203 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1204 | } 1205 | }, 1206 | "node_modules/natural-compare": { 1207 | "version": "1.4.0", 1208 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1209 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1210 | "dev": true 1211 | }, 1212 | "node_modules/nock": { 1213 | "version": "13.2.3", 1214 | "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.3.tgz", 1215 | "integrity": "sha512-91wGYjHrjSvrnSUwpiopbmowbIx5s+QSkqj801edTMtrFY4mAiZXP1mKlk5ZG2oZclB8/PcxJ9TJviG+akmrdw==", 1216 | "dev": true, 1217 | "dependencies": { 1218 | "debug": "^4.1.0", 1219 | "json-stringify-safe": "^5.0.1", 1220 | "lodash.set": "^4.3.2", 1221 | "propagate": "^2.0.0" 1222 | }, 1223 | "engines": { 1224 | "node": ">= 10.13" 1225 | } 1226 | }, 1227 | "node_modules/node-domexception": { 1228 | "version": "1.0.0", 1229 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 1230 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 1231 | "funding": [ 1232 | { 1233 | "type": "github", 1234 | "url": "https://github.com/sponsors/jimmywarting" 1235 | }, 1236 | { 1237 | "type": "github", 1238 | "url": "https://paypal.me/jimmywarting" 1239 | } 1240 | ], 1241 | "engines": { 1242 | "node": ">=10.5.0" 1243 | } 1244 | }, 1245 | "node_modules/node-fetch": { 1246 | "version": "3.2.0", 1247 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.0.tgz", 1248 | "integrity": "sha512-8xeimMwMItMw8hRrOl3C9/xzU49HV/yE6ORew/l+dxWimO5A4Ra8ld2rerlJvc/O7et5Z1zrWsPX43v1QBjCxw==", 1249 | "dependencies": { 1250 | "data-uri-to-buffer": "^4.0.0", 1251 | "fetch-blob": "^3.1.4", 1252 | "formdata-polyfill": "^4.0.10" 1253 | }, 1254 | "engines": { 1255 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1256 | }, 1257 | "funding": { 1258 | "type": "opencollective", 1259 | "url": "https://opencollective.com/node-fetch" 1260 | } 1261 | }, 1262 | "node_modules/node-forge": { 1263 | "version": "1.2.1", 1264 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz", 1265 | "integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==", 1266 | "engines": { 1267 | "node": ">= 6.13.0" 1268 | } 1269 | }, 1270 | "node_modules/normalize-path": { 1271 | "version": "3.0.0", 1272 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1273 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1274 | "dev": true, 1275 | "engines": { 1276 | "node": ">=0.10.0" 1277 | } 1278 | }, 1279 | "node_modules/once": { 1280 | "version": "1.4.0", 1281 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1282 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1283 | "dev": true, 1284 | "dependencies": { 1285 | "wrappy": "1" 1286 | } 1287 | }, 1288 | "node_modules/optionator": { 1289 | "version": "0.9.1", 1290 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1291 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1292 | "dev": true, 1293 | "dependencies": { 1294 | "deep-is": "^0.1.3", 1295 | "fast-levenshtein": "^2.0.6", 1296 | "levn": "^0.4.1", 1297 | "prelude-ls": "^1.2.1", 1298 | "type-check": "^0.4.0", 1299 | "word-wrap": "^1.2.3" 1300 | }, 1301 | "engines": { 1302 | "node": ">= 0.8.0" 1303 | } 1304 | }, 1305 | "node_modules/p-limit": { 1306 | "version": "3.1.0", 1307 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1308 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1309 | "dev": true, 1310 | "dependencies": { 1311 | "yocto-queue": "^0.1.0" 1312 | }, 1313 | "engines": { 1314 | "node": ">=10" 1315 | }, 1316 | "funding": { 1317 | "url": "https://github.com/sponsors/sindresorhus" 1318 | } 1319 | }, 1320 | "node_modules/p-locate": { 1321 | "version": "5.0.0", 1322 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1323 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1324 | "dev": true, 1325 | "dependencies": { 1326 | "p-limit": "^3.0.2" 1327 | }, 1328 | "engines": { 1329 | "node": ">=10" 1330 | }, 1331 | "funding": { 1332 | "url": "https://github.com/sponsors/sindresorhus" 1333 | } 1334 | }, 1335 | "node_modules/parent-module": { 1336 | "version": "1.0.1", 1337 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1338 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1339 | "dev": true, 1340 | "dependencies": { 1341 | "callsites": "^3.0.0" 1342 | }, 1343 | "engines": { 1344 | "node": ">=6" 1345 | } 1346 | }, 1347 | "node_modules/path-exists": { 1348 | "version": "4.0.0", 1349 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1350 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1351 | "dev": true, 1352 | "engines": { 1353 | "node": ">=8" 1354 | } 1355 | }, 1356 | "node_modules/path-is-absolute": { 1357 | "version": "1.0.1", 1358 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1359 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1360 | "dev": true, 1361 | "engines": { 1362 | "node": ">=0.10.0" 1363 | } 1364 | }, 1365 | "node_modules/path-key": { 1366 | "version": "3.1.1", 1367 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1368 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1369 | "dev": true, 1370 | "engines": { 1371 | "node": ">=8" 1372 | } 1373 | }, 1374 | "node_modules/pathval": { 1375 | "version": "1.1.1", 1376 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 1377 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 1378 | "dev": true, 1379 | "engines": { 1380 | "node": "*" 1381 | } 1382 | }, 1383 | "node_modules/picomatch": { 1384 | "version": "2.3.1", 1385 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1386 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1387 | "dev": true, 1388 | "engines": { 1389 | "node": ">=8.6" 1390 | }, 1391 | "funding": { 1392 | "url": "https://github.com/sponsors/jonschlinkert" 1393 | } 1394 | }, 1395 | "node_modules/prelude-ls": { 1396 | "version": "1.2.1", 1397 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1398 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1399 | "dev": true, 1400 | "engines": { 1401 | "node": ">= 0.8.0" 1402 | } 1403 | }, 1404 | "node_modules/propagate": { 1405 | "version": "2.0.1", 1406 | "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", 1407 | "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", 1408 | "dev": true, 1409 | "engines": { 1410 | "node": ">= 8" 1411 | } 1412 | }, 1413 | "node_modules/punycode": { 1414 | "version": "2.1.1", 1415 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1416 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1417 | "dev": true, 1418 | "engines": { 1419 | "node": ">=6" 1420 | } 1421 | }, 1422 | "node_modules/randombytes": { 1423 | "version": "2.1.0", 1424 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1425 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1426 | "dev": true, 1427 | "dependencies": { 1428 | "safe-buffer": "^5.1.0" 1429 | } 1430 | }, 1431 | "node_modules/readdirp": { 1432 | "version": "3.6.0", 1433 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1434 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1435 | "dev": true, 1436 | "dependencies": { 1437 | "picomatch": "^2.2.1" 1438 | }, 1439 | "engines": { 1440 | "node": ">=8.10.0" 1441 | } 1442 | }, 1443 | "node_modules/regexpp": { 1444 | "version": "3.2.0", 1445 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 1446 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1447 | "dev": true, 1448 | "engines": { 1449 | "node": ">=8" 1450 | }, 1451 | "funding": { 1452 | "url": "https://github.com/sponsors/mysticatea" 1453 | } 1454 | }, 1455 | "node_modules/require-directory": { 1456 | "version": "2.1.1", 1457 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1458 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1459 | "dev": true, 1460 | "engines": { 1461 | "node": ">=0.10.0" 1462 | } 1463 | }, 1464 | "node_modules/resolve-from": { 1465 | "version": "4.0.0", 1466 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1467 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1468 | "dev": true, 1469 | "engines": { 1470 | "node": ">=4" 1471 | } 1472 | }, 1473 | "node_modules/rimraf": { 1474 | "version": "3.0.2", 1475 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1476 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1477 | "dev": true, 1478 | "dependencies": { 1479 | "glob": "^7.1.3" 1480 | }, 1481 | "bin": { 1482 | "rimraf": "bin.js" 1483 | }, 1484 | "funding": { 1485 | "url": "https://github.com/sponsors/isaacs" 1486 | } 1487 | }, 1488 | "node_modules/safe-buffer": { 1489 | "version": "5.2.1", 1490 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1491 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1492 | "dev": true, 1493 | "funding": [ 1494 | { 1495 | "type": "github", 1496 | "url": "https://github.com/sponsors/feross" 1497 | }, 1498 | { 1499 | "type": "patreon", 1500 | "url": "https://www.patreon.com/feross" 1501 | }, 1502 | { 1503 | "type": "consulting", 1504 | "url": "https://feross.org/support" 1505 | } 1506 | ] 1507 | }, 1508 | "node_modules/serialize-javascript": { 1509 | "version": "6.0.0", 1510 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 1511 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 1512 | "dev": true, 1513 | "dependencies": { 1514 | "randombytes": "^2.1.0" 1515 | } 1516 | }, 1517 | "node_modules/shebang-command": { 1518 | "version": "2.0.0", 1519 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1520 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1521 | "dev": true, 1522 | "dependencies": { 1523 | "shebang-regex": "^3.0.0" 1524 | }, 1525 | "engines": { 1526 | "node": ">=8" 1527 | } 1528 | }, 1529 | "node_modules/shebang-regex": { 1530 | "version": "3.0.0", 1531 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1532 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1533 | "dev": true, 1534 | "engines": { 1535 | "node": ">=8" 1536 | } 1537 | }, 1538 | "node_modules/string-width": { 1539 | "version": "4.2.3", 1540 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1541 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1542 | "dev": true, 1543 | "dependencies": { 1544 | "emoji-regex": "^8.0.0", 1545 | "is-fullwidth-code-point": "^3.0.0", 1546 | "strip-ansi": "^6.0.1" 1547 | }, 1548 | "engines": { 1549 | "node": ">=8" 1550 | } 1551 | }, 1552 | "node_modules/strip-ansi": { 1553 | "version": "6.0.1", 1554 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1555 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1556 | "dev": true, 1557 | "dependencies": { 1558 | "ansi-regex": "^5.0.1" 1559 | }, 1560 | "engines": { 1561 | "node": ">=8" 1562 | } 1563 | }, 1564 | "node_modules/strip-json-comments": { 1565 | "version": "3.1.1", 1566 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1567 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1568 | "dev": true, 1569 | "engines": { 1570 | "node": ">=8" 1571 | }, 1572 | "funding": { 1573 | "url": "https://github.com/sponsors/sindresorhus" 1574 | } 1575 | }, 1576 | "node_modules/supports-color": { 1577 | "version": "7.2.0", 1578 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1579 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1580 | "dev": true, 1581 | "dependencies": { 1582 | "has-flag": "^4.0.0" 1583 | }, 1584 | "engines": { 1585 | "node": ">=8" 1586 | } 1587 | }, 1588 | "node_modules/text-table": { 1589 | "version": "0.2.0", 1590 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1591 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1592 | "dev": true 1593 | }, 1594 | "node_modules/to-regex-range": { 1595 | "version": "5.0.1", 1596 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1597 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1598 | "dev": true, 1599 | "dependencies": { 1600 | "is-number": "^7.0.0" 1601 | }, 1602 | "engines": { 1603 | "node": ">=8.0" 1604 | } 1605 | }, 1606 | "node_modules/type-check": { 1607 | "version": "0.4.0", 1608 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1609 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1610 | "dev": true, 1611 | "dependencies": { 1612 | "prelude-ls": "^1.2.1" 1613 | }, 1614 | "engines": { 1615 | "node": ">= 0.8.0" 1616 | } 1617 | }, 1618 | "node_modules/type-detect": { 1619 | "version": "4.0.8", 1620 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1621 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1622 | "dev": true, 1623 | "engines": { 1624 | "node": ">=4" 1625 | } 1626 | }, 1627 | "node_modules/type-fest": { 1628 | "version": "0.20.2", 1629 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1630 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1631 | "dev": true, 1632 | "engines": { 1633 | "node": ">=10" 1634 | }, 1635 | "funding": { 1636 | "url": "https://github.com/sponsors/sindresorhus" 1637 | } 1638 | }, 1639 | "node_modules/uri-js": { 1640 | "version": "4.4.1", 1641 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1642 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1643 | "dev": true, 1644 | "dependencies": { 1645 | "punycode": "^2.1.0" 1646 | } 1647 | }, 1648 | "node_modules/v8-compile-cache": { 1649 | "version": "2.3.0", 1650 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 1651 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 1652 | "dev": true 1653 | }, 1654 | "node_modules/web-streams-polyfill": { 1655 | "version": "3.2.0", 1656 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", 1657 | "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", 1658 | "engines": { 1659 | "node": ">= 8" 1660 | } 1661 | }, 1662 | "node_modules/which": { 1663 | "version": "2.0.2", 1664 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1665 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1666 | "dev": true, 1667 | "dependencies": { 1668 | "isexe": "^2.0.0" 1669 | }, 1670 | "bin": { 1671 | "node-which": "bin/node-which" 1672 | }, 1673 | "engines": { 1674 | "node": ">= 8" 1675 | } 1676 | }, 1677 | "node_modules/word-wrap": { 1678 | "version": "1.2.3", 1679 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1680 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1681 | "dev": true, 1682 | "engines": { 1683 | "node": ">=0.10.0" 1684 | } 1685 | }, 1686 | "node_modules/workerpool": { 1687 | "version": "6.2.0", 1688 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", 1689 | "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", 1690 | "dev": true 1691 | }, 1692 | "node_modules/wrap-ansi": { 1693 | "version": "7.0.0", 1694 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1695 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1696 | "dev": true, 1697 | "dependencies": { 1698 | "ansi-styles": "^4.0.0", 1699 | "string-width": "^4.1.0", 1700 | "strip-ansi": "^6.0.0" 1701 | }, 1702 | "engines": { 1703 | "node": ">=10" 1704 | }, 1705 | "funding": { 1706 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1707 | } 1708 | }, 1709 | "node_modules/wrappy": { 1710 | "version": "1.0.2", 1711 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1712 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1713 | "dev": true 1714 | }, 1715 | "node_modules/ws": { 1716 | "version": "8.4.2", 1717 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", 1718 | "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", 1719 | "engines": { 1720 | "node": ">=10.0.0" 1721 | }, 1722 | "peerDependencies": { 1723 | "bufferutil": "^4.0.1", 1724 | "utf-8-validate": "^5.0.2" 1725 | }, 1726 | "peerDependenciesMeta": { 1727 | "bufferutil": { 1728 | "optional": true 1729 | }, 1730 | "utf-8-validate": { 1731 | "optional": true 1732 | } 1733 | } 1734 | }, 1735 | "node_modules/y18n": { 1736 | "version": "5.0.8", 1737 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1738 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1739 | "dev": true, 1740 | "engines": { 1741 | "node": ">=10" 1742 | } 1743 | }, 1744 | "node_modules/yargs": { 1745 | "version": "16.2.0", 1746 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1747 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1748 | "dev": true, 1749 | "dependencies": { 1750 | "cliui": "^7.0.2", 1751 | "escalade": "^3.1.1", 1752 | "get-caller-file": "^2.0.5", 1753 | "require-directory": "^2.1.1", 1754 | "string-width": "^4.2.0", 1755 | "y18n": "^5.0.5", 1756 | "yargs-parser": "^20.2.2" 1757 | }, 1758 | "engines": { 1759 | "node": ">=10" 1760 | } 1761 | }, 1762 | "node_modules/yargs-parser": { 1763 | "version": "20.2.4", 1764 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1765 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1766 | "dev": true, 1767 | "engines": { 1768 | "node": ">=10" 1769 | } 1770 | }, 1771 | "node_modules/yargs-unparser": { 1772 | "version": "2.0.0", 1773 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1774 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1775 | "dev": true, 1776 | "dependencies": { 1777 | "camelcase": "^6.0.0", 1778 | "decamelize": "^4.0.0", 1779 | "flat": "^5.0.2", 1780 | "is-plain-obj": "^2.1.0" 1781 | }, 1782 | "engines": { 1783 | "node": ">=10" 1784 | } 1785 | }, 1786 | "node_modules/yocto-queue": { 1787 | "version": "0.1.0", 1788 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1789 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1790 | "dev": true, 1791 | "engines": { 1792 | "node": ">=10" 1793 | }, 1794 | "funding": { 1795 | "url": "https://github.com/sponsors/sindresorhus" 1796 | } 1797 | } 1798 | }, 1799 | "dependencies": { 1800 | "@eslint/eslintrc": { 1801 | "version": "1.0.5", 1802 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", 1803 | "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", 1804 | "dev": true, 1805 | "requires": { 1806 | "ajv": "^6.12.4", 1807 | "debug": "^4.3.2", 1808 | "espree": "^9.2.0", 1809 | "globals": "^13.9.0", 1810 | "ignore": "^4.0.6", 1811 | "import-fresh": "^3.2.1", 1812 | "js-yaml": "^4.1.0", 1813 | "minimatch": "^3.0.4", 1814 | "strip-json-comments": "^3.1.1" 1815 | }, 1816 | "dependencies": { 1817 | "ignore": { 1818 | "version": "4.0.6", 1819 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1820 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1821 | "dev": true 1822 | } 1823 | } 1824 | }, 1825 | "@humanwhocodes/config-array": { 1826 | "version": "0.9.3", 1827 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", 1828 | "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", 1829 | "dev": true, 1830 | "requires": { 1831 | "@humanwhocodes/object-schema": "^1.2.1", 1832 | "debug": "^4.1.1", 1833 | "minimatch": "^3.0.4" 1834 | } 1835 | }, 1836 | "@humanwhocodes/object-schema": { 1837 | "version": "1.2.1", 1838 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 1839 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 1840 | "dev": true 1841 | }, 1842 | "@ungap/promise-all-settled": { 1843 | "version": "1.1.2", 1844 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 1845 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 1846 | "dev": true 1847 | }, 1848 | "acorn": { 1849 | "version": "8.7.0", 1850 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", 1851 | "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", 1852 | "dev": true 1853 | }, 1854 | "acorn-jsx": { 1855 | "version": "5.3.2", 1856 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 1857 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 1858 | "dev": true, 1859 | "requires": {} 1860 | }, 1861 | "ajv": { 1862 | "version": "6.12.6", 1863 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 1864 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 1865 | "dev": true, 1866 | "requires": { 1867 | "fast-deep-equal": "^3.1.1", 1868 | "fast-json-stable-stringify": "^2.0.0", 1869 | "json-schema-traverse": "^0.4.1", 1870 | "uri-js": "^4.2.2" 1871 | } 1872 | }, 1873 | "ansi-colors": { 1874 | "version": "4.1.1", 1875 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 1876 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 1877 | "dev": true 1878 | }, 1879 | "ansi-regex": { 1880 | "version": "5.0.1", 1881 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1882 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1883 | "dev": true 1884 | }, 1885 | "ansi-styles": { 1886 | "version": "4.3.0", 1887 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1888 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1889 | "dev": true, 1890 | "requires": { 1891 | "color-convert": "^2.0.1" 1892 | } 1893 | }, 1894 | "anymatch": { 1895 | "version": "3.1.2", 1896 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 1897 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 1898 | "dev": true, 1899 | "requires": { 1900 | "normalize-path": "^3.0.0", 1901 | "picomatch": "^2.0.4" 1902 | } 1903 | }, 1904 | "argparse": { 1905 | "version": "2.0.1", 1906 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1907 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1908 | "dev": true 1909 | }, 1910 | "assertion-error": { 1911 | "version": "1.1.0", 1912 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 1913 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 1914 | "dev": true 1915 | }, 1916 | "balanced-match": { 1917 | "version": "1.0.0", 1918 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 1919 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 1920 | "dev": true 1921 | }, 1922 | "binary-extensions": { 1923 | "version": "2.2.0", 1924 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 1925 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 1926 | "dev": true 1927 | }, 1928 | "brace-expansion": { 1929 | "version": "1.1.11", 1930 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1931 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1932 | "dev": true, 1933 | "requires": { 1934 | "balanced-match": "^1.0.0", 1935 | "concat-map": "0.0.1" 1936 | } 1937 | }, 1938 | "braces": { 1939 | "version": "3.0.2", 1940 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1941 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1942 | "dev": true, 1943 | "requires": { 1944 | "fill-range": "^7.0.1" 1945 | } 1946 | }, 1947 | "browser-stdout": { 1948 | "version": "1.3.1", 1949 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 1950 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 1951 | "dev": true 1952 | }, 1953 | "callsites": { 1954 | "version": "3.1.0", 1955 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1956 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1957 | "dev": true 1958 | }, 1959 | "camelcase": { 1960 | "version": "6.3.0", 1961 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 1962 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 1963 | "dev": true 1964 | }, 1965 | "chai": { 1966 | "version": "4.3.6", 1967 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", 1968 | "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", 1969 | "dev": true, 1970 | "requires": { 1971 | "assertion-error": "^1.1.0", 1972 | "check-error": "^1.0.2", 1973 | "deep-eql": "^3.0.1", 1974 | "get-func-name": "^2.0.0", 1975 | "loupe": "^2.3.1", 1976 | "pathval": "^1.1.1", 1977 | "type-detect": "^4.0.5" 1978 | } 1979 | }, 1980 | "chalk": { 1981 | "version": "4.1.2", 1982 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1983 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1984 | "dev": true, 1985 | "requires": { 1986 | "ansi-styles": "^4.1.0", 1987 | "supports-color": "^7.1.0" 1988 | } 1989 | }, 1990 | "check-error": { 1991 | "version": "1.0.2", 1992 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 1993 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 1994 | "dev": true 1995 | }, 1996 | "chokidar": { 1997 | "version": "3.5.3", 1998 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 1999 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 2000 | "dev": true, 2001 | "requires": { 2002 | "anymatch": "~3.1.2", 2003 | "braces": "~3.0.2", 2004 | "fsevents": "~2.3.2", 2005 | "glob-parent": "~5.1.2", 2006 | "is-binary-path": "~2.1.0", 2007 | "is-glob": "~4.0.1", 2008 | "normalize-path": "~3.0.0", 2009 | "readdirp": "~3.6.0" 2010 | }, 2011 | "dependencies": { 2012 | "glob-parent": { 2013 | "version": "5.1.2", 2014 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2015 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2016 | "dev": true, 2017 | "requires": { 2018 | "is-glob": "^4.0.1" 2019 | } 2020 | } 2021 | } 2022 | }, 2023 | "cliui": { 2024 | "version": "7.0.4", 2025 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 2026 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 2027 | "dev": true, 2028 | "requires": { 2029 | "string-width": "^4.2.0", 2030 | "strip-ansi": "^6.0.0", 2031 | "wrap-ansi": "^7.0.0" 2032 | } 2033 | }, 2034 | "clone": { 2035 | "version": "2.1.2", 2036 | "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", 2037 | "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" 2038 | }, 2039 | "color-convert": { 2040 | "version": "2.0.1", 2041 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2042 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2043 | "dev": true, 2044 | "requires": { 2045 | "color-name": "~1.1.4" 2046 | } 2047 | }, 2048 | "color-name": { 2049 | "version": "1.1.4", 2050 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2051 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2052 | "dev": true 2053 | }, 2054 | "concat-map": { 2055 | "version": "0.0.1", 2056 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 2057 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 2058 | "dev": true 2059 | }, 2060 | "cross-spawn": { 2061 | "version": "7.0.3", 2062 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 2063 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 2064 | "dev": true, 2065 | "requires": { 2066 | "path-key": "^3.1.0", 2067 | "shebang-command": "^2.0.0", 2068 | "which": "^2.0.1" 2069 | } 2070 | }, 2071 | "data-uri-to-buffer": { 2072 | "version": "4.0.0", 2073 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", 2074 | "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" 2075 | }, 2076 | "debug": { 2077 | "version": "4.3.3", 2078 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 2079 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 2080 | "dev": true, 2081 | "requires": { 2082 | "ms": "2.1.2" 2083 | }, 2084 | "dependencies": { 2085 | "ms": { 2086 | "version": "2.1.2", 2087 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2088 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2089 | "dev": true 2090 | } 2091 | } 2092 | }, 2093 | "decamelize": { 2094 | "version": "4.0.0", 2095 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 2096 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 2097 | "dev": true 2098 | }, 2099 | "deep-eql": { 2100 | "version": "3.0.1", 2101 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 2102 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 2103 | "dev": true, 2104 | "requires": { 2105 | "type-detect": "^4.0.0" 2106 | } 2107 | }, 2108 | "deep-is": { 2109 | "version": "0.1.4", 2110 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 2111 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 2112 | "dev": true 2113 | }, 2114 | "diff": { 2115 | "version": "5.0.0", 2116 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 2117 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 2118 | "dev": true 2119 | }, 2120 | "doctrine": { 2121 | "version": "3.0.0", 2122 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 2123 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 2124 | "dev": true, 2125 | "requires": { 2126 | "esutils": "^2.0.2" 2127 | } 2128 | }, 2129 | "emoji-regex": { 2130 | "version": "8.0.0", 2131 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2132 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2133 | "dev": true 2134 | }, 2135 | "escalade": { 2136 | "version": "3.1.1", 2137 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 2138 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 2139 | "dev": true 2140 | }, 2141 | "escape-string-regexp": { 2142 | "version": "4.0.0", 2143 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 2144 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 2145 | "dev": true 2146 | }, 2147 | "eslint": { 2148 | "version": "8.8.0", 2149 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", 2150 | "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", 2151 | "dev": true, 2152 | "requires": { 2153 | "@eslint/eslintrc": "^1.0.5", 2154 | "@humanwhocodes/config-array": "^0.9.2", 2155 | "ajv": "^6.10.0", 2156 | "chalk": "^4.0.0", 2157 | "cross-spawn": "^7.0.2", 2158 | "debug": "^4.3.2", 2159 | "doctrine": "^3.0.0", 2160 | "escape-string-regexp": "^4.0.0", 2161 | "eslint-scope": "^7.1.0", 2162 | "eslint-utils": "^3.0.0", 2163 | "eslint-visitor-keys": "^3.2.0", 2164 | "espree": "^9.3.0", 2165 | "esquery": "^1.4.0", 2166 | "esutils": "^2.0.2", 2167 | "fast-deep-equal": "^3.1.3", 2168 | "file-entry-cache": "^6.0.1", 2169 | "functional-red-black-tree": "^1.0.1", 2170 | "glob-parent": "^6.0.1", 2171 | "globals": "^13.6.0", 2172 | "ignore": "^5.2.0", 2173 | "import-fresh": "^3.0.0", 2174 | "imurmurhash": "^0.1.4", 2175 | "is-glob": "^4.0.0", 2176 | "js-yaml": "^4.1.0", 2177 | "json-stable-stringify-without-jsonify": "^1.0.1", 2178 | "levn": "^0.4.1", 2179 | "lodash.merge": "^4.6.2", 2180 | "minimatch": "^3.0.4", 2181 | "natural-compare": "^1.4.0", 2182 | "optionator": "^0.9.1", 2183 | "regexpp": "^3.2.0", 2184 | "strip-ansi": "^6.0.1", 2185 | "strip-json-comments": "^3.1.0", 2186 | "text-table": "^0.2.0", 2187 | "v8-compile-cache": "^2.0.3" 2188 | } 2189 | }, 2190 | "eslint-scope": { 2191 | "version": "7.1.0", 2192 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", 2193 | "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", 2194 | "dev": true, 2195 | "requires": { 2196 | "esrecurse": "^4.3.0", 2197 | "estraverse": "^5.2.0" 2198 | } 2199 | }, 2200 | "eslint-utils": { 2201 | "version": "3.0.0", 2202 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 2203 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 2204 | "dev": true, 2205 | "requires": { 2206 | "eslint-visitor-keys": "^2.0.0" 2207 | }, 2208 | "dependencies": { 2209 | "eslint-visitor-keys": { 2210 | "version": "2.1.0", 2211 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 2212 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 2213 | "dev": true 2214 | } 2215 | } 2216 | }, 2217 | "eslint-visitor-keys": { 2218 | "version": "3.2.0", 2219 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", 2220 | "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", 2221 | "dev": true 2222 | }, 2223 | "espree": { 2224 | "version": "9.3.0", 2225 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", 2226 | "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", 2227 | "dev": true, 2228 | "requires": { 2229 | "acorn": "^8.7.0", 2230 | "acorn-jsx": "^5.3.1", 2231 | "eslint-visitor-keys": "^3.1.0" 2232 | } 2233 | }, 2234 | "esquery": { 2235 | "version": "1.4.0", 2236 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 2237 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 2238 | "dev": true, 2239 | "requires": { 2240 | "estraverse": "^5.1.0" 2241 | } 2242 | }, 2243 | "esrecurse": { 2244 | "version": "4.3.0", 2245 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 2246 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 2247 | "dev": true, 2248 | "requires": { 2249 | "estraverse": "^5.2.0" 2250 | } 2251 | }, 2252 | "estraverse": { 2253 | "version": "5.3.0", 2254 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 2255 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 2256 | "dev": true 2257 | }, 2258 | "esutils": { 2259 | "version": "2.0.3", 2260 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 2261 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 2262 | "dev": true 2263 | }, 2264 | "fast-deep-equal": { 2265 | "version": "3.1.3", 2266 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 2267 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 2268 | "dev": true 2269 | }, 2270 | "fast-json-stable-stringify": { 2271 | "version": "2.1.0", 2272 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 2273 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 2274 | "dev": true 2275 | }, 2276 | "fast-levenshtein": { 2277 | "version": "2.0.6", 2278 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 2279 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 2280 | "dev": true 2281 | }, 2282 | "fetch-blob": { 2283 | "version": "3.1.4", 2284 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", 2285 | "integrity": "sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA==", 2286 | "requires": { 2287 | "node-domexception": "^1.0.0", 2288 | "web-streams-polyfill": "^3.0.3" 2289 | } 2290 | }, 2291 | "file-entry-cache": { 2292 | "version": "6.0.1", 2293 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 2294 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 2295 | "dev": true, 2296 | "requires": { 2297 | "flat-cache": "^3.0.4" 2298 | } 2299 | }, 2300 | "fill-range": { 2301 | "version": "7.0.1", 2302 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 2303 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 2304 | "dev": true, 2305 | "requires": { 2306 | "to-regex-range": "^5.0.1" 2307 | } 2308 | }, 2309 | "find-up": { 2310 | "version": "5.0.0", 2311 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 2312 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 2313 | "dev": true, 2314 | "requires": { 2315 | "locate-path": "^6.0.0", 2316 | "path-exists": "^4.0.0" 2317 | } 2318 | }, 2319 | "flat": { 2320 | "version": "5.0.2", 2321 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 2322 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 2323 | "dev": true 2324 | }, 2325 | "flat-cache": { 2326 | "version": "3.0.4", 2327 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 2328 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 2329 | "dev": true, 2330 | "requires": { 2331 | "flatted": "^3.1.0", 2332 | "rimraf": "^3.0.2" 2333 | } 2334 | }, 2335 | "flatted": { 2336 | "version": "3.2.5", 2337 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", 2338 | "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", 2339 | "dev": true 2340 | }, 2341 | "formdata-polyfill": { 2342 | "version": "4.0.10", 2343 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 2344 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 2345 | "requires": { 2346 | "fetch-blob": "^3.1.2" 2347 | } 2348 | }, 2349 | "fs.realpath": { 2350 | "version": "1.0.0", 2351 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 2352 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 2353 | "dev": true 2354 | }, 2355 | "fsevents": { 2356 | "version": "2.3.2", 2357 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 2358 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 2359 | "dev": true, 2360 | "optional": true 2361 | }, 2362 | "functional-red-black-tree": { 2363 | "version": "1.0.1", 2364 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 2365 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 2366 | "dev": true 2367 | }, 2368 | "get-caller-file": { 2369 | "version": "2.0.5", 2370 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 2371 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 2372 | "dev": true 2373 | }, 2374 | "get-func-name": { 2375 | "version": "2.0.0", 2376 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 2377 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 2378 | "dev": true 2379 | }, 2380 | "glob": { 2381 | "version": "7.2.0", 2382 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 2383 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 2384 | "dev": true, 2385 | "requires": { 2386 | "fs.realpath": "^1.0.0", 2387 | "inflight": "^1.0.4", 2388 | "inherits": "2", 2389 | "minimatch": "^3.0.4", 2390 | "once": "^1.3.0", 2391 | "path-is-absolute": "^1.0.0" 2392 | } 2393 | }, 2394 | "glob-parent": { 2395 | "version": "6.0.2", 2396 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 2397 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 2398 | "dev": true, 2399 | "requires": { 2400 | "is-glob": "^4.0.3" 2401 | } 2402 | }, 2403 | "globals": { 2404 | "version": "13.12.0", 2405 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", 2406 | "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", 2407 | "dev": true, 2408 | "requires": { 2409 | "type-fest": "^0.20.2" 2410 | } 2411 | }, 2412 | "growl": { 2413 | "version": "1.10.5", 2414 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 2415 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 2416 | "dev": true 2417 | }, 2418 | "has-flag": { 2419 | "version": "4.0.0", 2420 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2421 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2422 | "dev": true 2423 | }, 2424 | "he": { 2425 | "version": "1.2.0", 2426 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 2427 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 2428 | "dev": true 2429 | }, 2430 | "ignore": { 2431 | "version": "5.2.0", 2432 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", 2433 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", 2434 | "dev": true 2435 | }, 2436 | "import-fresh": { 2437 | "version": "3.3.0", 2438 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 2439 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 2440 | "dev": true, 2441 | "requires": { 2442 | "parent-module": "^1.0.0", 2443 | "resolve-from": "^4.0.0" 2444 | } 2445 | }, 2446 | "imurmurhash": { 2447 | "version": "0.1.4", 2448 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 2449 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 2450 | "dev": true 2451 | }, 2452 | "inflight": { 2453 | "version": "1.0.6", 2454 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 2455 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 2456 | "dev": true, 2457 | "requires": { 2458 | "once": "^1.3.0", 2459 | "wrappy": "1" 2460 | } 2461 | }, 2462 | "inherits": { 2463 | "version": "2.0.3", 2464 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2465 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 2466 | "dev": true 2467 | }, 2468 | "is-binary-path": { 2469 | "version": "2.1.0", 2470 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2471 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2472 | "dev": true, 2473 | "requires": { 2474 | "binary-extensions": "^2.0.0" 2475 | } 2476 | }, 2477 | "is-extglob": { 2478 | "version": "2.1.1", 2479 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2480 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 2481 | "dev": true 2482 | }, 2483 | "is-fullwidth-code-point": { 2484 | "version": "3.0.0", 2485 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2486 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2487 | "dev": true 2488 | }, 2489 | "is-glob": { 2490 | "version": "4.0.3", 2491 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2492 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2493 | "dev": true, 2494 | "requires": { 2495 | "is-extglob": "^2.1.1" 2496 | } 2497 | }, 2498 | "is-number": { 2499 | "version": "7.0.0", 2500 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2501 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 2502 | "dev": true 2503 | }, 2504 | "is-plain-obj": { 2505 | "version": "2.1.0", 2506 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 2507 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 2508 | "dev": true 2509 | }, 2510 | "is-unicode-supported": { 2511 | "version": "0.1.0", 2512 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 2513 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 2514 | "dev": true 2515 | }, 2516 | "isexe": { 2517 | "version": "2.0.0", 2518 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 2519 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 2520 | "dev": true 2521 | }, 2522 | "js-yaml": { 2523 | "version": "4.1.0", 2524 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 2525 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 2526 | "dev": true, 2527 | "requires": { 2528 | "argparse": "^2.0.1" 2529 | } 2530 | }, 2531 | "json-schema-traverse": { 2532 | "version": "0.4.1", 2533 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2534 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 2535 | "dev": true 2536 | }, 2537 | "json-stable-stringify-without-jsonify": { 2538 | "version": "1.0.1", 2539 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 2540 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 2541 | "dev": true 2542 | }, 2543 | "json-stringify-safe": { 2544 | "version": "5.0.1", 2545 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 2546 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 2547 | "dev": true 2548 | }, 2549 | "levn": { 2550 | "version": "0.4.1", 2551 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 2552 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 2553 | "dev": true, 2554 | "requires": { 2555 | "prelude-ls": "^1.2.1", 2556 | "type-check": "~0.4.0" 2557 | } 2558 | }, 2559 | "locate-path": { 2560 | "version": "6.0.0", 2561 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 2562 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 2563 | "dev": true, 2564 | "requires": { 2565 | "p-locate": "^5.0.0" 2566 | } 2567 | }, 2568 | "lodash.merge": { 2569 | "version": "4.6.2", 2570 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 2571 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 2572 | "dev": true 2573 | }, 2574 | "lodash.set": { 2575 | "version": "4.3.2", 2576 | "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", 2577 | "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", 2578 | "dev": true 2579 | }, 2580 | "log-symbols": { 2581 | "version": "4.1.0", 2582 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 2583 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 2584 | "dev": true, 2585 | "requires": { 2586 | "chalk": "^4.1.0", 2587 | "is-unicode-supported": "^0.1.0" 2588 | } 2589 | }, 2590 | "loupe": { 2591 | "version": "2.3.1", 2592 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", 2593 | "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", 2594 | "dev": true, 2595 | "requires": { 2596 | "get-func-name": "^2.0.0" 2597 | } 2598 | }, 2599 | "mime": { 2600 | "version": "3.0.0", 2601 | "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 2602 | "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" 2603 | }, 2604 | "minimatch": { 2605 | "version": "3.0.4", 2606 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 2607 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 2608 | "dev": true, 2609 | "requires": { 2610 | "brace-expansion": "^1.1.7" 2611 | } 2612 | }, 2613 | "mocha": { 2614 | "version": "9.2.0", 2615 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.0.tgz", 2616 | "integrity": "sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q==", 2617 | "dev": true, 2618 | "requires": { 2619 | "@ungap/promise-all-settled": "1.1.2", 2620 | "ansi-colors": "4.1.1", 2621 | "browser-stdout": "1.3.1", 2622 | "chokidar": "3.5.3", 2623 | "debug": "4.3.3", 2624 | "diff": "5.0.0", 2625 | "escape-string-regexp": "4.0.0", 2626 | "find-up": "5.0.0", 2627 | "glob": "7.2.0", 2628 | "growl": "1.10.5", 2629 | "he": "1.2.0", 2630 | "js-yaml": "4.1.0", 2631 | "log-symbols": "4.1.0", 2632 | "minimatch": "3.0.4", 2633 | "ms": "2.1.3", 2634 | "nanoid": "3.2.0", 2635 | "serialize-javascript": "6.0.0", 2636 | "strip-json-comments": "3.1.1", 2637 | "supports-color": "8.1.1", 2638 | "which": "2.0.2", 2639 | "workerpool": "6.2.0", 2640 | "yargs": "16.2.0", 2641 | "yargs-parser": "20.2.4", 2642 | "yargs-unparser": "2.0.0" 2643 | }, 2644 | "dependencies": { 2645 | "supports-color": { 2646 | "version": "8.1.1", 2647 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 2648 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 2649 | "dev": true, 2650 | "requires": { 2651 | "has-flag": "^4.0.0" 2652 | } 2653 | } 2654 | } 2655 | }, 2656 | "ms": { 2657 | "version": "2.1.3", 2658 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2659 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2660 | "dev": true 2661 | }, 2662 | "nanoid": { 2663 | "version": "3.2.0", 2664 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", 2665 | "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", 2666 | "dev": true 2667 | }, 2668 | "natural-compare": { 2669 | "version": "1.4.0", 2670 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 2671 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 2672 | "dev": true 2673 | }, 2674 | "nock": { 2675 | "version": "13.2.3", 2676 | "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.3.tgz", 2677 | "integrity": "sha512-91wGYjHrjSvrnSUwpiopbmowbIx5s+QSkqj801edTMtrFY4mAiZXP1mKlk5ZG2oZclB8/PcxJ9TJviG+akmrdw==", 2678 | "dev": true, 2679 | "requires": { 2680 | "debug": "^4.1.0", 2681 | "json-stringify-safe": "^5.0.1", 2682 | "lodash.set": "^4.3.2", 2683 | "propagate": "^2.0.0" 2684 | } 2685 | }, 2686 | "node-domexception": { 2687 | "version": "1.0.0", 2688 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 2689 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" 2690 | }, 2691 | "node-fetch": { 2692 | "version": "3.2.0", 2693 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.0.tgz", 2694 | "integrity": "sha512-8xeimMwMItMw8hRrOl3C9/xzU49HV/yE6ORew/l+dxWimO5A4Ra8ld2rerlJvc/O7et5Z1zrWsPX43v1QBjCxw==", 2695 | "requires": { 2696 | "data-uri-to-buffer": "^4.0.0", 2697 | "fetch-blob": "^3.1.4", 2698 | "formdata-polyfill": "^4.0.10" 2699 | } 2700 | }, 2701 | "node-forge": { 2702 | "version": "1.2.1", 2703 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz", 2704 | "integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==" 2705 | }, 2706 | "normalize-path": { 2707 | "version": "3.0.0", 2708 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2709 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 2710 | "dev": true 2711 | }, 2712 | "once": { 2713 | "version": "1.4.0", 2714 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2715 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2716 | "dev": true, 2717 | "requires": { 2718 | "wrappy": "1" 2719 | } 2720 | }, 2721 | "optionator": { 2722 | "version": "0.9.1", 2723 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 2724 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 2725 | "dev": true, 2726 | "requires": { 2727 | "deep-is": "^0.1.3", 2728 | "fast-levenshtein": "^2.0.6", 2729 | "levn": "^0.4.1", 2730 | "prelude-ls": "^1.2.1", 2731 | "type-check": "^0.4.0", 2732 | "word-wrap": "^1.2.3" 2733 | } 2734 | }, 2735 | "p-limit": { 2736 | "version": "3.1.0", 2737 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 2738 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 2739 | "dev": true, 2740 | "requires": { 2741 | "yocto-queue": "^0.1.0" 2742 | } 2743 | }, 2744 | "p-locate": { 2745 | "version": "5.0.0", 2746 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 2747 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 2748 | "dev": true, 2749 | "requires": { 2750 | "p-limit": "^3.0.2" 2751 | } 2752 | }, 2753 | "parent-module": { 2754 | "version": "1.0.1", 2755 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2756 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2757 | "dev": true, 2758 | "requires": { 2759 | "callsites": "^3.0.0" 2760 | } 2761 | }, 2762 | "path-exists": { 2763 | "version": "4.0.0", 2764 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2765 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2766 | "dev": true 2767 | }, 2768 | "path-is-absolute": { 2769 | "version": "1.0.1", 2770 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2771 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2772 | "dev": true 2773 | }, 2774 | "path-key": { 2775 | "version": "3.1.1", 2776 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2777 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2778 | "dev": true 2779 | }, 2780 | "pathval": { 2781 | "version": "1.1.1", 2782 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 2783 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 2784 | "dev": true 2785 | }, 2786 | "picomatch": { 2787 | "version": "2.3.1", 2788 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2789 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2790 | "dev": true 2791 | }, 2792 | "prelude-ls": { 2793 | "version": "1.2.1", 2794 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2795 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2796 | "dev": true 2797 | }, 2798 | "propagate": { 2799 | "version": "2.0.1", 2800 | "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", 2801 | "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", 2802 | "dev": true 2803 | }, 2804 | "punycode": { 2805 | "version": "2.1.1", 2806 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2807 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2808 | "dev": true 2809 | }, 2810 | "randombytes": { 2811 | "version": "2.1.0", 2812 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 2813 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 2814 | "dev": true, 2815 | "requires": { 2816 | "safe-buffer": "^5.1.0" 2817 | } 2818 | }, 2819 | "readdirp": { 2820 | "version": "3.6.0", 2821 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2822 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2823 | "dev": true, 2824 | "requires": { 2825 | "picomatch": "^2.2.1" 2826 | } 2827 | }, 2828 | "regexpp": { 2829 | "version": "3.2.0", 2830 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2831 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2832 | "dev": true 2833 | }, 2834 | "require-directory": { 2835 | "version": "2.1.1", 2836 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2837 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 2838 | "dev": true 2839 | }, 2840 | "resolve-from": { 2841 | "version": "4.0.0", 2842 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2843 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2844 | "dev": true 2845 | }, 2846 | "rimraf": { 2847 | "version": "3.0.2", 2848 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2849 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2850 | "dev": true, 2851 | "requires": { 2852 | "glob": "^7.1.3" 2853 | } 2854 | }, 2855 | "safe-buffer": { 2856 | "version": "5.2.1", 2857 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2858 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2859 | "dev": true 2860 | }, 2861 | "serialize-javascript": { 2862 | "version": "6.0.0", 2863 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 2864 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 2865 | "dev": true, 2866 | "requires": { 2867 | "randombytes": "^2.1.0" 2868 | } 2869 | }, 2870 | "shebang-command": { 2871 | "version": "2.0.0", 2872 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2873 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2874 | "dev": true, 2875 | "requires": { 2876 | "shebang-regex": "^3.0.0" 2877 | } 2878 | }, 2879 | "shebang-regex": { 2880 | "version": "3.0.0", 2881 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2882 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2883 | "dev": true 2884 | }, 2885 | "string-width": { 2886 | "version": "4.2.3", 2887 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2888 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2889 | "dev": true, 2890 | "requires": { 2891 | "emoji-regex": "^8.0.0", 2892 | "is-fullwidth-code-point": "^3.0.0", 2893 | "strip-ansi": "^6.0.1" 2894 | } 2895 | }, 2896 | "strip-ansi": { 2897 | "version": "6.0.1", 2898 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2899 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2900 | "dev": true, 2901 | "requires": { 2902 | "ansi-regex": "^5.0.1" 2903 | } 2904 | }, 2905 | "strip-json-comments": { 2906 | "version": "3.1.1", 2907 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2908 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2909 | "dev": true 2910 | }, 2911 | "supports-color": { 2912 | "version": "7.2.0", 2913 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2914 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2915 | "dev": true, 2916 | "requires": { 2917 | "has-flag": "^4.0.0" 2918 | } 2919 | }, 2920 | "text-table": { 2921 | "version": "0.2.0", 2922 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2923 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2924 | "dev": true 2925 | }, 2926 | "to-regex-range": { 2927 | "version": "5.0.1", 2928 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2929 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2930 | "dev": true, 2931 | "requires": { 2932 | "is-number": "^7.0.0" 2933 | } 2934 | }, 2935 | "type-check": { 2936 | "version": "0.4.0", 2937 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2938 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2939 | "dev": true, 2940 | "requires": { 2941 | "prelude-ls": "^1.2.1" 2942 | } 2943 | }, 2944 | "type-detect": { 2945 | "version": "4.0.8", 2946 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 2947 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 2948 | "dev": true 2949 | }, 2950 | "type-fest": { 2951 | "version": "0.20.2", 2952 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2953 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2954 | "dev": true 2955 | }, 2956 | "uri-js": { 2957 | "version": "4.4.1", 2958 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2959 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2960 | "dev": true, 2961 | "requires": { 2962 | "punycode": "^2.1.0" 2963 | } 2964 | }, 2965 | "v8-compile-cache": { 2966 | "version": "2.3.0", 2967 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2968 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2969 | "dev": true 2970 | }, 2971 | "web-streams-polyfill": { 2972 | "version": "3.2.0", 2973 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", 2974 | "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==" 2975 | }, 2976 | "which": { 2977 | "version": "2.0.2", 2978 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2979 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2980 | "dev": true, 2981 | "requires": { 2982 | "isexe": "^2.0.0" 2983 | } 2984 | }, 2985 | "word-wrap": { 2986 | "version": "1.2.3", 2987 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2988 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2989 | "dev": true 2990 | }, 2991 | "workerpool": { 2992 | "version": "6.2.0", 2993 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", 2994 | "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", 2995 | "dev": true 2996 | }, 2997 | "wrap-ansi": { 2998 | "version": "7.0.0", 2999 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 3000 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 3001 | "dev": true, 3002 | "requires": { 3003 | "ansi-styles": "^4.0.0", 3004 | "string-width": "^4.1.0", 3005 | "strip-ansi": "^6.0.0" 3006 | } 3007 | }, 3008 | "wrappy": { 3009 | "version": "1.0.2", 3010 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3011 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 3012 | "dev": true 3013 | }, 3014 | "ws": { 3015 | "version": "8.4.2", 3016 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", 3017 | "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", 3018 | "requires": {} 3019 | }, 3020 | "y18n": { 3021 | "version": "5.0.8", 3022 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 3023 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 3024 | "dev": true 3025 | }, 3026 | "yargs": { 3027 | "version": "16.2.0", 3028 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 3029 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 3030 | "dev": true, 3031 | "requires": { 3032 | "cliui": "^7.0.2", 3033 | "escalade": "^3.1.1", 3034 | "get-caller-file": "^2.0.5", 3035 | "require-directory": "^2.1.1", 3036 | "string-width": "^4.2.0", 3037 | "y18n": "^5.0.5", 3038 | "yargs-parser": "^20.2.2" 3039 | } 3040 | }, 3041 | "yargs-parser": { 3042 | "version": "20.2.4", 3043 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 3044 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 3045 | "dev": true 3046 | }, 3047 | "yargs-unparser": { 3048 | "version": "2.0.0", 3049 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 3050 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 3051 | "dev": true, 3052 | "requires": { 3053 | "camelcase": "^6.0.0", 3054 | "decamelize": "^4.0.0", 3055 | "flat": "^5.0.2", 3056 | "is-plain-obj": "^2.1.0" 3057 | } 3058 | }, 3059 | "yocto-queue": { 3060 | "version": "0.1.0", 3061 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 3062 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 3063 | "dev": true 3064 | } 3065 | } 3066 | } 3067 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pushbullet", 3 | "version": "3.0.0", 4 | "description": "Use PushBullets REST API", 5 | "main": "./lib/pushbullet.js", 6 | "type": "module", 7 | "scripts": { 8 | "lint": "./node_modules/.bin/eslint . *.cjs", 9 | "test": "./node_modules/.bin/mocha" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/alexwhitman/node-pushbullet-api" 14 | }, 15 | "keywords": [ 16 | "pushbullet", 17 | "api", 18 | "rest" 19 | ], 20 | "author": "Alex Whitman ", 21 | "license": "BSD", 22 | "dependencies": { 23 | "clone": "^2.1.2", 24 | "mime": "^3.0.0", 25 | "node-fetch": "^3.2.0", 26 | "node-forge": "^1.2.1", 27 | "ws": "^8.4.2" 28 | }, 29 | "devDependencies": { 30 | "chai": "^4.3.6", 31 | "eslint": "^8.8.0", 32 | "mocha": "^9.2.0", 33 | "nock": "^13.2.3" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/channels.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.createChannel()', () => { 14 | it('should create a channel', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .post('/channels', { 17 | tag : 'channel-tag', 18 | name : 'channel-name', 19 | description : 'channel-description', 20 | image_url : 'image-url', 21 | website_url : 'website-url', 22 | feed_url : 'feed-url', 23 | feed_filters : [{ 24 | field : 'title', 25 | operator : 'contains', 26 | value : 'test', 27 | ignore_case : 'true' 28 | }], 29 | subscribe : 'true' 30 | }) 31 | .reply(200, {}); 32 | 33 | const pb = new PushBullet(accessToken); 34 | const response = await pb.createChannel({ 35 | tag : 'channel-tag', 36 | name : 'channel-name', 37 | description : 'channel-description', 38 | image_url : 'image-url', 39 | website_url : 'website-url', 40 | feed_url : 'feed-url', 41 | feed_filters : [{ 42 | field : 'title', 43 | operator : 'contains', 44 | value : 'test', 45 | ignore_case : 'true' 46 | }], 47 | subscribe : 'true' 48 | }); 49 | response.status.should.equal(200); 50 | 51 | const j = await response.json(); 52 | j.should.be.an.an('object'); 53 | }); 54 | }); 55 | 56 | describe('PushBullet.channelInfo()', () => { 57 | it('should mute a chat', async () => { 58 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 59 | .get('/channel-info') 60 | .query({ tag : 'channel-tag' }) 61 | .reply(200, {}); 62 | 63 | const pb = new PushBullet(accessToken); 64 | const response = await pb.channelInfo('channel-tag'); 65 | response.status.should.equal(200); 66 | 67 | const j = await response.json(); 68 | j.should.be.an.an('object'); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /test/chats.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.chats()', () => { 14 | it('should request active chats', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .get('/chats') 17 | .query({ 18 | active : 'true' 19 | }) 20 | .reply(200, {}); 21 | 22 | const pb = new PushBullet(accessToken); 23 | const response = await pb.chats(); 24 | response.status.should.equal(200); 25 | 26 | const j = await response.json(); 27 | j.should.be.an.an('object'); 28 | }); 29 | 30 | it('should request chats with options', async () => { 31 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 32 | .get('/chats') 33 | .query({ 34 | active : 'false' 35 | }) 36 | .reply(200, {}); 37 | 38 | const pb = new PushBullet(accessToken); 39 | const response = await pb.chats({ 40 | active : false 41 | }); 42 | response.status.should.equal(200); 43 | 44 | const j = await response.json(); 45 | j.should.be.an.an('object'); 46 | }); 47 | }); 48 | 49 | describe('PushBullet.createChat()', () => { 50 | it('should create a chat', async () => { 51 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 52 | .post('/chats', { 53 | email : 'test@test.com' 54 | }) 55 | .reply(200, {}); 56 | 57 | const pb = new PushBullet(accessToken); 58 | const response = await pb.createChat('test@test.com'); 59 | response.status.should.equal(200); 60 | 61 | const j = await response.json(); 62 | j.should.be.an.an('object'); 63 | }); 64 | }); 65 | 66 | describe('PushBullet.muteChat()', () => { 67 | it('should mute a chat', async () => { 68 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 69 | .post('/chats/chat-iden', { 70 | muted : true 71 | }) 72 | .reply(200, {}); 73 | 74 | const pb = new PushBullet(accessToken); 75 | const response = await pb.muteChat('chat-iden'); 76 | response.status.should.equal(200); 77 | 78 | const j = await response.json(); 79 | j.should.be.an.an('object'); 80 | }); 81 | }); 82 | 83 | describe('PushBullet.unmuteChat()', () => { 84 | it('should mute a chat', async () => { 85 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 86 | .post('/chats/chat-iden', { 87 | muted : false 88 | }) 89 | .reply(200, {}); 90 | 91 | const pb = new PushBullet(accessToken); 92 | const response = await pb.unmuteChat('chat-iden'); 93 | response.status.should.equal(200); 94 | 95 | const j = await response.json(); 96 | j.should.be.an.an('object'); 97 | }); 98 | }); 99 | 100 | describe('PushBullet.deleteChat()', () => { 101 | it('should delete a chat', async () => { 102 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 103 | .delete('/chats/chat-iden') 104 | .reply(200, {}); 105 | 106 | const pb = new PushBullet(accessToken); 107 | const response = await pb.deleteChat('chat-iden'); 108 | response.status.should.equal(200); 109 | 110 | const j = await response.json(); 111 | j.should.be.an.an('object'); 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /test/devices.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.devices()', () => { 14 | it('should request active devices', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .get('/devices') 17 | .query({ 18 | active : 'true' 19 | }) 20 | .reply(200, {}); 21 | 22 | const pb = new PushBullet(accessToken); 23 | const response = await pb.devices(); 24 | response.status.should.equal(200); 25 | 26 | const j = await response.json(); 27 | j.should.be.an.an('object'); 28 | }); 29 | 30 | it('should request devices with options', async () => { 31 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 32 | .get('/devices') 33 | .query({ 34 | active : 'false' 35 | }) 36 | .reply(200, {}); 37 | 38 | const pb = new PushBullet(accessToken); 39 | const response = await pb.devices({ 40 | active : false 41 | }); 42 | response.status.should.equal(200); 43 | 44 | const j = await response.json(); 45 | j.should.be.an.an('object'); 46 | }); 47 | }); 48 | 49 | describe('PushBullet.createDevice()', () => { 50 | it('should create a device', async () => { 51 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 52 | .post('/devices', { 53 | nickname : 'device-nickname', 54 | model : 'device-model', 55 | has_sms : false 56 | }) 57 | .reply(200, {}); 58 | 59 | const pb = new PushBullet(accessToken); 60 | const response = await pb.createDevice({ 61 | nickname : 'device-nickname', 62 | model : 'device-model', 63 | has_sms : false 64 | }); 65 | response.status.should.equal(200); 66 | 67 | const j = await response.json(); 68 | j.should.be.an.an('object'); 69 | }); 70 | }); 71 | 72 | describe('PushBullet.updateDevice()', () => { 73 | it('should update a device', async () => { 74 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 75 | .post('/devices/device-iden', { 76 | nickname : 'device-nickname', 77 | model : 'device-model', 78 | has_sms : false 79 | }) 80 | .reply(200, {}); 81 | 82 | const pb = new PushBullet(accessToken); 83 | const response = await pb.updateDevice('device-iden', { 84 | nickname : 'device-nickname', 85 | model : 'device-model', 86 | has_sms : false 87 | }); 88 | response.status.should.equal(200); 89 | 90 | const j = await response.json(); 91 | j.should.be.an.an('object'); 92 | }); 93 | }); 94 | 95 | describe('PushBullet.deleteDevice()', () => { 96 | it('should update a device', async () => { 97 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 98 | .delete('/devices/device-iden') 99 | .reply(200, {}); 100 | 101 | const pb = new PushBullet(accessToken); 102 | const response = await pb.deleteDevice('device-iden'); 103 | response.status.should.equal(200); 104 | 105 | const j = await response.json(); 106 | j.should.be.an.an('object'); 107 | }); 108 | }); 109 | -------------------------------------------------------------------------------- /test/ephemerals.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.sendSMS()', () => { 14 | it('should send an SMS', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .post('/ephemerals', { 17 | type : 'push', 18 | push : { 19 | package_name : 'com.pushbullet.android', 20 | type : 'messaging_extension_reply', 21 | target_device_iden : 'target-device-iden', 22 | conversation_iden : 'conversation-iden', 23 | message : 'message' 24 | } 25 | }) 26 | .reply(200, {}); 27 | 28 | const pb = new PushBullet(accessToken); 29 | const response = await pb.sendSMS({ 30 | target_device_iden : 'target-device-iden', 31 | conversation_iden : 'conversation-iden', 32 | message : 'message' 33 | }); 34 | response.status.should.equal(200); 35 | 36 | const j = await response.json(); 37 | j.should.be.an.an('object'); 38 | }); 39 | }); 40 | 41 | describe('PushBullet.sendClipboard()', () => { 42 | it('should send clipboard content', async () => { 43 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 44 | .post('/ephemerals', { 45 | type : 'push', 46 | push : { 47 | type : 'clip', 48 | body : 'clipboard-content', 49 | source_user_iden : 'source-user-iden', 50 | source_device_iden : 'source-device-iden' 51 | } 52 | }) 53 | .reply(200, {}); 54 | 55 | const pb = new PushBullet(accessToken); 56 | const response = await pb.sendClipboard({ 57 | body : 'clipboard-content', 58 | source_user_iden : 'source-user-iden', 59 | source_device_iden : 'source-device-iden' 60 | }); 61 | response.status.should.equal(200); 62 | 63 | const j = await response.json(); 64 | j.should.be.an.an('object'); 65 | }); 66 | }); 67 | 68 | describe('PushBullet.dismissEphemeral()', () => { 69 | it('should dismiss an ephemeral', async () => { 70 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 71 | .post('/ephemerals', { 72 | type : 'push', 73 | push : { 74 | type : 'dismissal', 75 | package_name : 'package-name', 76 | notification_id : 'notification-id', 77 | notification_tag : 'notification-tag', 78 | source_user_iden : 'source-user-iden' 79 | } 80 | }) 81 | .reply(200, {}); 82 | 83 | const pb = new PushBullet(accessToken); 84 | const response = await pb.dismissEphemeral({ 85 | package_name : 'package-name', 86 | notification_id : 'notification-id', 87 | notification_tag : 'notification-tag', 88 | source_user_iden : 'source-user-iden' 89 | }); 90 | response.status.should.equal(200); 91 | 92 | const j = await response.json(); 93 | j.should.be.an.an('object'); 94 | }); 95 | }); 96 | 97 | describe('PushBullet.sendEphemeral() with encryption', () => { 98 | it('should send an encrypted ephemeral', async () => { 99 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 100 | .post('/ephemerals', { 101 | type : 'push', 102 | push : { 103 | ciphertext : /.+/i, 104 | encrypted : true 105 | } 106 | }) 107 | .reply(200, {}); 108 | 109 | const pb = new PushBullet(accessToken); 110 | pb.enableEncryption('password', 'user-iden'); 111 | const response = await pb.sendEphemeral({ 112 | option1 : 'option1', 113 | option2 : 'option2' 114 | }); 115 | response.status.should.equal(200); 116 | 117 | const j = await response.json(); 118 | j.should.be.an.an('object'); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /test/pushes.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import { fileURLToPath } from 'url'; 4 | import nock from 'nock'; 5 | import PushBullet from '../lib/pushbullet.js'; 6 | import { should } from 'chai'; 7 | should(); 8 | 9 | const accessToken = 'test-access-token'; 10 | const requestHeaders = { 11 | 'Access-Token' : accessToken 12 | }; 13 | 14 | describe('PushBullet.note()', () => { 15 | it('should push a note', async () => { 16 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 17 | .post('/pushes', { 18 | device_iden : 'device-iden', 19 | type : 'note', 20 | title : 'note-title', 21 | body : 'note-body' 22 | }) 23 | .reply(200, {}); 24 | 25 | const pb = new PushBullet(accessToken); 26 | const response = await pb.note('device-iden', 'note-title', 'note-body'); 27 | response.status.should.equal(200); 28 | 29 | const j = await response.json(); 30 | j.should.be.an.an('object'); 31 | }); 32 | }); 33 | 34 | describe('PushBullet.link()', () => { 35 | it('should push a link', async () => { 36 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 37 | .post('/pushes', { 38 | device_iden : 'device-iden', 39 | type : 'link', 40 | title : 'link-title', 41 | url : 'link-url', 42 | body : 'link-body' 43 | }) 44 | .reply(200, {}); 45 | 46 | const pb = new PushBullet(accessToken); 47 | const response = await pb.link('device-iden', 'link-title', 'link-url', 'link-body'); 48 | response.status.should.equal(200); 49 | 50 | const j = await response.json(); 51 | j.should.be.an.an('object'); 52 | }); 53 | }); 54 | 55 | describe('PushBullet.file()', () => { 56 | it('should push a file', async () => { 57 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 58 | .post('/upload-request', { 59 | file_name : 'pushes.js', 60 | file_type : 'application/javascript' 61 | }) 62 | .reply(200, { 63 | file_url : 'https://dl.pushbulletusercontent.com/some-hash/pushes.js', 64 | upload_url : 'https://upload.pushbullet.com/upload-legacy/some-hash' 65 | }); 66 | 67 | const uploadHeaders = { 68 | 'Content-Type' : headerValue => headerValue.startsWith('multipart/form-data; boundary') 69 | }; 70 | 71 | nock('https://upload.pushbullet.com', { reqheaders : uploadHeaders }) 72 | .post('/upload-legacy/some-hash', /.*Content-Disposition: form-data;.*/gi) 73 | .reply(204); 74 | 75 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 76 | .post('/pushes', { 77 | device_iden : 'device-iden', 78 | type : 'file', 79 | file_name : 'pushes.js', 80 | file_type : 'application/javascript', 81 | file_url : 'https://dl.pushbulletusercontent.com/some-hash/pushes.js', 82 | body : 'file-body' 83 | }) 84 | .reply(200, {}); 85 | 86 | const pb = new PushBullet(accessToken); 87 | const response = await pb.file('device-iden', fileURLToPath(import.meta.url), 'file-body'); 88 | response.status.should.equal(200); 89 | 90 | const j = await response.json(); 91 | j.should.be.an.an('object'); 92 | }); 93 | }); 94 | 95 | describe('PushBullet.history()', () => { 96 | it('should request push history', async () => { 97 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 98 | .get('/pushes') 99 | .query({ 100 | active : 'true', 101 | modified_after : '0' 102 | }) 103 | .reply(200, {}); 104 | 105 | const pb = new PushBullet(accessToken); 106 | const response = await pb.history(); 107 | response.status.should.equal(200); 108 | 109 | const j = await response.json(); 110 | j.should.be.an.an('object'); 111 | }); 112 | 113 | it('should request push history with options', async () => { 114 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 115 | .get('/pushes') 116 | .query({ 117 | active : 'false', 118 | modified_after : '123', 119 | cursor : 'some-cursor', 120 | limit : '10' 121 | }) 122 | .reply(200, {}); 123 | 124 | const pb = new PushBullet(accessToken); 125 | const response = await pb.history({ 126 | active : false, 127 | modified_after : 123, 128 | cursor : 'some-cursor', 129 | limit : 10 130 | }); 131 | response.status.should.equal(200); 132 | 133 | const j = await response.json(); 134 | j.should.be.an.an('object'); 135 | }); 136 | }); 137 | 138 | describe('PushBullet.dismissPush()', () => { 139 | it('should dismiss a push', async () => { 140 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 141 | .post('/pushes/push-iden', { 142 | dismissed : true 143 | }) 144 | .reply(200, {}); 145 | 146 | const pb = new PushBullet(accessToken); 147 | const response = await pb.dismissPush('push-iden'); 148 | response.status.should.equal(200); 149 | 150 | const j = await response.json(); 151 | j.should.be.an.an('object'); 152 | }); 153 | }); 154 | 155 | describe('PushBullet.deletePush()', () => { 156 | it('should delete a push', async () => { 157 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 158 | .delete('/pushes/push-iden') 159 | .reply(200, {}); 160 | 161 | const pb = new PushBullet(accessToken); 162 | const response = await pb.deletePush('push-iden'); 163 | response.status.should.equal(200); 164 | 165 | const j = await response.json(); 166 | j.should.be.an.an('object'); 167 | }); 168 | }); 169 | 170 | describe('PushBullet.deleteAllPushes()', () => { 171 | it('should delete all pushes', async () => { 172 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 173 | .delete('/pushes') 174 | .reply(200, {}); 175 | 176 | const pb = new PushBullet(accessToken); 177 | const response = await pb.deleteAllPushes(); 178 | response.status.should.equal(200); 179 | 180 | const j = await response.json(); 181 | j.should.be.an.an('object'); 182 | }); 183 | }); 184 | -------------------------------------------------------------------------------- /test/subscriptions.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.subscriptions()', () => { 14 | it('should request active subscriptions', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .get('/subscriptions') 17 | .query({ 18 | active : 'true' 19 | }) 20 | .reply(200, {}); 21 | 22 | const pb = new PushBullet(accessToken); 23 | const response = await pb.subscriptions(); 24 | response.status.should.equal(200); 25 | 26 | const j = await response.json(); 27 | j.should.be.an.an('object'); 28 | }); 29 | 30 | it('should request subscriptions with options', async () => { 31 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 32 | .get('/subscriptions') 33 | .query({ 34 | active : 'false' 35 | }) 36 | .reply(200, {}); 37 | 38 | const pb = new PushBullet(accessToken); 39 | const response = await pb.subscriptions({ 40 | active : false 41 | }); 42 | response.status.should.equal(200); 43 | 44 | const j = await response.json(); 45 | j.should.be.an.an('object'); 46 | }); 47 | }); 48 | 49 | describe('PushBullet.subscribe()', () => { 50 | it('should subscribe to a channel', async () => { 51 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 52 | .post('/subscriptions', { 53 | channel_tag : 'channel-tag' 54 | }) 55 | .reply(200, {}); 56 | 57 | const pb = new PushBullet(accessToken); 58 | const response = await pb.subscribe('channel-tag'); 59 | response.status.should.equal(200); 60 | 61 | const j = await response.json(); 62 | j.should.be.an.an('object'); 63 | }); 64 | }); 65 | 66 | describe('PushBullet.unsubscribe()', () => { 67 | it('should unsubscribe to a channel', async () => { 68 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 69 | .delete('/subscriptions/subscription-iden') 70 | .reply(200, {}); 71 | 72 | const pb = new PushBullet(accessToken); 73 | const response = await pb.unsubscribe('subscription-iden'); 74 | response.status.should.equal(200); 75 | 76 | const j = await response.json(); 77 | j.should.be.an.an('object'); 78 | }); 79 | }); 80 | 81 | describe('PushBullet.muteSubscription()', () => { 82 | it('should mute a chat', async () => { 83 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 84 | .post('/subscriptions/subscription-iden', { 85 | muted : true 86 | }) 87 | .reply(200, {}); 88 | 89 | const pb = new PushBullet(accessToken); 90 | const response = await pb.muteSubscription('subscription-iden'); 91 | response.status.should.equal(200); 92 | 93 | const j = await response.json(); 94 | j.should.be.an.an('object'); 95 | }); 96 | }); 97 | 98 | describe('PushBullet.unmuteSubscription()', () => { 99 | it('should mute a chat', async () => { 100 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 101 | .post('/subscriptions/subscription-iden', { 102 | muted : false 103 | }) 104 | .reply(200, {}); 105 | 106 | const pb = new PushBullet(accessToken); 107 | const response = await pb.unmuteSubscription('subscription-iden'); 108 | response.status.should.equal(200); 109 | 110 | const j = await response.json(); 111 | j.should.be.an.an('object'); 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /test/texts.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.createText()', () => { 14 | it('should create a text', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .post('/texts', { 17 | data : { 18 | target_device_iden : 'device-iden', 19 | addresses : [ '123-456-789' ], 20 | message : 'text-message', 21 | file_type : 'type-of-file' 22 | }, 23 | file_url : 'url-to-file' 24 | }) 25 | .reply(200, {}); 26 | 27 | const pb = new PushBullet(accessToken); 28 | const response = await pb.createText('device-iden', '123-456-789', 'text-message', { 29 | file_url : 'url-to-file', 30 | file_type : 'type-of-file' 31 | }); 32 | response.status.should.equal(200); 33 | 34 | const j = await response.json(); 35 | j.should.be.an.an('object'); 36 | }); 37 | }); 38 | 39 | describe('PushBullet.updateText()', () => { 40 | it('should update a text', async () => { 41 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 42 | .post('/texts/text-iden', { 43 | data : { 44 | message : 'updated-message' 45 | } 46 | }) 47 | .reply(200, {}); 48 | 49 | const pb = new PushBullet(accessToken); 50 | const response = await pb.updateText('text-iden', { 51 | data : { 52 | message : 'updated-message' 53 | } 54 | }); 55 | response.status.should.equal(200); 56 | 57 | const j = await response.json(); 58 | j.should.be.an.an('object'); 59 | }); 60 | }); 61 | 62 | describe('PushBullet.deleteText()', () => { 63 | it('should delete a chat', async () => { 64 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 65 | .delete('/texts/text-iden') 66 | .reply(200, {}); 67 | 68 | const pb = new PushBullet(accessToken); 69 | const response = await pb.deleteText('text-iden'); 70 | response.status.should.equal(200); 71 | 72 | const j = await response.json(); 73 | j.should.be.an.an('object'); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /test/users.js: -------------------------------------------------------------------------------- 1 | /* global describe,it */ 2 | 3 | import nock from 'nock'; 4 | import PushBullet from '../lib/pushbullet.js'; 5 | import { should } from 'chai'; 6 | should(); 7 | 8 | const accessToken = 'test-access-token'; 9 | const requestHeaders = { 10 | 'Access-Token' : accessToken 11 | }; 12 | 13 | describe('PushBullet.me()', () => { 14 | it('should request user details', async () => { 15 | nock(PushBullet.API_BASE, { reqheaders : requestHeaders }) 16 | .get('/users/me') 17 | .reply(200, {}); 18 | 19 | const pb = new PushBullet(accessToken); 20 | const response = await pb.me(); 21 | response.status.should.equal(200); 22 | 23 | const j = await response.json(); 24 | j.should.be.an.an('object'); 25 | }); 26 | }); 27 | --------------------------------------------------------------------------------