├── .eslintrc.js ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── appveyor.yml ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── src ├── class-style │ ├── BaseAction.ts │ └── decorator.ts ├── device.ts ├── dynamic-view │ └── DynamicView.ts ├── index.ts ├── types │ ├── events.ts │ └── interfaces.ts └── util │ ├── constant.ts │ └── image-helper.ts ├── tests ├── dev-index.ts ├── image.png ├── index.ts ├── stream-deck-mock.ts ├── test-action-mock.ts └── tsconfig.json └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: [ 5 | '@typescript-eslint', 6 | ], 7 | rules: { 8 | "@typescript-eslint/no-explicit-any": "off" 9 | }, 10 | extends: [ 11 | 'eslint:recommended', 12 | 'plugin:@typescript-eslint/recommended', 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: fcannizzaro 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/webstorm+all,node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=webstorm+all,node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | .pnpm-debug.log* 14 | 15 | # Diagnostic reports (https://nodejs.org/api/report.html) 16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 17 | 18 | # Runtime data 19 | pids 20 | *.pid 21 | *.seed 22 | *.pid.lock 23 | 24 | # Directory for instrumented libs generated by jscoverage/JSCover 25 | lib-cov 26 | 27 | # Coverage directory used by tools like istanbul 28 | coverage 29 | *.lcov 30 | 31 | # nyc test coverage 32 | .nyc_output 33 | 34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Bower dependency directory (https://bower.io/) 38 | bower_components 39 | 40 | # node-waf configuration 41 | .lock-wscript 42 | 43 | # Compiled binary addons (https://nodejs.org/api/addons.html) 44 | build/Release 45 | 46 | # Dependency directories 47 | node_modules/ 48 | jspm_packages/ 49 | 50 | # Snowpack dependency directory (https://snowpack.dev/) 51 | web_modules/ 52 | 53 | # TypeScript cache 54 | *.tsbuildinfo 55 | 56 | # Optional npm cache directory 57 | .npm 58 | 59 | # Optional eslint cache 60 | .eslintcache 61 | 62 | # Microbundle cache 63 | .rpt2_cache/ 64 | .rts2_cache_cjs/ 65 | .rts2_cache_es/ 66 | .rts2_cache_umd/ 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # Output of 'npm pack' 72 | *.tgz 73 | 74 | # Yarn Integrity file 75 | .yarn-integrity 76 | 77 | # dotenv environment variables file 78 | .env 79 | .env.test 80 | .env.production 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # Serverless directories 104 | .serverless/ 105 | 106 | # FuseBox cache 107 | .fusebox/ 108 | 109 | # DynamoDB Local files 110 | .dynamodb/ 111 | 112 | # TernJS port file 113 | .tern-port 114 | 115 | # Stores VSCode versions used for testing VSCode extensions 116 | .vscode-test 117 | 118 | # yarn v2 119 | .yarn/cache 120 | .yarn/unplugged 121 | .yarn/build-state.yml 122 | .yarn/install-state.gz 123 | .pnp.* 124 | 125 | ### Node Patch ### 126 | # Serverless Webpack directories 127 | .webpack/ 128 | 129 | # Optional stylelint cache 130 | .stylelintcache 131 | 132 | # SvelteKit build / generate output 133 | .svelte-kit 134 | 135 | ### WebStorm+all ### 136 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 137 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 138 | 139 | # User-specific stuff 140 | .idea/**/workspace.xml 141 | .idea/**/tasks.xml 142 | .idea/**/usage.statistics.xml 143 | .idea/**/dictionaries 144 | .idea/**/shelf 145 | 146 | # AWS User-specific 147 | .idea/**/aws.xml 148 | 149 | # Generated files 150 | .idea/**/contentModel.xml 151 | 152 | # Sensitive or high-churn files 153 | .idea/**/dataSources/ 154 | .idea/**/dataSources.ids 155 | .idea/**/dataSources.local.xml 156 | .idea/**/sqlDataSources.xml 157 | .idea/**/dynamic.xml 158 | .idea/**/uiDesigner.xml 159 | .idea/**/dbnavigator.xml 160 | 161 | # Gradle 162 | .idea/**/gradle.xml 163 | .idea/**/libraries 164 | 165 | # Gradle and Maven with auto-import 166 | # When using Gradle or Maven with auto-import, you should exclude module files, 167 | # since they will be recreated, and may cause churn. Uncomment if using 168 | # auto-import. 169 | # .idea/artifacts 170 | # .idea/compiler.xml 171 | # .idea/jarRepositories.xml 172 | # .idea/modules.xml 173 | # .idea/*.iml 174 | # .idea/modules 175 | # *.iml 176 | # *.ipr 177 | 178 | # CMake 179 | cmake-build-*/ 180 | 181 | # Mongo Explorer plugin 182 | .idea/**/mongoSettings.xml 183 | 184 | # File-based project format 185 | *.iws 186 | 187 | # IntelliJ 188 | out/ 189 | 190 | # mpeltonen/sbt-idea plugin 191 | .idea_modules/ 192 | 193 | # JIRA plugin 194 | atlassian-ide-plugin.xml 195 | 196 | # Cursive Clojure plugin 197 | .idea/replstate.xml 198 | 199 | # Crashlytics plugin (for Android Studio and IntelliJ) 200 | com_crashlytics_export_strings.xml 201 | crashlytics.properties 202 | crashlytics-build.properties 203 | fabric.properties 204 | 205 | # Editor-based Rest Client 206 | .idea/httpRequests 207 | 208 | # Android studio 3.1+ serialized cache file 209 | .idea/caches/build_file_checksums.ser 210 | 211 | ### WebStorm+all Patch ### 212 | # Ignores the whole .idea folder and all .iml files 213 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 214 | 215 | .idea/ 216 | 217 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 218 | 219 | *.iml 220 | modules.xml 221 | .idea/misc.xml 222 | *.ipr 223 | 224 | # Sonarlint plugin 225 | .idea/sonarlint 226 | 227 | # End of https://www.toptal.com/developers/gitignore/api/webstorm+all,node 228 | 229 | # OTHER 230 | lib/ 231 | dist/ 232 | .pkg-cache 233 | *.exe 234 | yarn.lock 235 | 236 | !debug-plugin/dist 237 | !debug-plugin/dist/* 238 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "none", 4 | "singleQuote": true, 5 | "printWidth": 80 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Elgato released an official Node.js sdk](https://github.com/elgatosf/streamdeck) 2 | > Now they support Node.js plugins, hot reload and more. 3 | > 4 | > _This project is now archived_ 5 | 6 | ------ 7 | 8 | 9 |

Elgato Stream Deck SDK

10 |

Unofficial Node.js SDK

11 |

12 | 13 | 14 | 15 |

16 | 17 | # Library Features 18 | 19 | - Allow the creation and building of a Node.js plugin (not everything can be done with the internal JavaScript in the 20 | Stream Deck App) 21 | - Strictly typed 22 | - Simplify the plugin's development 23 | - Auto-populate the plugin settings 24 | - Single / double taps and long press managed events 25 | - Automatically handles image url, file or Base64 images 26 | - Easy debugging + development (no stream deck application's reload necessary!) 27 | - Per action class development (not worry about checking every time the action UUID) 28 | 29 | ## Samples 30 | 31 | There are different types of sample (in the directory `/sample`), written in JavaScript and TypeScript and also a built 32 | plugin. 33 | 34 | ## Documentation 35 | 36 | You can read the full documentation at https://stream-deck-for-node.netlify.app 37 | 38 | ## TODO 39 | 40 | - Testing on **Mac** 41 | 42 | ## Changelog 43 | 44 | ### 1.0 (12/2021) 45 | 46 | An initial sdk version is released 47 | 48 | ## Inspiration 49 | 50 | I took my inspiration from [streamdeck-tools](https://github.com/BarRaider/streamdeck-tools) 51 | of [BarRaider](https://github.com/BarRaider), but I don't really like `C#`... so I created a tool to execute on-fly Node.js 52 | script through a binary executable or a full node packaged app. 53 | 54 | ## Author 55 | 56 | Francesco Saverio Cannizzaro ([fcannizzaro](https://github.com/fcannizzaro)) 57 | 58 | ## License 59 | 60 | GPL-3.0 61 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | nodejs_version: "16" 3 | 4 | # Install scripts. (runs after repo cloning) 5 | install: 6 | # Get the latest stable version of Node.js or io.js 7 | - ps: Install-Product node $env:nodejs_version 8 | # install modules 9 | - npm install 10 | 11 | build_script: 12 | - npm run build 13 | - npm run test 14 | - npm run test:coverage 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@stream-deck-for-node/sdk", 3 | "version": "1.0.15", 4 | "description": "Unofficial Elgato Stream Deck SDK for Node.js", 5 | "author": "Francesco Saverio Cannizzaro (fcannizzaro)", 6 | "dependencies": { 7 | "axios": "^0.24.0", 8 | "command-line-args": "^5.2.0", 9 | "mime-types": "^2.1.34", 10 | "rxjs": "^7.5.5", 11 | "ws": "^8.3.0" 12 | }, 13 | "homepage": "https://stream-deck-for-node.netlify.app", 14 | "repository": "github:stream-deck-for-node/sdk", 15 | "main": "./lib/index.js", 16 | "types": "./lib/index.d.ts", 17 | "license": "GPL-3.0", 18 | "scripts": { 19 | "prepublish": "npm run build", 20 | "test": "mocha -r ts-node/register tests/index.ts tests/dev-index.ts --exit", 21 | "test:coverage": "nyc mocha -r ts-node/register tests/index.ts tests/dev-index.ts --exit", 22 | "build": "tsc --outDir lib" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "files": [ 28 | "src", 29 | "package.json", 30 | "lib/**/*.ts", 31 | "lib/**/*.js", 32 | "README.md", 33 | "LICENSE", 34 | "tsconfig.json" 35 | ], 36 | "keywords": [ 37 | "stream-deck", 38 | "stream-deck-plugin", 39 | "sdk", 40 | "elgato" 41 | ], 42 | "devDependencies": { 43 | "@types/chai": "^4.3.0", 44 | "@types/chai-spies": "^1.0.3", 45 | "@types/command-line-args": "^5.2.0", 46 | "@types/mime-types": "^2.1.1", 47 | "@types/mocha": "^9.0.0", 48 | "@types/node": "^16.11.12", 49 | "@types/ws": "^8.2.2", 50 | "@typescript-eslint/eslint-plugin": "^5.8.1", 51 | "@typescript-eslint/parser": "^5.8.1", 52 | "chai": "^4.3.4", 53 | "chai-spies": "^1.0.0", 54 | "eslint": "^8.5.0", 55 | "mocha": "^9.1.3", 56 | "nyc": "^15.1.0", 57 | "prettier": "^2.5.1", 58 | "ts-node": "^10.4.0", 59 | "typescript": "^4.5.4" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | '@types/chai': ^4.3.0 5 | '@types/chai-spies': ^1.0.3 6 | '@types/command-line-args': ^5.2.0 7 | '@types/mime-types': ^2.1.1 8 | '@types/mocha': ^9.0.0 9 | '@types/node': ^16.11.12 10 | '@types/ws': ^8.2.2 11 | '@typescript-eslint/eslint-plugin': ^5.8.1 12 | '@typescript-eslint/parser': ^5.8.1 13 | axios: ^0.24.0 14 | chai: ^4.3.4 15 | chai-spies: ^1.0.0 16 | command-line-args: ^5.2.0 17 | eslint: ^8.5.0 18 | mime-types: ^2.1.34 19 | mocha: ^9.1.3 20 | nyc: ^15.1.0 21 | prettier: ^2.5.1 22 | rxjs: ^7.5.5 23 | ts-node: ^10.4.0 24 | typescript: ^4.5.4 25 | ws: ^8.3.0 26 | 27 | dependencies: 28 | axios: 0.24.0 29 | command-line-args: 5.2.1 30 | mime-types: 2.1.35 31 | rxjs: 7.5.5 32 | ws: 8.8.0 33 | 34 | devDependencies: 35 | '@types/chai': 4.3.1 36 | '@types/chai-spies': 1.0.3 37 | '@types/command-line-args': 5.2.0 38 | '@types/mime-types': 2.1.1 39 | '@types/mocha': 9.1.1 40 | '@types/node': 16.11.39 41 | '@types/ws': 8.5.3 42 | '@typescript-eslint/eslint-plugin': 5.27.1_aq7uryhocdbvbqum33pitcm3y4 43 | '@typescript-eslint/parser': 5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4 44 | chai: 4.3.6 45 | chai-spies: 1.0.0_chai@4.3.6 46 | eslint: 8.17.0 47 | mocha: 9.2.2 48 | nyc: 15.1.0 49 | prettier: 2.6.2 50 | ts-node: 10.8.1_pjlhwcktroxhni6x7uirug5lya 51 | typescript: 4.7.3 52 | 53 | packages: 54 | 55 | /@ampproject/remapping/2.2.0: 56 | resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} 57 | engines: {node: '>=6.0.0'} 58 | dependencies: 59 | '@jridgewell/gen-mapping': 0.1.1 60 | '@jridgewell/trace-mapping': 0.3.13 61 | dev: true 62 | 63 | /@babel/code-frame/7.16.7: 64 | resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} 65 | engines: {node: '>=6.9.0'} 66 | dependencies: 67 | '@babel/highlight': 7.17.12 68 | dev: true 69 | 70 | /@babel/compat-data/7.17.10: 71 | resolution: {integrity: sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==} 72 | engines: {node: '>=6.9.0'} 73 | dev: true 74 | 75 | /@babel/core/7.18.2: 76 | resolution: {integrity: sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==} 77 | engines: {node: '>=6.9.0'} 78 | dependencies: 79 | '@ampproject/remapping': 2.2.0 80 | '@babel/code-frame': 7.16.7 81 | '@babel/generator': 7.18.2 82 | '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 83 | '@babel/helper-module-transforms': 7.18.0 84 | '@babel/helpers': 7.18.2 85 | '@babel/parser': 7.18.4 86 | '@babel/template': 7.16.7 87 | '@babel/traverse': 7.18.2 88 | '@babel/types': 7.18.4 89 | convert-source-map: 1.8.0 90 | debug: 4.3.4 91 | gensync: 1.0.0-beta.2 92 | json5: 2.2.1 93 | semver: 6.3.0 94 | transitivePeerDependencies: 95 | - supports-color 96 | dev: true 97 | 98 | /@babel/generator/7.18.2: 99 | resolution: {integrity: sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==} 100 | engines: {node: '>=6.9.0'} 101 | dependencies: 102 | '@babel/types': 7.18.4 103 | '@jridgewell/gen-mapping': 0.3.1 104 | jsesc: 2.5.2 105 | dev: true 106 | 107 | /@babel/helper-compilation-targets/7.18.2_@babel+core@7.18.2: 108 | resolution: {integrity: sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==} 109 | engines: {node: '>=6.9.0'} 110 | peerDependencies: 111 | '@babel/core': ^7.0.0 112 | dependencies: 113 | '@babel/compat-data': 7.17.10 114 | '@babel/core': 7.18.2 115 | '@babel/helper-validator-option': 7.16.7 116 | browserslist: 4.20.4 117 | semver: 6.3.0 118 | dev: true 119 | 120 | /@babel/helper-environment-visitor/7.18.2: 121 | resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==} 122 | engines: {node: '>=6.9.0'} 123 | dev: true 124 | 125 | /@babel/helper-function-name/7.17.9: 126 | resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} 127 | engines: {node: '>=6.9.0'} 128 | dependencies: 129 | '@babel/template': 7.16.7 130 | '@babel/types': 7.18.4 131 | dev: true 132 | 133 | /@babel/helper-hoist-variables/7.16.7: 134 | resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} 135 | engines: {node: '>=6.9.0'} 136 | dependencies: 137 | '@babel/types': 7.18.4 138 | dev: true 139 | 140 | /@babel/helper-module-imports/7.16.7: 141 | resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} 142 | engines: {node: '>=6.9.0'} 143 | dependencies: 144 | '@babel/types': 7.18.4 145 | dev: true 146 | 147 | /@babel/helper-module-transforms/7.18.0: 148 | resolution: {integrity: sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==} 149 | engines: {node: '>=6.9.0'} 150 | dependencies: 151 | '@babel/helper-environment-visitor': 7.18.2 152 | '@babel/helper-module-imports': 7.16.7 153 | '@babel/helper-simple-access': 7.18.2 154 | '@babel/helper-split-export-declaration': 7.16.7 155 | '@babel/helper-validator-identifier': 7.16.7 156 | '@babel/template': 7.16.7 157 | '@babel/traverse': 7.18.2 158 | '@babel/types': 7.18.4 159 | transitivePeerDependencies: 160 | - supports-color 161 | dev: true 162 | 163 | /@babel/helper-simple-access/7.18.2: 164 | resolution: {integrity: sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==} 165 | engines: {node: '>=6.9.0'} 166 | dependencies: 167 | '@babel/types': 7.18.4 168 | dev: true 169 | 170 | /@babel/helper-split-export-declaration/7.16.7: 171 | resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} 172 | engines: {node: '>=6.9.0'} 173 | dependencies: 174 | '@babel/types': 7.18.4 175 | dev: true 176 | 177 | /@babel/helper-validator-identifier/7.16.7: 178 | resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} 179 | engines: {node: '>=6.9.0'} 180 | dev: true 181 | 182 | /@babel/helper-validator-option/7.16.7: 183 | resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} 184 | engines: {node: '>=6.9.0'} 185 | dev: true 186 | 187 | /@babel/helpers/7.18.2: 188 | resolution: {integrity: sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==} 189 | engines: {node: '>=6.9.0'} 190 | dependencies: 191 | '@babel/template': 7.16.7 192 | '@babel/traverse': 7.18.2 193 | '@babel/types': 7.18.4 194 | transitivePeerDependencies: 195 | - supports-color 196 | dev: true 197 | 198 | /@babel/highlight/7.17.12: 199 | resolution: {integrity: sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==} 200 | engines: {node: '>=6.9.0'} 201 | dependencies: 202 | '@babel/helper-validator-identifier': 7.16.7 203 | chalk: 2.4.2 204 | js-tokens: 4.0.0 205 | dev: true 206 | 207 | /@babel/parser/7.18.4: 208 | resolution: {integrity: sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==} 209 | engines: {node: '>=6.0.0'} 210 | hasBin: true 211 | dependencies: 212 | '@babel/types': 7.18.4 213 | dev: true 214 | 215 | /@babel/template/7.16.7: 216 | resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} 217 | engines: {node: '>=6.9.0'} 218 | dependencies: 219 | '@babel/code-frame': 7.16.7 220 | '@babel/parser': 7.18.4 221 | '@babel/types': 7.18.4 222 | dev: true 223 | 224 | /@babel/traverse/7.18.2: 225 | resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==} 226 | engines: {node: '>=6.9.0'} 227 | dependencies: 228 | '@babel/code-frame': 7.16.7 229 | '@babel/generator': 7.18.2 230 | '@babel/helper-environment-visitor': 7.18.2 231 | '@babel/helper-function-name': 7.17.9 232 | '@babel/helper-hoist-variables': 7.16.7 233 | '@babel/helper-split-export-declaration': 7.16.7 234 | '@babel/parser': 7.18.4 235 | '@babel/types': 7.18.4 236 | debug: 4.3.4 237 | globals: 11.12.0 238 | transitivePeerDependencies: 239 | - supports-color 240 | dev: true 241 | 242 | /@babel/types/7.18.4: 243 | resolution: {integrity: sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==} 244 | engines: {node: '>=6.9.0'} 245 | dependencies: 246 | '@babel/helper-validator-identifier': 7.16.7 247 | to-fast-properties: 2.0.0 248 | dev: true 249 | 250 | /@cspotcode/source-map-support/0.8.1: 251 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 252 | engines: {node: '>=12'} 253 | dependencies: 254 | '@jridgewell/trace-mapping': 0.3.9 255 | dev: true 256 | 257 | /@eslint/eslintrc/1.3.0: 258 | resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} 259 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 260 | dependencies: 261 | ajv: 6.12.6 262 | debug: 4.3.4 263 | espree: 9.3.2 264 | globals: 13.15.0 265 | ignore: 5.2.0 266 | import-fresh: 3.3.0 267 | js-yaml: 4.1.0 268 | minimatch: 3.1.2 269 | strip-json-comments: 3.1.1 270 | transitivePeerDependencies: 271 | - supports-color 272 | dev: true 273 | 274 | /@humanwhocodes/config-array/0.9.5: 275 | resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} 276 | engines: {node: '>=10.10.0'} 277 | dependencies: 278 | '@humanwhocodes/object-schema': 1.2.1 279 | debug: 4.3.4 280 | minimatch: 3.1.2 281 | transitivePeerDependencies: 282 | - supports-color 283 | dev: true 284 | 285 | /@humanwhocodes/object-schema/1.2.1: 286 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 287 | dev: true 288 | 289 | /@istanbuljs/load-nyc-config/1.1.0: 290 | resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} 291 | engines: {node: '>=8'} 292 | dependencies: 293 | camelcase: 5.3.1 294 | find-up: 4.1.0 295 | get-package-type: 0.1.0 296 | js-yaml: 3.14.1 297 | resolve-from: 5.0.0 298 | dev: true 299 | 300 | /@istanbuljs/schema/0.1.3: 301 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} 302 | engines: {node: '>=8'} 303 | dev: true 304 | 305 | /@jridgewell/gen-mapping/0.1.1: 306 | resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} 307 | engines: {node: '>=6.0.0'} 308 | dependencies: 309 | '@jridgewell/set-array': 1.1.1 310 | '@jridgewell/sourcemap-codec': 1.4.13 311 | dev: true 312 | 313 | /@jridgewell/gen-mapping/0.3.1: 314 | resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==} 315 | engines: {node: '>=6.0.0'} 316 | dependencies: 317 | '@jridgewell/set-array': 1.1.1 318 | '@jridgewell/sourcemap-codec': 1.4.13 319 | '@jridgewell/trace-mapping': 0.3.13 320 | dev: true 321 | 322 | /@jridgewell/resolve-uri/3.0.7: 323 | resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} 324 | engines: {node: '>=6.0.0'} 325 | dev: true 326 | 327 | /@jridgewell/set-array/1.1.1: 328 | resolution: {integrity: sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==} 329 | engines: {node: '>=6.0.0'} 330 | dev: true 331 | 332 | /@jridgewell/sourcemap-codec/1.4.13: 333 | resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} 334 | dev: true 335 | 336 | /@jridgewell/trace-mapping/0.3.13: 337 | resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} 338 | dependencies: 339 | '@jridgewell/resolve-uri': 3.0.7 340 | '@jridgewell/sourcemap-codec': 1.4.13 341 | dev: true 342 | 343 | /@jridgewell/trace-mapping/0.3.9: 344 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 345 | dependencies: 346 | '@jridgewell/resolve-uri': 3.0.7 347 | '@jridgewell/sourcemap-codec': 1.4.13 348 | dev: true 349 | 350 | /@nodelib/fs.scandir/2.1.5: 351 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 352 | engines: {node: '>= 8'} 353 | dependencies: 354 | '@nodelib/fs.stat': 2.0.5 355 | run-parallel: 1.2.0 356 | dev: true 357 | 358 | /@nodelib/fs.stat/2.0.5: 359 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 360 | engines: {node: '>= 8'} 361 | dev: true 362 | 363 | /@nodelib/fs.walk/1.2.8: 364 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 365 | engines: {node: '>= 8'} 366 | dependencies: 367 | '@nodelib/fs.scandir': 2.1.5 368 | fastq: 1.13.0 369 | dev: true 370 | 371 | /@tsconfig/node10/1.0.8: 372 | resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} 373 | dev: true 374 | 375 | /@tsconfig/node12/1.0.9: 376 | resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} 377 | dev: true 378 | 379 | /@tsconfig/node14/1.0.1: 380 | resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} 381 | dev: true 382 | 383 | /@tsconfig/node16/1.0.2: 384 | resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} 385 | dev: true 386 | 387 | /@types/chai-spies/1.0.3: 388 | resolution: {integrity: sha512-RBZjhVuK7vrg4rWMt04UF5zHYwfHnpk5mIWu3nQvU3AKGDixXzSjZ6v0zke6pBcaJqMv3IBZ5ibLWPMRDL0sLw==} 389 | dependencies: 390 | '@types/chai': 4.3.1 391 | dev: true 392 | 393 | /@types/chai/4.3.1: 394 | resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==} 395 | dev: true 396 | 397 | /@types/command-line-args/5.2.0: 398 | resolution: {integrity: sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==} 399 | dev: true 400 | 401 | /@types/json-schema/7.0.11: 402 | resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} 403 | dev: true 404 | 405 | /@types/mime-types/2.1.1: 406 | resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==} 407 | dev: true 408 | 409 | /@types/mocha/9.1.1: 410 | resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} 411 | dev: true 412 | 413 | /@types/node/16.11.39: 414 | resolution: {integrity: sha512-K0MsdV42vPwm9L6UwhIxMAOmcvH/1OoVkZyCgEtVu4Wx7sElGloy/W7kMBNe/oJ7V/jW9BVt1F6RahH6e7tPXw==} 415 | dev: true 416 | 417 | /@types/ws/8.5.3: 418 | resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} 419 | dependencies: 420 | '@types/node': 16.11.39 421 | dev: true 422 | 423 | /@typescript-eslint/eslint-plugin/5.27.1_aq7uryhocdbvbqum33pitcm3y4: 424 | resolution: {integrity: sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==} 425 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 426 | peerDependencies: 427 | '@typescript-eslint/parser': ^5.0.0 428 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 429 | typescript: '*' 430 | peerDependenciesMeta: 431 | typescript: 432 | optional: true 433 | dependencies: 434 | '@typescript-eslint/parser': 5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4 435 | '@typescript-eslint/scope-manager': 5.27.1 436 | '@typescript-eslint/type-utils': 5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4 437 | '@typescript-eslint/utils': 5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4 438 | debug: 4.3.4 439 | eslint: 8.17.0 440 | functional-red-black-tree: 1.0.1 441 | ignore: 5.2.0 442 | regexpp: 3.2.0 443 | semver: 7.3.7 444 | tsutils: 3.21.0_typescript@4.7.3 445 | typescript: 4.7.3 446 | transitivePeerDependencies: 447 | - supports-color 448 | dev: true 449 | 450 | /@typescript-eslint/parser/5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4: 451 | resolution: {integrity: sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==} 452 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 453 | peerDependencies: 454 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 455 | typescript: '*' 456 | peerDependenciesMeta: 457 | typescript: 458 | optional: true 459 | dependencies: 460 | '@typescript-eslint/scope-manager': 5.27.1 461 | '@typescript-eslint/types': 5.27.1 462 | '@typescript-eslint/typescript-estree': 5.27.1_typescript@4.7.3 463 | debug: 4.3.4 464 | eslint: 8.17.0 465 | typescript: 4.7.3 466 | transitivePeerDependencies: 467 | - supports-color 468 | dev: true 469 | 470 | /@typescript-eslint/scope-manager/5.27.1: 471 | resolution: {integrity: sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg==} 472 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 473 | dependencies: 474 | '@typescript-eslint/types': 5.27.1 475 | '@typescript-eslint/visitor-keys': 5.27.1 476 | dev: true 477 | 478 | /@typescript-eslint/type-utils/5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4: 479 | resolution: {integrity: sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw==} 480 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 481 | peerDependencies: 482 | eslint: '*' 483 | typescript: '*' 484 | peerDependenciesMeta: 485 | typescript: 486 | optional: true 487 | dependencies: 488 | '@typescript-eslint/utils': 5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4 489 | debug: 4.3.4 490 | eslint: 8.17.0 491 | tsutils: 3.21.0_typescript@4.7.3 492 | typescript: 4.7.3 493 | transitivePeerDependencies: 494 | - supports-color 495 | dev: true 496 | 497 | /@typescript-eslint/types/5.27.1: 498 | resolution: {integrity: sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg==} 499 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 500 | dev: true 501 | 502 | /@typescript-eslint/typescript-estree/5.27.1_typescript@4.7.3: 503 | resolution: {integrity: sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw==} 504 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 505 | peerDependencies: 506 | typescript: '*' 507 | peerDependenciesMeta: 508 | typescript: 509 | optional: true 510 | dependencies: 511 | '@typescript-eslint/types': 5.27.1 512 | '@typescript-eslint/visitor-keys': 5.27.1 513 | debug: 4.3.4 514 | globby: 11.1.0 515 | is-glob: 4.0.3 516 | semver: 7.3.7 517 | tsutils: 3.21.0_typescript@4.7.3 518 | typescript: 4.7.3 519 | transitivePeerDependencies: 520 | - supports-color 521 | dev: true 522 | 523 | /@typescript-eslint/utils/5.27.1_ud6rd4xtew5bv4yhvkvu24pzm4: 524 | resolution: {integrity: sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w==} 525 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 526 | peerDependencies: 527 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 528 | dependencies: 529 | '@types/json-schema': 7.0.11 530 | '@typescript-eslint/scope-manager': 5.27.1 531 | '@typescript-eslint/types': 5.27.1 532 | '@typescript-eslint/typescript-estree': 5.27.1_typescript@4.7.3 533 | eslint: 8.17.0 534 | eslint-scope: 5.1.1 535 | eslint-utils: 3.0.0_eslint@8.17.0 536 | transitivePeerDependencies: 537 | - supports-color 538 | - typescript 539 | dev: true 540 | 541 | /@typescript-eslint/visitor-keys/5.27.1: 542 | resolution: {integrity: sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ==} 543 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 544 | dependencies: 545 | '@typescript-eslint/types': 5.27.1 546 | eslint-visitor-keys: 3.3.0 547 | dev: true 548 | 549 | /@ungap/promise-all-settled/1.1.2: 550 | resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} 551 | dev: true 552 | 553 | /acorn-jsx/5.3.2_acorn@8.7.1: 554 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 555 | peerDependencies: 556 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 557 | dependencies: 558 | acorn: 8.7.1 559 | dev: true 560 | 561 | /acorn-walk/8.2.0: 562 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} 563 | engines: {node: '>=0.4.0'} 564 | dev: true 565 | 566 | /acorn/8.7.1: 567 | resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} 568 | engines: {node: '>=0.4.0'} 569 | hasBin: true 570 | dev: true 571 | 572 | /aggregate-error/3.1.0: 573 | resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} 574 | engines: {node: '>=8'} 575 | dependencies: 576 | clean-stack: 2.2.0 577 | indent-string: 4.0.0 578 | dev: true 579 | 580 | /ajv/6.12.6: 581 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 582 | dependencies: 583 | fast-deep-equal: 3.1.3 584 | fast-json-stable-stringify: 2.1.0 585 | json-schema-traverse: 0.4.1 586 | uri-js: 4.4.1 587 | dev: true 588 | 589 | /ansi-colors/4.1.1: 590 | resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} 591 | engines: {node: '>=6'} 592 | dev: true 593 | 594 | /ansi-regex/5.0.1: 595 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 596 | engines: {node: '>=8'} 597 | dev: true 598 | 599 | /ansi-styles/3.2.1: 600 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 601 | engines: {node: '>=4'} 602 | dependencies: 603 | color-convert: 1.9.3 604 | dev: true 605 | 606 | /ansi-styles/4.3.0: 607 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 608 | engines: {node: '>=8'} 609 | dependencies: 610 | color-convert: 2.0.1 611 | dev: true 612 | 613 | /anymatch/3.1.2: 614 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} 615 | engines: {node: '>= 8'} 616 | dependencies: 617 | normalize-path: 3.0.0 618 | picomatch: 2.3.1 619 | dev: true 620 | 621 | /append-transform/2.0.0: 622 | resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==} 623 | engines: {node: '>=8'} 624 | dependencies: 625 | default-require-extensions: 3.0.0 626 | dev: true 627 | 628 | /archy/1.0.0: 629 | resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} 630 | dev: true 631 | 632 | /arg/4.1.3: 633 | resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} 634 | dev: true 635 | 636 | /argparse/1.0.10: 637 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 638 | dependencies: 639 | sprintf-js: 1.0.3 640 | dev: true 641 | 642 | /argparse/2.0.1: 643 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 644 | dev: true 645 | 646 | /array-back/3.1.0: 647 | resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} 648 | engines: {node: '>=6'} 649 | dev: false 650 | 651 | /array-union/2.1.0: 652 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 653 | engines: {node: '>=8'} 654 | dev: true 655 | 656 | /assertion-error/1.1.0: 657 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 658 | dev: true 659 | 660 | /axios/0.24.0: 661 | resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} 662 | dependencies: 663 | follow-redirects: 1.15.1 664 | transitivePeerDependencies: 665 | - debug 666 | dev: false 667 | 668 | /balanced-match/1.0.2: 669 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 670 | dev: true 671 | 672 | /binary-extensions/2.2.0: 673 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 674 | engines: {node: '>=8'} 675 | dev: true 676 | 677 | /brace-expansion/1.1.11: 678 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 679 | dependencies: 680 | balanced-match: 1.0.2 681 | concat-map: 0.0.1 682 | dev: true 683 | 684 | /braces/3.0.2: 685 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 686 | engines: {node: '>=8'} 687 | dependencies: 688 | fill-range: 7.0.1 689 | dev: true 690 | 691 | /browser-stdout/1.3.1: 692 | resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} 693 | dev: true 694 | 695 | /browserslist/4.20.4: 696 | resolution: {integrity: sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==} 697 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 698 | hasBin: true 699 | dependencies: 700 | caniuse-lite: 1.0.30001352 701 | electron-to-chromium: 1.4.151 702 | escalade: 3.1.1 703 | node-releases: 2.0.5 704 | picocolors: 1.0.0 705 | dev: true 706 | 707 | /caching-transform/4.0.0: 708 | resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} 709 | engines: {node: '>=8'} 710 | dependencies: 711 | hasha: 5.2.2 712 | make-dir: 3.1.0 713 | package-hash: 4.0.0 714 | write-file-atomic: 3.0.3 715 | dev: true 716 | 717 | /callsites/3.1.0: 718 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 719 | engines: {node: '>=6'} 720 | dev: true 721 | 722 | /camelcase/5.3.1: 723 | resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} 724 | engines: {node: '>=6'} 725 | dev: true 726 | 727 | /camelcase/6.3.0: 728 | resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} 729 | engines: {node: '>=10'} 730 | dev: true 731 | 732 | /caniuse-lite/1.0.30001352: 733 | resolution: {integrity: sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==} 734 | dev: true 735 | 736 | /chai-spies/1.0.0_chai@4.3.6: 737 | resolution: {integrity: sha512-elF2ZUczBsFoP07qCfMO/zeggs8pqCf3fZGyK5+2X4AndS8jycZYID91ztD9oQ7d/0tnS963dPkd0frQEThDsg==} 738 | engines: {node: '>= 4.0.0'} 739 | peerDependencies: 740 | chai: '*' 741 | dependencies: 742 | chai: 4.3.6 743 | dev: true 744 | 745 | /chai/4.3.6: 746 | resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==} 747 | engines: {node: '>=4'} 748 | dependencies: 749 | assertion-error: 1.1.0 750 | check-error: 1.0.2 751 | deep-eql: 3.0.1 752 | get-func-name: 2.0.0 753 | loupe: 2.3.4 754 | pathval: 1.1.1 755 | type-detect: 4.0.8 756 | dev: true 757 | 758 | /chalk/2.4.2: 759 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 760 | engines: {node: '>=4'} 761 | dependencies: 762 | ansi-styles: 3.2.1 763 | escape-string-regexp: 1.0.5 764 | supports-color: 5.5.0 765 | dev: true 766 | 767 | /chalk/4.1.2: 768 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 769 | engines: {node: '>=10'} 770 | dependencies: 771 | ansi-styles: 4.3.0 772 | supports-color: 7.2.0 773 | dev: true 774 | 775 | /check-error/1.0.2: 776 | resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} 777 | dev: true 778 | 779 | /chokidar/3.5.3: 780 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 781 | engines: {node: '>= 8.10.0'} 782 | dependencies: 783 | anymatch: 3.1.2 784 | braces: 3.0.2 785 | glob-parent: 5.1.2 786 | is-binary-path: 2.1.0 787 | is-glob: 4.0.3 788 | normalize-path: 3.0.0 789 | readdirp: 3.6.0 790 | optionalDependencies: 791 | fsevents: 2.3.2 792 | dev: true 793 | 794 | /clean-stack/2.2.0: 795 | resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} 796 | engines: {node: '>=6'} 797 | dev: true 798 | 799 | /cliui/6.0.0: 800 | resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} 801 | dependencies: 802 | string-width: 4.2.3 803 | strip-ansi: 6.0.1 804 | wrap-ansi: 6.2.0 805 | dev: true 806 | 807 | /cliui/7.0.4: 808 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} 809 | dependencies: 810 | string-width: 4.2.3 811 | strip-ansi: 6.0.1 812 | wrap-ansi: 7.0.0 813 | dev: true 814 | 815 | /color-convert/1.9.3: 816 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 817 | dependencies: 818 | color-name: 1.1.3 819 | dev: true 820 | 821 | /color-convert/2.0.1: 822 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 823 | engines: {node: '>=7.0.0'} 824 | dependencies: 825 | color-name: 1.1.4 826 | dev: true 827 | 828 | /color-name/1.1.3: 829 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 830 | dev: true 831 | 832 | /color-name/1.1.4: 833 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 834 | dev: true 835 | 836 | /command-line-args/5.2.1: 837 | resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} 838 | engines: {node: '>=4.0.0'} 839 | dependencies: 840 | array-back: 3.1.0 841 | find-replace: 3.0.0 842 | lodash.camelcase: 4.3.0 843 | typical: 4.0.0 844 | dev: false 845 | 846 | /commondir/1.0.1: 847 | resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} 848 | dev: true 849 | 850 | /concat-map/0.0.1: 851 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} 852 | dev: true 853 | 854 | /convert-source-map/1.8.0: 855 | resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} 856 | dependencies: 857 | safe-buffer: 5.1.2 858 | dev: true 859 | 860 | /create-require/1.1.1: 861 | resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} 862 | dev: true 863 | 864 | /cross-spawn/7.0.3: 865 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 866 | engines: {node: '>= 8'} 867 | dependencies: 868 | path-key: 3.1.1 869 | shebang-command: 2.0.0 870 | which: 2.0.2 871 | dev: true 872 | 873 | /debug/4.3.3_supports-color@8.1.1: 874 | resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} 875 | engines: {node: '>=6.0'} 876 | peerDependencies: 877 | supports-color: '*' 878 | peerDependenciesMeta: 879 | supports-color: 880 | optional: true 881 | dependencies: 882 | ms: 2.1.2 883 | supports-color: 8.1.1 884 | dev: true 885 | 886 | /debug/4.3.4: 887 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 888 | engines: {node: '>=6.0'} 889 | peerDependencies: 890 | supports-color: '*' 891 | peerDependenciesMeta: 892 | supports-color: 893 | optional: true 894 | dependencies: 895 | ms: 2.1.2 896 | dev: true 897 | 898 | /decamelize/1.2.0: 899 | resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} 900 | engines: {node: '>=0.10.0'} 901 | dev: true 902 | 903 | /decamelize/4.0.0: 904 | resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} 905 | engines: {node: '>=10'} 906 | dev: true 907 | 908 | /deep-eql/3.0.1: 909 | resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==} 910 | engines: {node: '>=0.12'} 911 | dependencies: 912 | type-detect: 4.0.8 913 | dev: true 914 | 915 | /deep-is/0.1.4: 916 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 917 | dev: true 918 | 919 | /default-require-extensions/3.0.0: 920 | resolution: {integrity: sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==} 921 | engines: {node: '>=8'} 922 | dependencies: 923 | strip-bom: 4.0.0 924 | dev: true 925 | 926 | /diff/4.0.2: 927 | resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} 928 | engines: {node: '>=0.3.1'} 929 | dev: true 930 | 931 | /diff/5.0.0: 932 | resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} 933 | engines: {node: '>=0.3.1'} 934 | dev: true 935 | 936 | /dir-glob/3.0.1: 937 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 938 | engines: {node: '>=8'} 939 | dependencies: 940 | path-type: 4.0.0 941 | dev: true 942 | 943 | /doctrine/3.0.0: 944 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 945 | engines: {node: '>=6.0.0'} 946 | dependencies: 947 | esutils: 2.0.3 948 | dev: true 949 | 950 | /electron-to-chromium/1.4.151: 951 | resolution: {integrity: sha512-XaG2LpZi9fdiWYOqJh0dJy4SlVywCvpgYXhzOlZTp4JqSKqxn5URqOjbm9OMYB3aInA2GuHQiem1QUOc1yT0Pw==} 952 | dev: true 953 | 954 | /emoji-regex/8.0.0: 955 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 956 | dev: true 957 | 958 | /es6-error/4.1.1: 959 | resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} 960 | dev: true 961 | 962 | /escalade/3.1.1: 963 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 964 | engines: {node: '>=6'} 965 | dev: true 966 | 967 | /escape-string-regexp/1.0.5: 968 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 969 | engines: {node: '>=0.8.0'} 970 | dev: true 971 | 972 | /escape-string-regexp/4.0.0: 973 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 974 | engines: {node: '>=10'} 975 | dev: true 976 | 977 | /eslint-scope/5.1.1: 978 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 979 | engines: {node: '>=8.0.0'} 980 | dependencies: 981 | esrecurse: 4.3.0 982 | estraverse: 4.3.0 983 | dev: true 984 | 985 | /eslint-scope/7.1.1: 986 | resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} 987 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 988 | dependencies: 989 | esrecurse: 4.3.0 990 | estraverse: 5.3.0 991 | dev: true 992 | 993 | /eslint-utils/3.0.0_eslint@8.17.0: 994 | resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} 995 | engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} 996 | peerDependencies: 997 | eslint: '>=5' 998 | dependencies: 999 | eslint: 8.17.0 1000 | eslint-visitor-keys: 2.1.0 1001 | dev: true 1002 | 1003 | /eslint-visitor-keys/2.1.0: 1004 | resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 1005 | engines: {node: '>=10'} 1006 | dev: true 1007 | 1008 | /eslint-visitor-keys/3.3.0: 1009 | resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} 1010 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1011 | dev: true 1012 | 1013 | /eslint/8.17.0: 1014 | resolution: {integrity: sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==} 1015 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1016 | hasBin: true 1017 | dependencies: 1018 | '@eslint/eslintrc': 1.3.0 1019 | '@humanwhocodes/config-array': 0.9.5 1020 | ajv: 6.12.6 1021 | chalk: 4.1.2 1022 | cross-spawn: 7.0.3 1023 | debug: 4.3.4 1024 | doctrine: 3.0.0 1025 | escape-string-regexp: 4.0.0 1026 | eslint-scope: 7.1.1 1027 | eslint-utils: 3.0.0_eslint@8.17.0 1028 | eslint-visitor-keys: 3.3.0 1029 | espree: 9.3.2 1030 | esquery: 1.4.0 1031 | esutils: 2.0.3 1032 | fast-deep-equal: 3.1.3 1033 | file-entry-cache: 6.0.1 1034 | functional-red-black-tree: 1.0.1 1035 | glob-parent: 6.0.2 1036 | globals: 13.15.0 1037 | ignore: 5.2.0 1038 | import-fresh: 3.3.0 1039 | imurmurhash: 0.1.4 1040 | is-glob: 4.0.3 1041 | js-yaml: 4.1.0 1042 | json-stable-stringify-without-jsonify: 1.0.1 1043 | levn: 0.4.1 1044 | lodash.merge: 4.6.2 1045 | minimatch: 3.1.2 1046 | natural-compare: 1.4.0 1047 | optionator: 0.9.1 1048 | regexpp: 3.2.0 1049 | strip-ansi: 6.0.1 1050 | strip-json-comments: 3.1.1 1051 | text-table: 0.2.0 1052 | v8-compile-cache: 2.3.0 1053 | transitivePeerDependencies: 1054 | - supports-color 1055 | dev: true 1056 | 1057 | /espree/9.3.2: 1058 | resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} 1059 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1060 | dependencies: 1061 | acorn: 8.7.1 1062 | acorn-jsx: 5.3.2_acorn@8.7.1 1063 | eslint-visitor-keys: 3.3.0 1064 | dev: true 1065 | 1066 | /esprima/4.0.1: 1067 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 1068 | engines: {node: '>=4'} 1069 | hasBin: true 1070 | dev: true 1071 | 1072 | /esquery/1.4.0: 1073 | resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} 1074 | engines: {node: '>=0.10'} 1075 | dependencies: 1076 | estraverse: 5.3.0 1077 | dev: true 1078 | 1079 | /esrecurse/4.3.0: 1080 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 1081 | engines: {node: '>=4.0'} 1082 | dependencies: 1083 | estraverse: 5.3.0 1084 | dev: true 1085 | 1086 | /estraverse/4.3.0: 1087 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 1088 | engines: {node: '>=4.0'} 1089 | dev: true 1090 | 1091 | /estraverse/5.3.0: 1092 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 1093 | engines: {node: '>=4.0'} 1094 | dev: true 1095 | 1096 | /esutils/2.0.3: 1097 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 1098 | engines: {node: '>=0.10.0'} 1099 | dev: true 1100 | 1101 | /fast-deep-equal/3.1.3: 1102 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1103 | dev: true 1104 | 1105 | /fast-glob/3.2.11: 1106 | resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} 1107 | engines: {node: '>=8.6.0'} 1108 | dependencies: 1109 | '@nodelib/fs.stat': 2.0.5 1110 | '@nodelib/fs.walk': 1.2.8 1111 | glob-parent: 5.1.2 1112 | merge2: 1.4.1 1113 | micromatch: 4.0.5 1114 | dev: true 1115 | 1116 | /fast-json-stable-stringify/2.1.0: 1117 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1118 | dev: true 1119 | 1120 | /fast-levenshtein/2.0.6: 1121 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 1122 | dev: true 1123 | 1124 | /fastq/1.13.0: 1125 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} 1126 | dependencies: 1127 | reusify: 1.0.4 1128 | dev: true 1129 | 1130 | /file-entry-cache/6.0.1: 1131 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 1132 | engines: {node: ^10.12.0 || >=12.0.0} 1133 | dependencies: 1134 | flat-cache: 3.0.4 1135 | dev: true 1136 | 1137 | /fill-range/7.0.1: 1138 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1139 | engines: {node: '>=8'} 1140 | dependencies: 1141 | to-regex-range: 5.0.1 1142 | dev: true 1143 | 1144 | /find-cache-dir/3.3.2: 1145 | resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} 1146 | engines: {node: '>=8'} 1147 | dependencies: 1148 | commondir: 1.0.1 1149 | make-dir: 3.1.0 1150 | pkg-dir: 4.2.0 1151 | dev: true 1152 | 1153 | /find-replace/3.0.0: 1154 | resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} 1155 | engines: {node: '>=4.0.0'} 1156 | dependencies: 1157 | array-back: 3.1.0 1158 | dev: false 1159 | 1160 | /find-up/4.1.0: 1161 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 1162 | engines: {node: '>=8'} 1163 | dependencies: 1164 | locate-path: 5.0.0 1165 | path-exists: 4.0.0 1166 | dev: true 1167 | 1168 | /find-up/5.0.0: 1169 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 1170 | engines: {node: '>=10'} 1171 | dependencies: 1172 | locate-path: 6.0.0 1173 | path-exists: 4.0.0 1174 | dev: true 1175 | 1176 | /flat-cache/3.0.4: 1177 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} 1178 | engines: {node: ^10.12.0 || >=12.0.0} 1179 | dependencies: 1180 | flatted: 3.2.5 1181 | rimraf: 3.0.2 1182 | dev: true 1183 | 1184 | /flat/5.0.2: 1185 | resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} 1186 | hasBin: true 1187 | dev: true 1188 | 1189 | /flatted/3.2.5: 1190 | resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} 1191 | dev: true 1192 | 1193 | /follow-redirects/1.15.1: 1194 | resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} 1195 | engines: {node: '>=4.0'} 1196 | peerDependencies: 1197 | debug: '*' 1198 | peerDependenciesMeta: 1199 | debug: 1200 | optional: true 1201 | dev: false 1202 | 1203 | /foreground-child/2.0.0: 1204 | resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} 1205 | engines: {node: '>=8.0.0'} 1206 | dependencies: 1207 | cross-spawn: 7.0.3 1208 | signal-exit: 3.0.7 1209 | dev: true 1210 | 1211 | /fromentries/1.3.2: 1212 | resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} 1213 | dev: true 1214 | 1215 | /fs.realpath/1.0.0: 1216 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 1217 | dev: true 1218 | 1219 | /fsevents/2.3.2: 1220 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 1221 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1222 | os: [darwin] 1223 | requiresBuild: true 1224 | dev: true 1225 | optional: true 1226 | 1227 | /functional-red-black-tree/1.0.1: 1228 | resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} 1229 | dev: true 1230 | 1231 | /gensync/1.0.0-beta.2: 1232 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1233 | engines: {node: '>=6.9.0'} 1234 | dev: true 1235 | 1236 | /get-caller-file/2.0.5: 1237 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 1238 | engines: {node: 6.* || 8.* || >= 10.*} 1239 | dev: true 1240 | 1241 | /get-func-name/2.0.0: 1242 | resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} 1243 | dev: true 1244 | 1245 | /get-package-type/0.1.0: 1246 | resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} 1247 | engines: {node: '>=8.0.0'} 1248 | dev: true 1249 | 1250 | /glob-parent/5.1.2: 1251 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1252 | engines: {node: '>= 6'} 1253 | dependencies: 1254 | is-glob: 4.0.3 1255 | dev: true 1256 | 1257 | /glob-parent/6.0.2: 1258 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1259 | engines: {node: '>=10.13.0'} 1260 | dependencies: 1261 | is-glob: 4.0.3 1262 | dev: true 1263 | 1264 | /glob/7.2.0: 1265 | resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} 1266 | dependencies: 1267 | fs.realpath: 1.0.0 1268 | inflight: 1.0.6 1269 | inherits: 2.0.4 1270 | minimatch: 3.1.2 1271 | once: 1.4.0 1272 | path-is-absolute: 1.0.1 1273 | dev: true 1274 | 1275 | /glob/7.2.3: 1276 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 1277 | dependencies: 1278 | fs.realpath: 1.0.0 1279 | inflight: 1.0.6 1280 | inherits: 2.0.4 1281 | minimatch: 3.1.2 1282 | once: 1.4.0 1283 | path-is-absolute: 1.0.1 1284 | dev: true 1285 | 1286 | /globals/11.12.0: 1287 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1288 | engines: {node: '>=4'} 1289 | dev: true 1290 | 1291 | /globals/13.15.0: 1292 | resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} 1293 | engines: {node: '>=8'} 1294 | dependencies: 1295 | type-fest: 0.20.2 1296 | dev: true 1297 | 1298 | /globby/11.1.0: 1299 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1300 | engines: {node: '>=10'} 1301 | dependencies: 1302 | array-union: 2.1.0 1303 | dir-glob: 3.0.1 1304 | fast-glob: 3.2.11 1305 | ignore: 5.2.0 1306 | merge2: 1.4.1 1307 | slash: 3.0.0 1308 | dev: true 1309 | 1310 | /graceful-fs/4.2.10: 1311 | resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} 1312 | dev: true 1313 | 1314 | /growl/1.10.5: 1315 | resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} 1316 | engines: {node: '>=4.x'} 1317 | dev: true 1318 | 1319 | /has-flag/3.0.0: 1320 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 1321 | engines: {node: '>=4'} 1322 | dev: true 1323 | 1324 | /has-flag/4.0.0: 1325 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1326 | engines: {node: '>=8'} 1327 | dev: true 1328 | 1329 | /hasha/5.2.2: 1330 | resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} 1331 | engines: {node: '>=8'} 1332 | dependencies: 1333 | is-stream: 2.0.1 1334 | type-fest: 0.8.1 1335 | dev: true 1336 | 1337 | /he/1.2.0: 1338 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 1339 | hasBin: true 1340 | dev: true 1341 | 1342 | /html-escaper/2.0.2: 1343 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} 1344 | dev: true 1345 | 1346 | /ignore/5.2.0: 1347 | resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} 1348 | engines: {node: '>= 4'} 1349 | dev: true 1350 | 1351 | /import-fresh/3.3.0: 1352 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1353 | engines: {node: '>=6'} 1354 | dependencies: 1355 | parent-module: 1.0.1 1356 | resolve-from: 4.0.0 1357 | dev: true 1358 | 1359 | /imurmurhash/0.1.4: 1360 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1361 | engines: {node: '>=0.8.19'} 1362 | dev: true 1363 | 1364 | /indent-string/4.0.0: 1365 | resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} 1366 | engines: {node: '>=8'} 1367 | dev: true 1368 | 1369 | /inflight/1.0.6: 1370 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 1371 | dependencies: 1372 | once: 1.4.0 1373 | wrappy: 1.0.2 1374 | dev: true 1375 | 1376 | /inherits/2.0.4: 1377 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1378 | dev: true 1379 | 1380 | /is-binary-path/2.1.0: 1381 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1382 | engines: {node: '>=8'} 1383 | dependencies: 1384 | binary-extensions: 2.2.0 1385 | dev: true 1386 | 1387 | /is-extglob/2.1.1: 1388 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1389 | engines: {node: '>=0.10.0'} 1390 | dev: true 1391 | 1392 | /is-fullwidth-code-point/3.0.0: 1393 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1394 | engines: {node: '>=8'} 1395 | dev: true 1396 | 1397 | /is-glob/4.0.3: 1398 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1399 | engines: {node: '>=0.10.0'} 1400 | dependencies: 1401 | is-extglob: 2.1.1 1402 | dev: true 1403 | 1404 | /is-number/7.0.0: 1405 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1406 | engines: {node: '>=0.12.0'} 1407 | dev: true 1408 | 1409 | /is-plain-obj/2.1.0: 1410 | resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} 1411 | engines: {node: '>=8'} 1412 | dev: true 1413 | 1414 | /is-stream/2.0.1: 1415 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 1416 | engines: {node: '>=8'} 1417 | dev: true 1418 | 1419 | /is-typedarray/1.0.0: 1420 | resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} 1421 | dev: true 1422 | 1423 | /is-unicode-supported/0.1.0: 1424 | resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} 1425 | engines: {node: '>=10'} 1426 | dev: true 1427 | 1428 | /is-windows/1.0.2: 1429 | resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} 1430 | engines: {node: '>=0.10.0'} 1431 | dev: true 1432 | 1433 | /isexe/2.0.0: 1434 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1435 | dev: true 1436 | 1437 | /istanbul-lib-coverage/3.2.0: 1438 | resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} 1439 | engines: {node: '>=8'} 1440 | dev: true 1441 | 1442 | /istanbul-lib-hook/3.0.0: 1443 | resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==} 1444 | engines: {node: '>=8'} 1445 | dependencies: 1446 | append-transform: 2.0.0 1447 | dev: true 1448 | 1449 | /istanbul-lib-instrument/4.0.3: 1450 | resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} 1451 | engines: {node: '>=8'} 1452 | dependencies: 1453 | '@babel/core': 7.18.2 1454 | '@istanbuljs/schema': 0.1.3 1455 | istanbul-lib-coverage: 3.2.0 1456 | semver: 6.3.0 1457 | transitivePeerDependencies: 1458 | - supports-color 1459 | dev: true 1460 | 1461 | /istanbul-lib-processinfo/2.0.3: 1462 | resolution: {integrity: sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==} 1463 | engines: {node: '>=8'} 1464 | dependencies: 1465 | archy: 1.0.0 1466 | cross-spawn: 7.0.3 1467 | istanbul-lib-coverage: 3.2.0 1468 | p-map: 3.0.0 1469 | rimraf: 3.0.2 1470 | uuid: 8.3.2 1471 | dev: true 1472 | 1473 | /istanbul-lib-report/3.0.0: 1474 | resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} 1475 | engines: {node: '>=8'} 1476 | dependencies: 1477 | istanbul-lib-coverage: 3.2.0 1478 | make-dir: 3.1.0 1479 | supports-color: 7.2.0 1480 | dev: true 1481 | 1482 | /istanbul-lib-source-maps/4.0.1: 1483 | resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} 1484 | engines: {node: '>=10'} 1485 | dependencies: 1486 | debug: 4.3.4 1487 | istanbul-lib-coverage: 3.2.0 1488 | source-map: 0.6.1 1489 | transitivePeerDependencies: 1490 | - supports-color 1491 | dev: true 1492 | 1493 | /istanbul-reports/3.1.4: 1494 | resolution: {integrity: sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==} 1495 | engines: {node: '>=8'} 1496 | dependencies: 1497 | html-escaper: 2.0.2 1498 | istanbul-lib-report: 3.0.0 1499 | dev: true 1500 | 1501 | /js-tokens/4.0.0: 1502 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1503 | dev: true 1504 | 1505 | /js-yaml/3.14.1: 1506 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} 1507 | hasBin: true 1508 | dependencies: 1509 | argparse: 1.0.10 1510 | esprima: 4.0.1 1511 | dev: true 1512 | 1513 | /js-yaml/4.1.0: 1514 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1515 | hasBin: true 1516 | dependencies: 1517 | argparse: 2.0.1 1518 | dev: true 1519 | 1520 | /jsesc/2.5.2: 1521 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} 1522 | engines: {node: '>=4'} 1523 | hasBin: true 1524 | dev: true 1525 | 1526 | /json-schema-traverse/0.4.1: 1527 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1528 | dev: true 1529 | 1530 | /json-stable-stringify-without-jsonify/1.0.1: 1531 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1532 | dev: true 1533 | 1534 | /json5/2.2.1: 1535 | resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} 1536 | engines: {node: '>=6'} 1537 | hasBin: true 1538 | dev: true 1539 | 1540 | /levn/0.4.1: 1541 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1542 | engines: {node: '>= 0.8.0'} 1543 | dependencies: 1544 | prelude-ls: 1.2.1 1545 | type-check: 0.4.0 1546 | dev: true 1547 | 1548 | /locate-path/5.0.0: 1549 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 1550 | engines: {node: '>=8'} 1551 | dependencies: 1552 | p-locate: 4.1.0 1553 | dev: true 1554 | 1555 | /locate-path/6.0.0: 1556 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1557 | engines: {node: '>=10'} 1558 | dependencies: 1559 | p-locate: 5.0.0 1560 | dev: true 1561 | 1562 | /lodash.camelcase/4.3.0: 1563 | resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} 1564 | dev: false 1565 | 1566 | /lodash.flattendeep/4.4.0: 1567 | resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} 1568 | dev: true 1569 | 1570 | /lodash.merge/4.6.2: 1571 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1572 | dev: true 1573 | 1574 | /log-symbols/4.1.0: 1575 | resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} 1576 | engines: {node: '>=10'} 1577 | dependencies: 1578 | chalk: 4.1.2 1579 | is-unicode-supported: 0.1.0 1580 | dev: true 1581 | 1582 | /loupe/2.3.4: 1583 | resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==} 1584 | dependencies: 1585 | get-func-name: 2.0.0 1586 | dev: true 1587 | 1588 | /lru-cache/6.0.0: 1589 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1590 | engines: {node: '>=10'} 1591 | dependencies: 1592 | yallist: 4.0.0 1593 | dev: true 1594 | 1595 | /make-dir/3.1.0: 1596 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 1597 | engines: {node: '>=8'} 1598 | dependencies: 1599 | semver: 6.3.0 1600 | dev: true 1601 | 1602 | /make-error/1.3.6: 1603 | resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} 1604 | dev: true 1605 | 1606 | /merge2/1.4.1: 1607 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1608 | engines: {node: '>= 8'} 1609 | dev: true 1610 | 1611 | /micromatch/4.0.5: 1612 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1613 | engines: {node: '>=8.6'} 1614 | dependencies: 1615 | braces: 3.0.2 1616 | picomatch: 2.3.1 1617 | dev: true 1618 | 1619 | /mime-db/1.52.0: 1620 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 1621 | engines: {node: '>= 0.6'} 1622 | dev: false 1623 | 1624 | /mime-types/2.1.35: 1625 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 1626 | engines: {node: '>= 0.6'} 1627 | dependencies: 1628 | mime-db: 1.52.0 1629 | dev: false 1630 | 1631 | /minimatch/3.1.2: 1632 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1633 | dependencies: 1634 | brace-expansion: 1.1.11 1635 | dev: true 1636 | 1637 | /minimatch/4.2.1: 1638 | resolution: {integrity: sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==} 1639 | engines: {node: '>=10'} 1640 | dependencies: 1641 | brace-expansion: 1.1.11 1642 | dev: true 1643 | 1644 | /mocha/9.2.2: 1645 | resolution: {integrity: sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==} 1646 | engines: {node: '>= 12.0.0'} 1647 | hasBin: true 1648 | dependencies: 1649 | '@ungap/promise-all-settled': 1.1.2 1650 | ansi-colors: 4.1.1 1651 | browser-stdout: 1.3.1 1652 | chokidar: 3.5.3 1653 | debug: 4.3.3_supports-color@8.1.1 1654 | diff: 5.0.0 1655 | escape-string-regexp: 4.0.0 1656 | find-up: 5.0.0 1657 | glob: 7.2.0 1658 | growl: 1.10.5 1659 | he: 1.2.0 1660 | js-yaml: 4.1.0 1661 | log-symbols: 4.1.0 1662 | minimatch: 4.2.1 1663 | ms: 2.1.3 1664 | nanoid: 3.3.1 1665 | serialize-javascript: 6.0.0 1666 | strip-json-comments: 3.1.1 1667 | supports-color: 8.1.1 1668 | which: 2.0.2 1669 | workerpool: 6.2.0 1670 | yargs: 16.2.0 1671 | yargs-parser: 20.2.4 1672 | yargs-unparser: 2.0.0 1673 | dev: true 1674 | 1675 | /ms/2.1.2: 1676 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1677 | dev: true 1678 | 1679 | /ms/2.1.3: 1680 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1681 | dev: true 1682 | 1683 | /nanoid/3.3.1: 1684 | resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} 1685 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1686 | hasBin: true 1687 | dev: true 1688 | 1689 | /natural-compare/1.4.0: 1690 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1691 | dev: true 1692 | 1693 | /node-preload/0.2.1: 1694 | resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} 1695 | engines: {node: '>=8'} 1696 | dependencies: 1697 | process-on-spawn: 1.0.0 1698 | dev: true 1699 | 1700 | /node-releases/2.0.5: 1701 | resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} 1702 | dev: true 1703 | 1704 | /normalize-path/3.0.0: 1705 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1706 | engines: {node: '>=0.10.0'} 1707 | dev: true 1708 | 1709 | /nyc/15.1.0: 1710 | resolution: {integrity: sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==} 1711 | engines: {node: '>=8.9'} 1712 | hasBin: true 1713 | dependencies: 1714 | '@istanbuljs/load-nyc-config': 1.1.0 1715 | '@istanbuljs/schema': 0.1.3 1716 | caching-transform: 4.0.0 1717 | convert-source-map: 1.8.0 1718 | decamelize: 1.2.0 1719 | find-cache-dir: 3.3.2 1720 | find-up: 4.1.0 1721 | foreground-child: 2.0.0 1722 | get-package-type: 0.1.0 1723 | glob: 7.2.3 1724 | istanbul-lib-coverage: 3.2.0 1725 | istanbul-lib-hook: 3.0.0 1726 | istanbul-lib-instrument: 4.0.3 1727 | istanbul-lib-processinfo: 2.0.3 1728 | istanbul-lib-report: 3.0.0 1729 | istanbul-lib-source-maps: 4.0.1 1730 | istanbul-reports: 3.1.4 1731 | make-dir: 3.1.0 1732 | node-preload: 0.2.1 1733 | p-map: 3.0.0 1734 | process-on-spawn: 1.0.0 1735 | resolve-from: 5.0.0 1736 | rimraf: 3.0.2 1737 | signal-exit: 3.0.7 1738 | spawn-wrap: 2.0.0 1739 | test-exclude: 6.0.0 1740 | yargs: 15.4.1 1741 | transitivePeerDependencies: 1742 | - supports-color 1743 | dev: true 1744 | 1745 | /once/1.4.0: 1746 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1747 | dependencies: 1748 | wrappy: 1.0.2 1749 | dev: true 1750 | 1751 | /optionator/0.9.1: 1752 | resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 1753 | engines: {node: '>= 0.8.0'} 1754 | dependencies: 1755 | deep-is: 0.1.4 1756 | fast-levenshtein: 2.0.6 1757 | levn: 0.4.1 1758 | prelude-ls: 1.2.1 1759 | type-check: 0.4.0 1760 | word-wrap: 1.2.3 1761 | dev: true 1762 | 1763 | /p-limit/2.3.0: 1764 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 1765 | engines: {node: '>=6'} 1766 | dependencies: 1767 | p-try: 2.2.0 1768 | dev: true 1769 | 1770 | /p-limit/3.1.0: 1771 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1772 | engines: {node: '>=10'} 1773 | dependencies: 1774 | yocto-queue: 0.1.0 1775 | dev: true 1776 | 1777 | /p-locate/4.1.0: 1778 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 1779 | engines: {node: '>=8'} 1780 | dependencies: 1781 | p-limit: 2.3.0 1782 | dev: true 1783 | 1784 | /p-locate/5.0.0: 1785 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1786 | engines: {node: '>=10'} 1787 | dependencies: 1788 | p-limit: 3.1.0 1789 | dev: true 1790 | 1791 | /p-map/3.0.0: 1792 | resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} 1793 | engines: {node: '>=8'} 1794 | dependencies: 1795 | aggregate-error: 3.1.0 1796 | dev: true 1797 | 1798 | /p-try/2.2.0: 1799 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 1800 | engines: {node: '>=6'} 1801 | dev: true 1802 | 1803 | /package-hash/4.0.0: 1804 | resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} 1805 | engines: {node: '>=8'} 1806 | dependencies: 1807 | graceful-fs: 4.2.10 1808 | hasha: 5.2.2 1809 | lodash.flattendeep: 4.4.0 1810 | release-zalgo: 1.0.0 1811 | dev: true 1812 | 1813 | /parent-module/1.0.1: 1814 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1815 | engines: {node: '>=6'} 1816 | dependencies: 1817 | callsites: 3.1.0 1818 | dev: true 1819 | 1820 | /path-exists/4.0.0: 1821 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1822 | engines: {node: '>=8'} 1823 | dev: true 1824 | 1825 | /path-is-absolute/1.0.1: 1826 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1827 | engines: {node: '>=0.10.0'} 1828 | dev: true 1829 | 1830 | /path-key/3.1.1: 1831 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1832 | engines: {node: '>=8'} 1833 | dev: true 1834 | 1835 | /path-type/4.0.0: 1836 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1837 | engines: {node: '>=8'} 1838 | dev: true 1839 | 1840 | /pathval/1.1.1: 1841 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 1842 | dev: true 1843 | 1844 | /picocolors/1.0.0: 1845 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1846 | dev: true 1847 | 1848 | /picomatch/2.3.1: 1849 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1850 | engines: {node: '>=8.6'} 1851 | dev: true 1852 | 1853 | /pkg-dir/4.2.0: 1854 | resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} 1855 | engines: {node: '>=8'} 1856 | dependencies: 1857 | find-up: 4.1.0 1858 | dev: true 1859 | 1860 | /prelude-ls/1.2.1: 1861 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1862 | engines: {node: '>= 0.8.0'} 1863 | dev: true 1864 | 1865 | /prettier/2.6.2: 1866 | resolution: {integrity: sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==} 1867 | engines: {node: '>=10.13.0'} 1868 | hasBin: true 1869 | dev: true 1870 | 1871 | /process-on-spawn/1.0.0: 1872 | resolution: {integrity: sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==} 1873 | engines: {node: '>=8'} 1874 | dependencies: 1875 | fromentries: 1.3.2 1876 | dev: true 1877 | 1878 | /punycode/2.1.1: 1879 | resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} 1880 | engines: {node: '>=6'} 1881 | dev: true 1882 | 1883 | /queue-microtask/1.2.3: 1884 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1885 | dev: true 1886 | 1887 | /randombytes/2.1.0: 1888 | resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} 1889 | dependencies: 1890 | safe-buffer: 5.2.1 1891 | dev: true 1892 | 1893 | /readdirp/3.6.0: 1894 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1895 | engines: {node: '>=8.10.0'} 1896 | dependencies: 1897 | picomatch: 2.3.1 1898 | dev: true 1899 | 1900 | /regexpp/3.2.0: 1901 | resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} 1902 | engines: {node: '>=8'} 1903 | dev: true 1904 | 1905 | /release-zalgo/1.0.0: 1906 | resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} 1907 | engines: {node: '>=4'} 1908 | dependencies: 1909 | es6-error: 4.1.1 1910 | dev: true 1911 | 1912 | /require-directory/2.1.1: 1913 | resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 1914 | engines: {node: '>=0.10.0'} 1915 | dev: true 1916 | 1917 | /require-main-filename/2.0.0: 1918 | resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} 1919 | dev: true 1920 | 1921 | /resolve-from/4.0.0: 1922 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1923 | engines: {node: '>=4'} 1924 | dev: true 1925 | 1926 | /resolve-from/5.0.0: 1927 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1928 | engines: {node: '>=8'} 1929 | dev: true 1930 | 1931 | /reusify/1.0.4: 1932 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1933 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1934 | dev: true 1935 | 1936 | /rimraf/3.0.2: 1937 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 1938 | hasBin: true 1939 | dependencies: 1940 | glob: 7.2.3 1941 | dev: true 1942 | 1943 | /run-parallel/1.2.0: 1944 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1945 | dependencies: 1946 | queue-microtask: 1.2.3 1947 | dev: true 1948 | 1949 | /rxjs/7.5.5: 1950 | resolution: {integrity: sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==} 1951 | dependencies: 1952 | tslib: 2.4.0 1953 | dev: false 1954 | 1955 | /safe-buffer/5.1.2: 1956 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 1957 | dev: true 1958 | 1959 | /safe-buffer/5.2.1: 1960 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1961 | dev: true 1962 | 1963 | /semver/6.3.0: 1964 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 1965 | hasBin: true 1966 | dev: true 1967 | 1968 | /semver/7.3.7: 1969 | resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} 1970 | engines: {node: '>=10'} 1971 | hasBin: true 1972 | dependencies: 1973 | lru-cache: 6.0.0 1974 | dev: true 1975 | 1976 | /serialize-javascript/6.0.0: 1977 | resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} 1978 | dependencies: 1979 | randombytes: 2.1.0 1980 | dev: true 1981 | 1982 | /set-blocking/2.0.0: 1983 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} 1984 | dev: true 1985 | 1986 | /shebang-command/2.0.0: 1987 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1988 | engines: {node: '>=8'} 1989 | dependencies: 1990 | shebang-regex: 3.0.0 1991 | dev: true 1992 | 1993 | /shebang-regex/3.0.0: 1994 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1995 | engines: {node: '>=8'} 1996 | dev: true 1997 | 1998 | /signal-exit/3.0.7: 1999 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 2000 | dev: true 2001 | 2002 | /slash/3.0.0: 2003 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 2004 | engines: {node: '>=8'} 2005 | dev: true 2006 | 2007 | /source-map/0.6.1: 2008 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 2009 | engines: {node: '>=0.10.0'} 2010 | dev: true 2011 | 2012 | /spawn-wrap/2.0.0: 2013 | resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} 2014 | engines: {node: '>=8'} 2015 | dependencies: 2016 | foreground-child: 2.0.0 2017 | is-windows: 1.0.2 2018 | make-dir: 3.1.0 2019 | rimraf: 3.0.2 2020 | signal-exit: 3.0.7 2021 | which: 2.0.2 2022 | dev: true 2023 | 2024 | /sprintf-js/1.0.3: 2025 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 2026 | dev: true 2027 | 2028 | /string-width/4.2.3: 2029 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 2030 | engines: {node: '>=8'} 2031 | dependencies: 2032 | emoji-regex: 8.0.0 2033 | is-fullwidth-code-point: 3.0.0 2034 | strip-ansi: 6.0.1 2035 | dev: true 2036 | 2037 | /strip-ansi/6.0.1: 2038 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 2039 | engines: {node: '>=8'} 2040 | dependencies: 2041 | ansi-regex: 5.0.1 2042 | dev: true 2043 | 2044 | /strip-bom/4.0.0: 2045 | resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} 2046 | engines: {node: '>=8'} 2047 | dev: true 2048 | 2049 | /strip-json-comments/3.1.1: 2050 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 2051 | engines: {node: '>=8'} 2052 | dev: true 2053 | 2054 | /supports-color/5.5.0: 2055 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 2056 | engines: {node: '>=4'} 2057 | dependencies: 2058 | has-flag: 3.0.0 2059 | dev: true 2060 | 2061 | /supports-color/7.2.0: 2062 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 2063 | engines: {node: '>=8'} 2064 | dependencies: 2065 | has-flag: 4.0.0 2066 | dev: true 2067 | 2068 | /supports-color/8.1.1: 2069 | resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} 2070 | engines: {node: '>=10'} 2071 | dependencies: 2072 | has-flag: 4.0.0 2073 | dev: true 2074 | 2075 | /test-exclude/6.0.0: 2076 | resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} 2077 | engines: {node: '>=8'} 2078 | dependencies: 2079 | '@istanbuljs/schema': 0.1.3 2080 | glob: 7.2.3 2081 | minimatch: 3.1.2 2082 | dev: true 2083 | 2084 | /text-table/0.2.0: 2085 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 2086 | dev: true 2087 | 2088 | /to-fast-properties/2.0.0: 2089 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 2090 | engines: {node: '>=4'} 2091 | dev: true 2092 | 2093 | /to-regex-range/5.0.1: 2094 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 2095 | engines: {node: '>=8.0'} 2096 | dependencies: 2097 | is-number: 7.0.0 2098 | dev: true 2099 | 2100 | /ts-node/10.8.1_pjlhwcktroxhni6x7uirug5lya: 2101 | resolution: {integrity: sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==} 2102 | hasBin: true 2103 | peerDependencies: 2104 | '@swc/core': '>=1.2.50' 2105 | '@swc/wasm': '>=1.2.50' 2106 | '@types/node': '*' 2107 | typescript: '>=2.7' 2108 | peerDependenciesMeta: 2109 | '@swc/core': 2110 | optional: true 2111 | '@swc/wasm': 2112 | optional: true 2113 | dependencies: 2114 | '@cspotcode/source-map-support': 0.8.1 2115 | '@tsconfig/node10': 1.0.8 2116 | '@tsconfig/node12': 1.0.9 2117 | '@tsconfig/node14': 1.0.1 2118 | '@tsconfig/node16': 1.0.2 2119 | '@types/node': 16.11.39 2120 | acorn: 8.7.1 2121 | acorn-walk: 8.2.0 2122 | arg: 4.1.3 2123 | create-require: 1.1.1 2124 | diff: 4.0.2 2125 | make-error: 1.3.6 2126 | typescript: 4.7.3 2127 | v8-compile-cache-lib: 3.0.1 2128 | yn: 3.1.1 2129 | dev: true 2130 | 2131 | /tslib/1.14.1: 2132 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 2133 | dev: true 2134 | 2135 | /tslib/2.4.0: 2136 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 2137 | dev: false 2138 | 2139 | /tsutils/3.21.0_typescript@4.7.3: 2140 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 2141 | engines: {node: '>= 6'} 2142 | peerDependencies: 2143 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 2144 | dependencies: 2145 | tslib: 1.14.1 2146 | typescript: 4.7.3 2147 | dev: true 2148 | 2149 | /type-check/0.4.0: 2150 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 2151 | engines: {node: '>= 0.8.0'} 2152 | dependencies: 2153 | prelude-ls: 1.2.1 2154 | dev: true 2155 | 2156 | /type-detect/4.0.8: 2157 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 2158 | engines: {node: '>=4'} 2159 | dev: true 2160 | 2161 | /type-fest/0.20.2: 2162 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 2163 | engines: {node: '>=10'} 2164 | dev: true 2165 | 2166 | /type-fest/0.8.1: 2167 | resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} 2168 | engines: {node: '>=8'} 2169 | dev: true 2170 | 2171 | /typedarray-to-buffer/3.1.5: 2172 | resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} 2173 | dependencies: 2174 | is-typedarray: 1.0.0 2175 | dev: true 2176 | 2177 | /typescript/4.7.3: 2178 | resolution: {integrity: sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==} 2179 | engines: {node: '>=4.2.0'} 2180 | hasBin: true 2181 | dev: true 2182 | 2183 | /typical/4.0.0: 2184 | resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} 2185 | engines: {node: '>=8'} 2186 | dev: false 2187 | 2188 | /uri-js/4.4.1: 2189 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 2190 | dependencies: 2191 | punycode: 2.1.1 2192 | dev: true 2193 | 2194 | /uuid/8.3.2: 2195 | resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} 2196 | hasBin: true 2197 | dev: true 2198 | 2199 | /v8-compile-cache-lib/3.0.1: 2200 | resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} 2201 | dev: true 2202 | 2203 | /v8-compile-cache/2.3.0: 2204 | resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} 2205 | dev: true 2206 | 2207 | /which-module/2.0.0: 2208 | resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} 2209 | dev: true 2210 | 2211 | /which/2.0.2: 2212 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 2213 | engines: {node: '>= 8'} 2214 | hasBin: true 2215 | dependencies: 2216 | isexe: 2.0.0 2217 | dev: true 2218 | 2219 | /word-wrap/1.2.3: 2220 | resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} 2221 | engines: {node: '>=0.10.0'} 2222 | dev: true 2223 | 2224 | /workerpool/6.2.0: 2225 | resolution: {integrity: sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==} 2226 | dev: true 2227 | 2228 | /wrap-ansi/6.2.0: 2229 | resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} 2230 | engines: {node: '>=8'} 2231 | dependencies: 2232 | ansi-styles: 4.3.0 2233 | string-width: 4.2.3 2234 | strip-ansi: 6.0.1 2235 | dev: true 2236 | 2237 | /wrap-ansi/7.0.0: 2238 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 2239 | engines: {node: '>=10'} 2240 | dependencies: 2241 | ansi-styles: 4.3.0 2242 | string-width: 4.2.3 2243 | strip-ansi: 6.0.1 2244 | dev: true 2245 | 2246 | /wrappy/1.0.2: 2247 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} 2248 | dev: true 2249 | 2250 | /write-file-atomic/3.0.3: 2251 | resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} 2252 | dependencies: 2253 | imurmurhash: 0.1.4 2254 | is-typedarray: 1.0.0 2255 | signal-exit: 3.0.7 2256 | typedarray-to-buffer: 3.1.5 2257 | dev: true 2258 | 2259 | /ws/8.8.0: 2260 | resolution: {integrity: sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==} 2261 | engines: {node: '>=10.0.0'} 2262 | peerDependencies: 2263 | bufferutil: ^4.0.1 2264 | utf-8-validate: ^5.0.2 2265 | peerDependenciesMeta: 2266 | bufferutil: 2267 | optional: true 2268 | utf-8-validate: 2269 | optional: true 2270 | dev: false 2271 | 2272 | /y18n/4.0.3: 2273 | resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} 2274 | dev: true 2275 | 2276 | /y18n/5.0.8: 2277 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 2278 | engines: {node: '>=10'} 2279 | dev: true 2280 | 2281 | /yallist/4.0.0: 2282 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 2283 | dev: true 2284 | 2285 | /yargs-parser/18.1.3: 2286 | resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} 2287 | engines: {node: '>=6'} 2288 | dependencies: 2289 | camelcase: 5.3.1 2290 | decamelize: 1.2.0 2291 | dev: true 2292 | 2293 | /yargs-parser/20.2.4: 2294 | resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} 2295 | engines: {node: '>=10'} 2296 | dev: true 2297 | 2298 | /yargs-unparser/2.0.0: 2299 | resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} 2300 | engines: {node: '>=10'} 2301 | dependencies: 2302 | camelcase: 6.3.0 2303 | decamelize: 4.0.0 2304 | flat: 5.0.2 2305 | is-plain-obj: 2.1.0 2306 | dev: true 2307 | 2308 | /yargs/15.4.1: 2309 | resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} 2310 | engines: {node: '>=8'} 2311 | dependencies: 2312 | cliui: 6.0.0 2313 | decamelize: 1.2.0 2314 | find-up: 4.1.0 2315 | get-caller-file: 2.0.5 2316 | require-directory: 2.1.1 2317 | require-main-filename: 2.0.0 2318 | set-blocking: 2.0.0 2319 | string-width: 4.2.3 2320 | which-module: 2.0.0 2321 | y18n: 4.0.3 2322 | yargs-parser: 18.1.3 2323 | dev: true 2324 | 2325 | /yargs/16.2.0: 2326 | resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} 2327 | engines: {node: '>=10'} 2328 | dependencies: 2329 | cliui: 7.0.4 2330 | escalade: 3.1.1 2331 | get-caller-file: 2.0.5 2332 | require-directory: 2.1.1 2333 | string-width: 4.2.3 2334 | y18n: 5.0.8 2335 | yargs-parser: 20.2.4 2336 | dev: true 2337 | 2338 | /yn/3.1.1: 2339 | resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} 2340 | engines: {node: '>=6'} 2341 | dev: true 2342 | 2343 | /yocto-queue/0.1.0: 2344 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 2345 | engines: {node: '>=10'} 2346 | dev: true 2347 | -------------------------------------------------------------------------------- /src/class-style/BaseAction.ts: -------------------------------------------------------------------------------- 1 | import { IAction } from '../types/interfaces'; 2 | 3 | export class BaseAction implements IAction { 4 | contexts: Set = new Set(); 5 | } 6 | -------------------------------------------------------------------------------- /src/class-style/decorator.ts: -------------------------------------------------------------------------------- 1 | import { AutoRunTimeUnits } from '../types/interfaces'; 2 | import { aHour, aMinute, aSecond } from '../util/constant'; 3 | 4 | export const registeredClasses: Array<[string, any]> = []; 5 | 6 | export const updatePeriods: Record = {}; 7 | 8 | export const Action = ( 9 | suffix: string, 10 | { h, m, s, ms }: AutoRunTimeUnits = {} 11 | ) => { 12 | return (target: any) => { 13 | registeredClasses.push([suffix, target]); 14 | updatePeriods[suffix] = 15 | (h ?? 0) * aHour || (m ?? 0) * aMinute || (s ?? 0) * aSecond || ms || 0; 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /src/device.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DeviceGeometry, 3 | DeviceGeometryPositions, 4 | DeviceType 5 | } from './types/interfaces'; 6 | 7 | const BaseStreamDeck: DeviceGeometryPositions = { 8 | topLeft: 0, 9 | topRight: 4, 10 | bottomLeft: 10, 11 | bottomRight: 14, 12 | center: 7, 13 | total: 3 * 5, 14 | rows: 3, 15 | columns: 5 16 | }; 17 | 18 | const positionsIndex: Record = { 19 | [DeviceType.StreamDeck]: BaseStreamDeck, 20 | [DeviceType.StreamDeckMini]: { 21 | topLeft: 0, 22 | topRight: 2, 23 | bottomLeft: 3, 24 | bottomRight: 5, 25 | approximatedCenter: 1, 26 | total: 2 * 3, 27 | rows: 2, 28 | columns: 3 29 | }, 30 | [DeviceType.StreamDeckXL]: { 31 | topLeft: 0, 32 | topRight: 7, 33 | bottomLeft: 24, 34 | bottomRight: 31, 35 | approximatedCenter: 11, 36 | total: 4 * 8, 37 | rows: 4, 38 | columns: 8 39 | }, 40 | [DeviceType.StreamDeckMobile]: BaseStreamDeck 41 | }; 42 | 43 | export const geometry = (deviceType: DeviceType): DeviceGeometry => { 44 | const positions = positionsIndex[deviceType]; 45 | return { 46 | ...positions, 47 | total: positions.total, 48 | columns: positions.columns, 49 | rows: positions.rows, 50 | 51 | mappable: ( 52 | ...except: Exclude< 53 | keyof DeviceGeometryPositions, 54 | 'total' | 'rows' | 'columns' 55 | >[] 56 | ) => { 57 | const excludedIndexes = except.map((it) => positions[it]); 58 | const validPositions = Array.from(new Array(positions.total)) 59 | .map((_, i) => i) 60 | .filter((it) => !excludedIndexes.includes(it)); 61 | return [validPositions, positions.total - validPositions.length]; 62 | } 63 | }; 64 | }; 65 | -------------------------------------------------------------------------------- /src/dynamic-view/DynamicView.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Device, 3 | DeviceGeometry, 4 | DynamicCell, 5 | DynamicViewMatrix 6 | } from '../types/interfaces'; 7 | import { geometry } from '../device'; 8 | import { BehaviorSubject, Subscription } from 'rxjs'; 9 | import { EventCoordinates } from '../types/events'; 10 | import { StreamDeck } from '../index'; 11 | 12 | export class DynamicViewInstance { 13 | public view: DynamicViewMatrix = []; 14 | public geometry: DeviceGeometry; 15 | public page = 0; 16 | public outsideListener?: () => void; 17 | public settings = {}; 18 | 19 | setSettings(context: string, settings: any) { 20 | this.settings[context] = settings; 21 | } 22 | 23 | storeSettings(context: string) { 24 | const settings = this.settings[context]; 25 | if (settings) { 26 | this.sd.setSettings(context, settings); 27 | delete this.settings[context]; 28 | } 29 | } 30 | 31 | nextPage(maxPages: number) { 32 | if (maxPages > this.page + 1) { 33 | this.page++; 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | prevPage(alternative?: () => void) { 40 | if (this.page > 0) { 41 | this.page--; 42 | return true; 43 | } else if (alternative) { 44 | alternative(); 45 | return false; 46 | } else { 47 | this.hide(); 48 | return false; 49 | } 50 | } 51 | 52 | constructor(private device: Device, private sd: StreamDeck) { 53 | this.geometry = geometry(device.type); 54 | this.view = Array.from(new Array(this.geometry.total)).map( 55 | () => new BehaviorSubject(null) 56 | ); 57 | } 58 | 59 | onTapOutside(cb: () => void) { 60 | this.outsideListener = cb; 61 | } 62 | 63 | update(index: number, cell: DynamicCell) { 64 | if (cell.source) { 65 | cell.source.index = index; 66 | } 67 | this.view[index].next(cell); 68 | } 69 | 70 | clear() { 71 | this.view.forEach((it) => it.next({})); 72 | } 73 | 74 | hide() { 75 | this.sd.switchToProfile(this.sd.uuid, this.device.id); 76 | } 77 | 78 | index(coords: EventCoordinates) { 79 | const { columns = 0 } = this.geometry || {}; 80 | return coords.column + coords.row * columns; 81 | } 82 | 83 | cell(coords: EventCoordinates): DynamicCell | null { 84 | const { columns = 0 } = this.geometry || {}; 85 | return this.view[coords.column + coords.row * columns].getValue(); 86 | } 87 | 88 | subscribe( 89 | coords: EventCoordinates, 90 | subscriber: (value: DynamicCell) => void, 91 | context: string 92 | ): [DynamicCell | null, Subscription] { 93 | const i = this.index(coords); 94 | const subscribeBind = this.view[i].subscribe(subscriber); 95 | 96 | // save temporary settings 97 | const settings = this.settings[context]; 98 | if (settings) { 99 | this.sd.setSettings(context, settings); 100 | delete this.settings[context]; 101 | } 102 | 103 | return [this.view[i].getValue(), subscribeBind]; 104 | } 105 | 106 | unsubscribe(coords: EventCoordinates) { 107 | const i = this.index(coords); 108 | this.view?.[i].unsubscribe(); 109 | } 110 | } 111 | 112 | export class DynamicView { 113 | instances: Record = {}; 114 | 115 | bind(device: Device, sd: StreamDeck): DynamicViewInstance { 116 | if (!this.instances[device.id]) { 117 | this.instances[device.id] = new DynamicViewInstance(device, sd); 118 | } 119 | return this.instances[device.id]; 120 | } 121 | 122 | for(device: string) { 123 | return this.instances[device]; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import WebSocket from 'ws'; 2 | import { 3 | BinaryArguments, 4 | Device, 5 | DeviceType, 6 | DynamicCell, 7 | DynamicViewInstance, 8 | IAction, 9 | IStreamDeck, 10 | StreamDeckConnector, 11 | StreamDeckInfo, 12 | StreamDeckOptions 13 | } from './types/interfaces'; 14 | import { AppearDisappearEvent, EVENT_MAPPING, KeyEvent } from './types/events'; 15 | import { TextDecoder } from 'util'; 16 | import { imageToBase64 } from './util/image-helper'; 17 | import { registeredClasses, updatePeriods } from './class-style/decorator'; 18 | import commandLineArgs from 'command-line-args'; 19 | import { BaseAction } from './class-style/BaseAction'; 20 | import { readFileSync } from 'fs'; 21 | import { tmpdir } from 'os'; 22 | import { DynamicView } from './dynamic-view/DynamicView'; 23 | import { Subject, Subscription } from 'rxjs'; 24 | 25 | export { Action } from './class-style/decorator'; 26 | export { BaseAction } from './class-style/BaseAction'; 27 | export * from './types/events'; 28 | 29 | export { geometry } from './device'; 30 | export { DynamicView } from './dynamic-view/DynamicView'; 31 | 32 | export class StreamDeck implements IStreamDeck { 33 | private ws: StreamDeckConnector; 34 | public actions: Record = {}; 35 | 36 | private readyObserver = new Subject(); 37 | 38 | // The plugin infos 39 | public uuid: string; 40 | public info: StreamDeckInfo; 41 | private doubleTapMillis: number; 42 | private longPressMillis: number; 43 | public pluginSettings: Partial = {}; 44 | public settingsManager: Record = {}; 45 | 46 | // group of records to identify specific events 47 | private taps: Record = {}; 48 | private doublePressTimeouts: Record = {}; 49 | private longPressTimeouts: Record = {}; 50 | private latestLongPress: Record = {}; 51 | private pressed: Record = {}; 52 | private subscriptions: Record = {}; 53 | 54 | constructor(options: StreamDeckOptions = {}) { 55 | // fix arguments dash broken :D 56 | process.argv = process.argv.map((it) => 57 | it.startsWith('-') ? `-${it}` : it 58 | ); 59 | 60 | // Get stream deck commandline arguments 61 | const flags = commandLineArgs([ 62 | { name: 'debug', type: String }, 63 | { name: 'port', type: String }, 64 | { name: 'registerEvent', type: String }, 65 | { name: 'pluginUUID', type: String }, 66 | { name: 'info', type: String } 67 | ]); 68 | 69 | let args: BinaryArguments = { 70 | debug: flags.debug, 71 | port: flags.port, 72 | info: flags.info ? JSON.parse(flags.info) : undefined, 73 | pluginUUID: flags.pluginUUID, 74 | registerEvent: flags.registerEvent 75 | }; 76 | 77 | if (args.debug) { 78 | const fileConfig = `${tmpdir()}/${args.debug}.dev.json`; 79 | args = JSON.parse(readFileSync(fileConfig).toString()); 80 | } 81 | 82 | this.init(options, args).then(); 83 | } 84 | 85 | async init(options: StreamDeckOptions = {}, args: BinaryArguments) { 86 | // assign uuid and plugin info 87 | this.uuid = args.pluginUUID; 88 | this.info = args.info; 89 | 90 | // init millis values 91 | this.doubleTapMillis = options.doubleTapMillis || 300; 92 | this.longPressMillis = options.longPressMillis || 700; 93 | 94 | this.ws = new WebSocket('ws://127.0.0.1:' + args.port); 95 | 96 | // Listen for the ws connection 97 | this.ws.on('open', () => { 98 | this.send({ 99 | event: args.registerEvent, 100 | uuid: args.pluginUUID 101 | }); 102 | }); 103 | 104 | this.ws.on('close', () => { 105 | process.exit(); 106 | }); 107 | 108 | this.ws.on('error', () => { 109 | process.exit(); 110 | }); 111 | 112 | this.ws.on('message', (msg: any) => this.onMessage.bind(this)(msg)); 113 | 114 | // register every annotated class 115 | for (const [suffix, clazz] of registeredClasses) { 116 | const uuid = this.register(suffix, new clazz()); 117 | const period = updatePeriods[suffix]; 118 | if (period) { 119 | setInterval(() => { 120 | const action = this.actions[uuid]; 121 | action && action.onPeriodicUpdate?.call(action); 122 | }, period); 123 | } 124 | } 125 | 126 | for (const [suffix, action] of Object.entries(options.actions || {})) { 127 | this.register(suffix, Object.assign({}, action)); 128 | } 129 | } 130 | 131 | // Wait for the websocket to be "connected" 132 | private waitForConnection(): Promise { 133 | return new Promise((res) => { 134 | let interval: any; 135 | if (this.ws.readyState === 1) { 136 | res(); 137 | } else { 138 | interval = setInterval(() => { 139 | if (this.ws.readyState === 1) { 140 | res(); 141 | clearInterval(interval); 142 | } 143 | }, 50); 144 | } 145 | }); 146 | } 147 | 148 | private cleanup(context: string) { 149 | delete this.pressed[context]; 150 | delete this.latestLongPress[context]; 151 | delete this.longPressTimeouts[context]; 152 | delete this.doublePressTimeouts[context]; 153 | delete this.taps[context]; 154 | delete this.settingsManager[context]; 155 | } 156 | 157 | private checkMultiTap(event: string, eventParams: any) { 158 | const { context } = eventParams; 159 | if (!context) return; 160 | 161 | this.pressed[context] = event === 'keyDown'; 162 | 163 | // code to identify the long press event 164 | if (event === 'keyDown') { 165 | if (this.longPressTimeouts[context]) { 166 | clearTimeout(this.longPressTimeouts[context]); 167 | } 168 | 169 | this.latestLongPress[context] = false; 170 | 171 | this.longPressTimeouts[context] = setTimeout(() => { 172 | if (this.pressed[context]) { 173 | this.latestLongPress[context] = true; 174 | this.pressed[context] = false; 175 | this.redirect('onLongPress', eventParams); 176 | } 177 | }, this.longPressMillis); 178 | } 179 | // code to identify the single or double tap event 180 | else { 181 | const taps = (this.taps[context] = (this.taps[context] || 0) + 1); 182 | 183 | if (this.doublePressTimeouts[context]) { 184 | clearTimeout(this.doublePressTimeouts[context]); 185 | } 186 | 187 | this.doublePressTimeouts[context] = setTimeout(() => { 188 | if (!this.latestLongPress[context]) { 189 | if (taps == 1) { 190 | this.latestLongPress[context] = false; 191 | this.redirect('onSingleTap', eventParams); 192 | } else if (taps > 1) { 193 | this.latestLongPress[context] = false; 194 | this.redirect('onDoubleTap', eventParams); 195 | } 196 | } 197 | this.taps[context] = 0; 198 | }, this.doubleTapMillis); 199 | } 200 | } 201 | 202 | // Send a json string through the websocket 203 | private send(msg: Record) { 204 | this.waitForConnection().then(() => { 205 | this.ws.send(JSON.stringify(msg)); 206 | }); 207 | } 208 | 209 | // Update a specific instance of an action and refresh the settings 210 | private notifySettingsChanged( 211 | context: string, 212 | action: string, 213 | settings: any 214 | ) { 215 | this.redirect('onSettingsChanged', { 216 | context, 217 | action, 218 | settings 219 | }); 220 | } 221 | 222 | private onMessage(msg: any) { 223 | let message; 224 | 225 | // try to decode ArrayBuffer 226 | try { 227 | message = new TextDecoder('utf-8').decode(Buffer.from(msg)); 228 | } catch (e) { 229 | message = msg; 230 | } 231 | 232 | const { event, ...eventParams } = JSON.parse(message); 233 | const { action, context } = eventParams; 234 | 235 | let params = eventParams; 236 | 237 | if (event !== 'willDisappear' && action && context) { 238 | this.actions[action]?.contexts.add(context); 239 | } 240 | 241 | switch (event) { 242 | case 'willAppear': 243 | this.settingsManager[context] = params.payload.settings; 244 | break; 245 | case 'willDisappear': 246 | this.actions[action]?.contexts.delete(context); 247 | this.cleanup(context); 248 | break; 249 | case 'didReceiveGlobalSettings': 250 | this.pluginSettings = eventParams.payload.settings; 251 | 252 | if (!this.readyObserver.closed) { 253 | this.readyObserver.next(true); 254 | } 255 | 256 | params = { 257 | changedKeys: Object.keys(this.pluginSettings) 258 | }; 259 | break; 260 | case 'keyDown': 261 | case 'keyUp': 262 | this.checkMultiTap(event, eventParams); 263 | break; 264 | case 'didReceiveSettings': 265 | this.settingsManager[eventParams.context] = 266 | eventParams.payload.settings; 267 | return this.notifySettingsChanged( 268 | eventParams.context, 269 | eventParams.action, 270 | eventParams.payload.settings 271 | ); 272 | } 273 | 274 | // emit to the internal events system 275 | this.redirect(event, params); 276 | } 277 | 278 | private redirect(eventName: string, event: any) { 279 | // close if no event or no action was registered 280 | if (!event || !Object.keys(this.actions).length) return; 281 | 282 | // find the correct action and method and propagate the event 283 | const { action } = event; 284 | const method = EVENT_MAPPING[eventName]; 285 | if (!method) return; 286 | 287 | if (action) { 288 | const registered = this.actions[action]; 289 | 290 | if (registered) { 291 | const fn = registered?.[method]; 292 | fn?.call(registered, event); 293 | } 294 | } else { 295 | Object.values(this.actions).forEach((registered) => { 296 | const fn = registered?.[method]; 297 | fn?.call(registered, event); 298 | }); 299 | } 300 | } 301 | 302 | // get the settings of a tile 303 | getSettings(context: string): S { 304 | return this.settingsManager[context]; 305 | } 306 | 307 | // register ready event 308 | async ready() { 309 | return new Promise((resolve) => { 310 | this.readyObserver.subscribe(() => { 311 | resolve(); 312 | this.readyObserver.complete(); 313 | }); 314 | }); 315 | } 316 | 317 | // register dynamic view action 318 | registerDynamicView(suffix: string, profile: string) { 319 | const dynamicView = new DynamicView(); 320 | this.register( 321 | suffix, 322 | Object.assign( 323 | { contexts: new Set() }, 324 | { 325 | binder: undefined, 326 | onDisappear: (e: AppearDisappearEvent) => { 327 | this.subscriptions[e.context]?.unsubscribe(); 328 | }, 329 | onSingleTap: (e: KeyEvent) => { 330 | const dv = dynamicView.for(e.device); 331 | const fn = 332 | dv.cell(e.payload.coordinates)?.onSingleTap ?? dv.outsideListener; 333 | fn && fn(); 334 | }, 335 | onDoubleTap: (e: KeyEvent) => { 336 | dynamicView 337 | .for(e.device) 338 | ?.cell(e.payload.coordinates) 339 | ?.onDoubleTap?.(); 340 | }, 341 | onLongPress: (e: KeyEvent) => { 342 | dynamicView 343 | .for(e.device) 344 | ?.cell(e.payload.coordinates) 345 | ?.onLongPress?.(); 346 | }, 347 | onAppear: (e: AppearDisappearEvent) => { 348 | const onUpdate = (cell: DynamicCell | null) => { 349 | this.setTitle(e.context, cell?.title ?? ''); 350 | this.setImage(e.context, cell?.image); 351 | }; 352 | const [value, bind] = 353 | dynamicView 354 | .for(e.device) 355 | ?.subscribe(e.payload.coordinates, onUpdate, e.context) ?? []; 356 | 357 | if (value) { 358 | this.subscriptions[e.context] = bind; 359 | onUpdate(value); 360 | } 361 | } 362 | } 363 | ) 364 | ); 365 | return { 366 | show: ( 367 | device: Device, 368 | except: DeviceType[] = [] 369 | ): DynamicViewInstance | undefined => { 370 | if (except.includes(device.type)) { 371 | return; 372 | } 373 | const instance = dynamicView.bind(device, this); 374 | this.switchToProfile(this.uuid, device.id, profile); 375 | return instance; 376 | }, 377 | storeSettings: (device: string, context: string) => { 378 | dynamicView.for(device)?.storeSettings(context); 379 | }, 380 | hide: (device: string) => { 381 | dynamicView.for(device)?.hide(); 382 | } 383 | }; 384 | } 385 | 386 | // get all registered actions' tiles 387 | allContexts() { 388 | return Object.fromEntries( 389 | Object.values(this.actions).map((it) => [ 390 | it.uuid, 391 | Array.from(it.contexts) 392 | ]) 393 | ); 394 | } 395 | 396 | // get an action's tiles 397 | contextsOf(action: string) { 398 | return Array.from(this.actions[action]?.contexts ?? []); 399 | } 400 | 401 | // register an action using its uuid (suffix) 402 | register(suffix: string, action: BaseAction): string { 403 | const uuid = `${this.info.plugin.uuid}.${suffix}`; 404 | Object.assign(action, { 405 | uuid, 406 | pluginUUID: this.uuid, 407 | contexts: new Set() 408 | }); 409 | this.actions[uuid] = action; 410 | this.send({ 411 | event: 'getGlobalSettings', 412 | context: this.uuid 413 | }); 414 | return uuid; 415 | } 416 | 417 | // Events Sent 418 | // https://developer.elgato.com/documentation/stream-deck/sdk/events-sent/ 419 | 420 | logMessage(message: string) { 421 | this.send({ 422 | event: 'logMessage', 423 | payload: { 424 | message 425 | } 426 | }); 427 | } 428 | 429 | openUrl(url: string) { 430 | this.send({ 431 | event: 'openUrl', 432 | payload: { 433 | url 434 | } 435 | }); 436 | } 437 | 438 | sendToPropertyInspector( 439 | context: string, 440 | action: string, 441 | payload: Record 442 | ) { 443 | this.send({ 444 | event: 'sendToPropertyInspector', 445 | action, 446 | context, 447 | payload 448 | }); 449 | } 450 | 451 | resetPluginSettings() { 452 | this.setPluginSettings({}); 453 | } 454 | 455 | setPluginSettings(settings: Partial) { 456 | if (!Object.keys(settings).length) { 457 | // reset global settings 458 | this.pluginSettings = {}; 459 | } else { 460 | 461 | // update global settings 462 | Object.assign(this.pluginSettings, settings); 463 | } 464 | 465 | this.send({ 466 | event: 'setGlobalSettings', 467 | context: this.uuid, 468 | payload: this.pluginSettings 469 | }); 470 | 471 | // send the changed keys to every action to prevent useless render 472 | const event = { 473 | changedKeys: Object.keys(settings) 474 | }; 475 | Object.values(this.actions).forEach((registered) => 476 | registered?.onPluginSettingsChanged?.call(registered, event) 477 | ); 478 | } 479 | 480 | setImage( 481 | context: string, 482 | image?: string, 483 | options: { target?: 0 | 1 | 2; state?: 0 | 1; useCache?: boolean } = {} 484 | ) { 485 | (async () => { 486 | if (image && !image.startsWith('data:image/')) { 487 | image = await imageToBase64(image, options.useCache); 488 | } 489 | 490 | this.send({ 491 | event: 'setImage', 492 | context, 493 | payload: { 494 | image, 495 | target: options.target, 496 | state: options.state 497 | } 498 | }); 499 | })(); 500 | } 501 | 502 | setSettings(context: string, settings: G) { 503 | const action = Object.values(this.actions).find((it) => 504 | it.contexts?.has(context) 505 | )?.uuid; 506 | 507 | this.settingsManager[context] = settings; 508 | 509 | if (action) { 510 | this.notifySettingsChanged(context, action, settings); 511 | } 512 | this.send({ 513 | event: 'setSettings', 514 | context: context, 515 | payload: settings 516 | }); 517 | } 518 | 519 | setState(context: string, state: 0 | 1 = 0) { 520 | this.send({ 521 | event: 'setState', 522 | context, 523 | payload: { 524 | state 525 | } 526 | }); 527 | } 528 | 529 | setTitle( 530 | context: string, 531 | title: string, 532 | options: { target?: 0 | 1 | 2; state?: 0 | 1 } = {} 533 | ) { 534 | this.send({ 535 | event: 'setTitle', 536 | context, 537 | payload: { 538 | title, 539 | target: options.target, 540 | state: options.state 541 | } 542 | }); 543 | } 544 | 545 | showAlert(context: string) { 546 | this.send({ 547 | event: 'showAlert', 548 | context 549 | }); 550 | } 551 | 552 | showOk(context: string) { 553 | this.send({ 554 | event: 'showOk', 555 | context 556 | }); 557 | } 558 | 559 | switchToProfile(context: string, device: string, profile?: string) { 560 | this.send({ 561 | event: 'switchToProfile', 562 | context, 563 | device, 564 | payload: { 565 | profile 566 | } 567 | }); 568 | } 569 | } 570 | -------------------------------------------------------------------------------- /src/types/events.ts: -------------------------------------------------------------------------------- 1 | export interface EventCoordinates { 2 | column: number; 3 | row: number; 4 | } 5 | 6 | export interface SettingsChanged { 7 | context: string; 8 | action: string; 9 | settings: T; 10 | } 11 | 12 | export interface KeyEvent { 13 | action: string; 14 | context: string; 15 | device: string; 16 | payload: { 17 | settings: T; 18 | coordinates: EventCoordinates; 19 | state: 0 | 1; 20 | userDesiredState: 0 | 1; 21 | isInMultiAction: boolean; 22 | }; 23 | } 24 | 25 | export interface AppearDisappearEvent { 26 | action: string; 27 | context: string; 28 | device: string; 29 | payload: { 30 | settings: T; 31 | coordinates: EventCoordinates; 32 | state: 0 | 1; 33 | isInMultiAction: boolean; 34 | }; 35 | } 36 | 37 | export interface TitleParametersDidChangeEvent { 38 | action: string; 39 | context: string; 40 | device: string; 41 | payload: { 42 | settings: T; 43 | coordinates: EventCoordinates; 44 | state: 0 | 1; 45 | title: string; 46 | titleParameters: { 47 | fontFamily: string; 48 | fontSize: number; 49 | fontStyle: string; 50 | fontUnderline: boolean; 51 | showTitle: boolean; 52 | titleAlignment: 'top' | 'bottom' | 'middle'; 53 | titleColor: string; 54 | }; 55 | }; 56 | } 57 | 58 | export interface DeviceConnectionEvent { 59 | device: string; 60 | deviceInfo: { 61 | name: string; 62 | type: 0 | 1 | 2 | 3 | 4; 63 | size: { 64 | rows: number; 65 | columns: number; 66 | }; 67 | }; 68 | } 69 | 70 | export interface DeviceDisconnectionEvent { 71 | device: string; 72 | } 73 | 74 | export interface ApplicationChangedEvent { 75 | payload: { 76 | application: string; 77 | }; 78 | } 79 | 80 | export interface PropertyInspectorEvent { 81 | action: string; 82 | context: string; 83 | device: string; 84 | } 85 | 86 | export interface PropertyInspectorMessagingEvent { 87 | action: string; 88 | context: string; 89 | device: string; 90 | payload: Record; 91 | } 92 | 93 | export interface PluginSettingsChanged { 94 | changedKeys: Array; 95 | } 96 | 97 | export const EVENT_MAPPING = { 98 | keyDown: 'onKeyDown', 99 | keyUp: 'onKeyUp', 100 | sendToPlugin: 'onMessageFromPropertyInspector', 101 | propertyInspectorDidDisappear: 'onPropertyInspectorAppear', 102 | willAppear: 'onAppear', 103 | willDisappear: 'onDisappear', 104 | onSingleTap: 'onSingleTap', 105 | onDoubleTap: 'onDoubleTap', 106 | onLongPress: 'onLongPress', 107 | onPropertyInspectorAppear: 'onPropertyInspectorAppear', 108 | onSettingsChanged: 'onSettingsChanged', 109 | didReceiveGlobalSettings: 'onPluginSettingsChanged', 110 | titleParametersDidChange: 'onTitleParametersChanged' 111 | }; 112 | -------------------------------------------------------------------------------- /src/types/interfaces.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AppearDisappearEvent, 3 | ApplicationChangedEvent, 4 | DeviceConnectionEvent, 5 | DeviceDisconnectionEvent, 6 | EventCoordinates, 7 | KeyEvent, 8 | PluginSettingsChanged, 9 | PropertyInspectorEvent, 10 | PropertyInspectorMessagingEvent, 11 | SettingsChanged, 12 | TitleParametersDidChangeEvent 13 | } from './events'; 14 | import { BaseAction } from '../class-style/BaseAction'; 15 | import Rx, { Subscription } from 'rxjs'; 16 | 17 | export interface StreamDeckConnector { 18 | readyState: number; 19 | load?: () => Promise; 20 | 21 | on(event: string, callback: (...args: any[]) => any): void; 22 | 23 | send(data: any): void; 24 | } 25 | 26 | export enum DeviceType { 27 | StreamDeck, 28 | StreamDeckMini, 29 | StreamDeckXL, 30 | StreamDeckMobile 31 | } 32 | 33 | export type ActionTarget = 0 | 1 | 2; 34 | 35 | export type ActionState = 0 | 1; 36 | 37 | export interface BinaryArguments { 38 | debug: string; 39 | port: string; 40 | registerEvent: string; 41 | pluginUUID: string; 42 | info: StreamDeckInfo; 43 | } 44 | 45 | export interface Device { 46 | id: string; 47 | name: string; 48 | size: { 49 | rows: number; 50 | columns: number; 51 | }; 52 | type: DeviceType; 53 | } 54 | 55 | export interface Application { 56 | font: string; 57 | language: string; 58 | platform: string; 59 | platformVersion: string; 60 | version: string; 61 | } 62 | 63 | export interface Colors { 64 | buttonMouseOverBackgroundColor: string; 65 | buttonPressedBackgroundColor: string; 66 | buttonPressedBorderColor: string; 67 | buttonPressedTextColor: string; 68 | highlightColor: string; 69 | } 70 | 71 | export interface PluginInfo { 72 | uuid: string; 73 | version: string; 74 | } 75 | 76 | export interface StreamDeckInfo { 77 | application: Application; 78 | colors: Colors; 79 | devices: Device[]; 80 | plugin: PluginInfo; 81 | devicePixelRatio: number; 82 | } 83 | 84 | export interface IStreamDeck { 85 | uuid?: string; 86 | 87 | info?: StreamDeckInfo; 88 | 89 | settings?: S; 90 | 91 | ready: () => Promise; 92 | 93 | setSettings(context: string, settings: Record): void; 94 | 95 | getSettings(context: string): T; 96 | 97 | setPluginSettings(settings: Partial): void; 98 | 99 | resetPluginSettings(): void; 100 | 101 | allContexts(): Record; 102 | 103 | contextsOf(action: string): string[]; 104 | 105 | registerDynamicView( 106 | suffix: string, 107 | profile: string 108 | ): { 109 | show: (device: Device) => void; 110 | hide: (device: string) => void; 111 | storeSettings: (device: string, context: string) => void; 112 | }; 113 | 114 | openUrl(url: string): void; 115 | 116 | logMessage(message: string): void; 117 | 118 | setTitle( 119 | context: string, 120 | title: string, 121 | options: { target: ActionTarget; state: ActionState } 122 | ): void; 123 | 124 | setImage( 125 | context: string, 126 | image: string, 127 | options: { target: ActionTarget; state: ActionState; useCache: boolean } 128 | ): void; 129 | 130 | showAlert(context: string): void; 131 | 132 | showOk(context: string): void; 133 | 134 | setState(context: string, state: ActionState): void; 135 | 136 | switchToProfile(context: string, device: string, profile: string): void; 137 | 138 | sendToPropertyInspector( 139 | context: string, 140 | action: string, 141 | payload: Record 142 | ): void; 143 | } 144 | 145 | export interface StreamDeckOptions { 146 | doubleTapMillis?: number; 147 | longPressMillis?: number; 148 | actions?: Record; 149 | } 150 | 151 | export interface IBaseAction { 152 | onAppear?: (_e: AppearDisappearEvent) => void; 153 | 154 | onDisappear?: (_e: AppearDisappearEvent) => void; 155 | 156 | onKeyDown?: (_e: KeyEvent) => void; 157 | 158 | onKeyUp?: (_e: KeyEvent) => void; 159 | 160 | onPeriodicUpdate?: () => void; 161 | 162 | onSettingsChanged?: (_e: SettingsChanged) => void; 163 | 164 | onPluginSettingsChanged?: (_e: PluginSettingsChanged) => void; 165 | 166 | onSingleTap?: (_e: KeyEvent) => void; 167 | 168 | onDoubleTap?: (_e: KeyEvent) => void; 169 | 170 | onLongPress?: (_e: KeyEvent) => void; 171 | 172 | onTitleParametersChanged?: (_e: TitleParametersDidChangeEvent) => void; 173 | 174 | onPropertyInspectorAppear?: (_e: PropertyInspectorEvent) => void; 175 | 176 | onPropertyInspectorDisappear?: (_e: PropertyInspectorEvent) => void; 177 | 178 | onMessageFromPropertyInspector?: ( 179 | _e: PropertyInspectorMessagingEvent 180 | ) => void; 181 | 182 | onApplicationLaunched?: (_e: ApplicationChangedEvent) => void; 183 | 184 | onApplicationTerminated?: (_e: ApplicationChangedEvent) => void; 185 | 186 | onDeviceConnected?: (_e: DeviceConnectionEvent) => void; 187 | 188 | onDeviceDisconnected?: (_e: DeviceDisconnectionEvent) => void; 189 | 190 | onSystemWakeUp?: () => void; 191 | } 192 | 193 | export interface IAction extends IBaseAction { 194 | uuid?: string; 195 | 196 | pluginUUID?: string; 197 | 198 | contexts: Set; 199 | } 200 | 201 | export interface AutoRunTimeUnits { 202 | h?: number; 203 | m?: number; 204 | s?: number; 205 | ms?: number; 206 | } 207 | 208 | export interface DeviceGeometryPositions { 209 | topLeft: number; 210 | topRight: number; 211 | bottomLeft: number; 212 | bottomRight: number; 213 | center?: number; // perfect 214 | approximatedCenter?: number; // approximated 215 | total: number; 216 | rows: number; 217 | columns: number; 218 | } 219 | 220 | export interface DeviceGeometry extends DeviceGeometryPositions { 221 | mappable: ( 222 | ...except: Exclude< 223 | keyof DeviceGeometryPositions, 224 | 'total' | 'rows' | 'columns' 225 | >[] 226 | ) => [number[], number]; 227 | } 228 | 229 | export interface DynamicCell { 230 | source?: any; 231 | title?: string; 232 | image?: string; 233 | onSingleTap?: () => void; 234 | onDoubleTap?: () => void; 235 | onLongPress?: () => void; 236 | data?: Record; 237 | } 238 | 239 | export interface DynamicViewInstance { 240 | settings: Record; 241 | view: DynamicViewMatrix; 242 | geometry: DeviceGeometry; 243 | page: number; 244 | nextPage: (maxPages: number) => boolean; 245 | prevPage: (alternative?: () => void) => boolean; 246 | clear: () => void; 247 | hide: () => void; 248 | update: (index: number, cell: DynamicCell) => void; 249 | onTapOutside: (cb: () => void) => void; 250 | cell: (coords: EventCoordinates) => DynamicCell | null; 251 | setSettings: (context: string, settings: any) => void; 252 | storeSettings: (context: string) => void; 253 | subscribe: ( 254 | coords: EventCoordinates, 255 | subscriber: (value: DynamicCell) => void, 256 | context: string 257 | ) => [DynamicCell | null, Subscription]; 258 | unsubscribe: (coords: EventCoordinates) => void; 259 | } 260 | 261 | // Single Index Matrix 262 | export type DynamicViewMatrix = Rx.BehaviorSubject[]; 263 | -------------------------------------------------------------------------------- /src/util/constant.ts: -------------------------------------------------------------------------------- 1 | export const aSecond = 1000; 2 | 3 | export const aMinute = 60 * aSecond; 4 | 5 | export const aHour = 60 * aMinute; 6 | -------------------------------------------------------------------------------- /src/util/image-helper.ts: -------------------------------------------------------------------------------- 1 | import { readFile } from 'fs/promises'; 2 | import axios from 'axios'; 3 | import mime from 'mime-types'; 4 | 5 | const cache = {}; 6 | 7 | const base64Image = async (file: string) => { 8 | // read binary data 9 | const bitmap = await readFile(file); 10 | // convert binary data to base64 encoded string 11 | cache[file] = Buffer.from(bitmap).toString('base64'); 12 | return cache[file]; 13 | }; 14 | 15 | const downloadBase64Image = async (url: string) => { 16 | // convert to base64 encoded string 17 | const res = await axios.get(url, { responseType: 'arraybuffer' }); 18 | // cache the result 19 | cache[url] = Buffer.from(res.data).toString('base64'); 20 | return cache[url]; 21 | }; 22 | 23 | // Convert url or file image to Base64 String 24 | export const imageToBase64 = async (image: string, useCache = false) => { 25 | if (useCache && cache[image]) { 26 | return cache[image]; 27 | } 28 | const [, type] = (mime.lookup(image.replace(/\?.+$/, '')) || '').split('/'); 29 | if (image.startsWith('http')) { 30 | image = await downloadBase64Image(image); 31 | } else { 32 | image = await base64Image(image); 33 | } 34 | return `data:image/${type};base64, ${image}`; 35 | }; 36 | -------------------------------------------------------------------------------- /tests/dev-index.ts: -------------------------------------------------------------------------------- 1 | import { StreamDeck } from "../src"; 2 | import { expect } from "chai"; 3 | import "./stream-deck-mock"; 4 | import { TEST_PLUGIN_ID, TEST_PLUGIN_UUID } from "./stream-deck-mock"; 5 | import { tmpdir } from "os"; 6 | import { writeFileSync } from "fs"; 7 | import { WebSocketServer } from "ws"; 8 | 9 | process.argv = ["node", "script.js", "-debug", TEST_PLUGIN_ID]; 10 | 11 | const fileConfig = `${tmpdir()}/${TEST_PLUGIN_ID}.dev.json`; 12 | 13 | new WebSocketServer({ port: 62800 }); 14 | 15 | writeFileSync(fileConfig, JSON.stringify({ 16 | "port": 62800, 17 | "pluginUUID": TEST_PLUGIN_UUID, 18 | "registerEvent": "registerPlugin", 19 | "info": { 20 | "application": {}, 21 | "colors": {}, 22 | "devicePixelRatio": 1, 23 | "devices": [], 24 | "plugin": { "uuid": TEST_PLUGIN_ID, "version": "1.0.0" } 25 | } 26 | })); 27 | 28 | export const sd = new StreamDeck(); 29 | 30 | describe("Checking development initialization", () => { 31 | 32 | it("Verify plugin UUID and plugin info from WS", () => { 33 | setTimeout(() => { 34 | expect(sd.uuid).to.equals(TEST_PLUGIN_UUID); 35 | expect(sd.info).to.be.not.null; 36 | expect(sd.info.plugin.uuid).to.equals(TEST_PLUGIN_ID); 37 | }, 200); 38 | }).slow("2s"); 39 | 40 | }); 41 | -------------------------------------------------------------------------------- /tests/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-deck-for-node/sdk/8b6c07d3680b5d35661a3194e56cb375c42a79a4/tests/image.png -------------------------------------------------------------------------------- /tests/index.ts: -------------------------------------------------------------------------------- 1 | import { StreamDeck } from "../src"; 2 | import chai, { expect } from "chai"; 3 | import "./stream-deck-mock"; 4 | import "./test-action-mock"; 5 | import { 6 | delay, 7 | emulateDoubleTap, 8 | emulateLongPress, 9 | emulateOnDisappear, 10 | emulateSetSettingFromPI, 11 | emulateSingleTap, 12 | sentEvents, 13 | TEST_ACTION_INSTANCE, 14 | TEST_PLUGIN_ID, 15 | TEST_PLUGIN_UUID 16 | } from "./stream-deck-mock"; 17 | import { TestActionMock } from "./test-action-mock"; 18 | import spies from "chai-spies"; 19 | 20 | chai.use(spies); 21 | 22 | process.argv = ["node", "script.js", 23 | "-port", "9999", 24 | "-registerEvent", "registerPlugin", 25 | "-pluginUUID", TEST_PLUGIN_UUID, 26 | "-info", `{"plugin": {"uuid": "${TEST_PLUGIN_ID}"}}` 27 | ]; 28 | 29 | export const sd = new StreamDeck(); 30 | 31 | describe("Checking initialization", () => { 32 | 33 | it("UUID and plugin info", () => { 34 | expect(sd.uuid).to.equals(TEST_PLUGIN_UUID); 35 | expect(sd.info).to.be.not.null; 36 | expect(sd.info.plugin.uuid).to.equals(TEST_PLUGIN_ID); 37 | }); 38 | 39 | it("Action registration", () => { 40 | expect(Object.keys(sd.actions)).to.contain("com.test.mocha.test-action"); 41 | expect(Object.keys(sd.actions)).to.length(1); 42 | }); 43 | 44 | }); 45 | 46 | // SPIES 47 | const action = Object.values(sd.actions)[0] as TestActionMock; 48 | chai.spy.on(action, "onPluginSettingsChanged"); 49 | chai.spy.on(action, "onSettingsChanged"); 50 | chai.spy.on(action, "onAppear"); 51 | chai.spy.on(action, "onDisappear"); 52 | chai.spy.on(action, "onSingleTap"); 53 | chai.spy.on(action, "onDoubleTap"); 54 | chai.spy.on(action, "onLongPress"); 55 | 56 | chai.spy.on(sd, "setTitle"); 57 | chai.spy.on(sd, "setImage"); 58 | chai.spy.on(sd, "setState"); 59 | chai.spy.on(sd, "showAlert"); 60 | chai.spy.on(sd, "showOk"); 61 | chai.spy.on(sd, "logMessage"); 62 | chai.spy.on(sd, "switchToProfile"); 63 | chai.spy.on(sd, "openUrl"); 64 | chai.spy.on(sd, "sendToPropertyInspector"); 65 | 66 | describe("Plugin Settings", () => { 67 | 68 | it("Obtain initial plugin settings", (done) => { 69 | const interval = setInterval(() => { 70 | if (!sentEvents.includes("didReceiveGlobalSettings")) return; 71 | clearInterval(interval); 72 | expect(Object.keys(sd.pluginSettings)).to.length(1); 73 | expect(sd.pluginSettings.sampleValue).to.equals(10); 74 | done(); 75 | }, 25); 76 | }).slow("1s"); 77 | 78 | it("Update plugin settings", () => { 79 | sd.setPluginSettings({ sampleValue: 11 }); 80 | expect(sd.pluginSettings.sampleValue).to.equals(11); 81 | }); 82 | 83 | it("Notify actions that the plugin settings changed", () => { 84 | expect(action.onPluginSettingsChanged).to.have.been.called(); 85 | }); 86 | 87 | }); 88 | 89 | 90 | describe("Instance Settings", () => { 91 | 92 | it("Emulate a settings change from Property Inspector", async () => { 93 | emulateSetSettingFromPI(); 94 | await delay(100); 95 | expect(action.onSettingsChanged).to.have.been.called(); 96 | }).slow("1s"); 97 | 98 | it("Verify and change the settings values", async () => { 99 | const instanceSettings: any = await sd.getSettings(TEST_ACTION_INSTANCE); 100 | expect(instanceSettings.instanceValue).to.equals(100); 101 | }); 102 | 103 | it("Change the instance settings", async () => { 104 | sd.setSettings(TEST_ACTION_INSTANCE, { instanceValue: 101 }); 105 | expect(action.onSettingsChanged).to.have.been.called.min(2); 106 | const instanceSettings: any = await sd.getSettings(TEST_ACTION_INSTANCE); 107 | expect(instanceSettings.instanceValue).to.equals(101); 108 | }); 109 | 110 | it("Verify the allContexts method", async () => { 111 | const contexts = sd.allContexts(); 112 | expect(Object.keys(contexts)).to.have.length(1); 113 | }); 114 | 115 | }); 116 | 117 | describe("Actions", () => { 118 | 119 | it("setImage called by onAppear", async () => { 120 | expect(sd.setImage).to.have.been.called(); 121 | }); 122 | 123 | it("setState called by onAppear", async () => { 124 | expect(sd.setState).to.have.been.called(); 125 | }); 126 | 127 | it("showOk called by onAppear", async () => { 128 | expect(sd.showOk).to.have.been.called(); 129 | }); 130 | 131 | it("showAlert called by onAppear", async () => { 132 | expect(sd.showAlert).to.have.been.called(); 133 | }); 134 | 135 | it("logMessage called by onAppear", async () => { 136 | expect(sd.logMessage).to.have.been.called(); 137 | }); 138 | 139 | it("switchToProfile called by onAppear", async () => { 140 | expect(sd.switchToProfile).to.have.been.called(); 141 | }); 142 | 143 | it("openUrl called by onAppear", async () => { 144 | expect(sd.openUrl).to.have.been.called(); 145 | }); 146 | 147 | it("sendToPropertyInspector called by onAppear", async () => { 148 | expect(sd.sendToPropertyInspector).to.have.been.called(); 149 | }); 150 | 151 | }); 152 | 153 | describe("Taps", () => { 154 | 155 | it("Verify the single tap event", async () => { 156 | await emulateSingleTap(); 157 | expect(action.onSingleTap).to.have.been.called(); 158 | }).slow("1s"); 159 | 160 | it("Verify the double tap event", async () => { 161 | await emulateDoubleTap(); 162 | expect(action.onDoubleTap).to.have.been.called(); 163 | }).slow("1s"); 164 | 165 | it("Verify the long press event", async () => { 166 | await emulateLongPress(); 167 | expect(action.onLongPress).to.have.been.called(); 168 | }).slow("2s"); 169 | 170 | }); 171 | 172 | describe("Events", () => { 173 | 174 | it("Verify that the onAppear was called", async () => { 175 | expect(action.onAppear).to.have.been.called(); 176 | }); 177 | 178 | it("Verify that the OnDisappear was called", async () => { 179 | await emulateOnDisappear(); 180 | expect(action.onDisappear).to.have.been.called(); 181 | }).slow('1s'); 182 | 183 | }); 184 | -------------------------------------------------------------------------------- /tests/stream-deck-mock.ts: -------------------------------------------------------------------------------- 1 | import WebSocket, { WebSocketServer } from "ws"; 2 | import { TextDecoder } from "util"; 3 | 4 | export const delay = (interval: number) => new Promise(done => setTimeout(done, interval)); 5 | 6 | export const TEST_PLUGIN_ID = "com.test.mocha"; 7 | export const TEST_ACTION_UUID = TEST_PLUGIN_ID + ".test-action"; 8 | export const TEST_PLUGIN_UUID = "GHRKSLVNSRIKJS"; 9 | export const TEST_ACTION_INSTANCE = "IFSIUYRLCHAE"; 10 | export const sentEvents: string[] = []; 11 | 12 | const pluginSettings: Record = { sampleValue: 10 }; 13 | 14 | const instancesSettings: Record> = { 15 | [TEST_ACTION_INSTANCE]: { instanceValue: 100 } 16 | }; 17 | 18 | const wss = new WebSocketServer({ port: 9999 }); 19 | 20 | const send = (data: any) => { 21 | sentEvents.push(data.event); 22 | const msg = JSON.stringify(data); 23 | wss.clients.forEach(client => { 24 | if (client.readyState === WebSocket.OPEN) { 25 | client.send(msg); 26 | } 27 | }); 28 | }; 29 | 30 | wss.on("connection", ws => { 31 | 32 | ws.on("message", (msg: any) => { 33 | 34 | let message; 35 | 36 | // try to decode ArrayBuffer 37 | try { 38 | message = new TextDecoder("utf-8").decode(Buffer.from(msg)); 39 | } catch (e) { 40 | message = msg; 41 | } 42 | 43 | const { event, ...eventParams } = JSON.parse(message); 44 | 45 | switch (event) { 46 | case "registerPlugin": 47 | send({ 48 | action: TEST_ACTION_UUID, 49 | context: TEST_ACTION_INSTANCE, 50 | event: "willAppear", 51 | payload: { 52 | settings: instancesSettings[eventParams.context] 53 | } 54 | }); 55 | break; 56 | case "getSettings": 57 | send({ 58 | action: TEST_ACTION_UUID, 59 | context: eventParams.context, 60 | event: "didReceiveSettings", 61 | payload: { 62 | settings: instancesSettings[eventParams.context] 63 | } 64 | }); 65 | break; 66 | case "setSettings": 67 | instancesSettings[eventParams.context] = eventParams.payload; 68 | break; 69 | case "getGlobalSettings": 70 | if (eventParams.context === TEST_PLUGIN_UUID) { 71 | send({ 72 | event: "didReceiveGlobalSettings", 73 | payload: { 74 | settings: pluginSettings 75 | } 76 | }); 77 | } 78 | break; 79 | } 80 | 81 | }); 82 | 83 | }); 84 | 85 | export const emulateSetSettingFromPI = () => { 86 | send({ 87 | context: TEST_ACTION_INSTANCE, 88 | action: TEST_ACTION_UUID, 89 | event: "didReceiveSettings", 90 | payload: { 91 | settings: instancesSettings[TEST_ACTION_INSTANCE] 92 | } 93 | }); 94 | }; 95 | 96 | const emulateKey = (keyType: string) => { 97 | send({ 98 | context: TEST_ACTION_INSTANCE, 99 | action: TEST_ACTION_UUID, 100 | event: `key${keyType[0].toUpperCase()}${keyType.slice(1)}` 101 | }); 102 | }; 103 | 104 | export const emulateSingleTap = async () => { 105 | emulateKey("down"); 106 | await delay(10); 107 | emulateKey("up"); 108 | await delay(400); 109 | }; 110 | 111 | export const emulateDoubleTap = async () => { 112 | emulateKey("down"); 113 | await delay(10); 114 | emulateKey("up"); 115 | await delay(50); 116 | emulateKey("down"); 117 | await delay(10); 118 | emulateKey("up"); 119 | await delay(350); 120 | }; 121 | 122 | export const emulateLongPress = async () => { 123 | emulateKey("down"); 124 | await delay(700); 125 | emulateKey("up"); 126 | await delay(100); 127 | }; 128 | 129 | export const emulateOnDisappear = async () => { 130 | send({ 131 | event: "willDisappear", 132 | context: TEST_ACTION_INSTANCE, 133 | action: TEST_ACTION_UUID, 134 | payload: { 135 | settings: instancesSettings[TEST_ACTION_INSTANCE] 136 | } 137 | }); 138 | await delay(150); 139 | }; 140 | -------------------------------------------------------------------------------- /tests/test-action-mock.ts: -------------------------------------------------------------------------------- 1 | import { join } from "path"; 2 | import { Action, AppearDisappearEvent, BaseAction, KeyEvent } from "../src"; 3 | import { sd } from "./index"; 4 | import { TEST_ACTION_UUID } from "./stream-deck-mock"; 5 | 6 | @Action("test-action") 7 | export class TestActionMock extends BaseAction { 8 | 9 | onDisappear() { 10 | // trigger 11 | } 12 | 13 | onAppear(e: AppearDisappearEvent) { 14 | sd.setTitle(e.context, "Test Title"); 15 | sd.setImage(e.context, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII="); 16 | sd.setImage(e.context, "https://www.pngkey.com/png/detail/178-1787508_github-icon-download-at-icons8-white-github-icon.png"); 17 | sd.setImage(e.context, "https://www.pngkey.com/png/detail/178-1787508_github-icon-download-at-icons8-white-github-icon.png"); 18 | sd.setImage(e.context, join(__dirname, "/image.png")); 19 | sd.setState(e.context, 1); 20 | sd.showAlert(e.context); 21 | sd.showOk(e.context); 22 | sd.logMessage("message"); 23 | sd.switchToProfile(e.context, "DEVICE_ID", "PROFILE_ID"); 24 | sd.openUrl("https://github.com"); 25 | sd.sendToPropertyInspector(e.context, TEST_ACTION_UUID, { content: "" }); 26 | } 27 | 28 | onSingleTap(e: KeyEvent) { 29 | sd.setTitle(e.context, "onSingleTap"); 30 | } 31 | 32 | onDoubleTap(e: KeyEvent) { 33 | sd.setTitle(e.context, "onDoubleTap"); 34 | } 35 | 36 | onLongPress(e: KeyEvent) { 37 | sd.setTitle(e.context, "onLongPress"); 38 | } 39 | 40 | onPluginSettingsChanged() { 41 | // trigger 42 | } 43 | 44 | onSettingsChanged() { 45 | // trigger 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": false, 4 | "outDir": "lib/esm", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "lib": ["es6", "es2016", "es2017"], 8 | "declaration": true, 9 | "moduleResolution": "node", 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "esModuleInterop": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | "noImplicitAny": true, 18 | "strictNullChecks": true, 19 | "suppressImplicitAnyIndexErrors": true, 20 | "allowSyntheticDefaultImports": true 21 | }, 22 | "include": ["**/*"], 23 | "exclude": [] 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": false, 4 | "outDir": "lib/esm", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "lib": ["es6", "es2016", "es2017"], 8 | "rootDir": "./src", 9 | "declaration": true, 10 | "moduleResolution": "node", 11 | "noUnusedLocals": true, 12 | "noUnusedParameters": true, 13 | "experimentalDecorators": true, 14 | "emitDecoratorMetadata": true, 15 | "esModuleInterop": true, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noImplicitAny": true, 19 | "strictNullChecks": true, 20 | "suppressImplicitAnyIndexErrors": true, 21 | "allowSyntheticDefaultImports": true 22 | }, 23 | "include": ["**/*"], 24 | "exclude": ["node_modules", "lib", "tests"] 25 | } 26 | --------------------------------------------------------------------------------