├── .eslintrc.json ├── .gitignore ├── .idea └── copyright │ ├── Copyright.xml │ └── profiles_settings.xml ├── .prettierrc.json ├── LICENSE ├── README.md ├── britmoji-made-it.png ├── package.json ├── pnpm-lock.yaml ├── src ├── constants.ts ├── index.tsx ├── routes │ ├── embed.ts │ ├── index.ts │ ├── meta.ts │ └── tiktok.tsx ├── types │ └── cloudflare.ts └── util │ ├── discord.tsx │ ├── http.ts │ ├── math.ts │ ├── numbers.ts │ └── tiktok.ts ├── tsconfig.json └── wrangler.toml /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "node": true, 5 | "es6": true 6 | }, 7 | "ignorePatterns": [ 8 | "node_modules/*", 9 | "src/generated/*" 10 | ], 11 | "extends": [ 12 | "eslint:recommended" 13 | ], 14 | "overrides": [ 15 | { 16 | "files": [ 17 | "**/*.{ts,tsx}" 18 | ], 19 | "parser": "@typescript-eslint/parser", 20 | "extends": [ 21 | "eslint:recommended", 22 | "plugin:@typescript-eslint/recommended", 23 | "plugin:prettier/recommended" 24 | ], 25 | "rules": { 26 | "prettier/prettier": [ 27 | "error", 28 | {}, 29 | { 30 | "usePrettierrc": true 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | 3 | logs 4 | _.log 5 | npm-debug.log_ 6 | yarn-debug.log* 7 | yarn-error.log* 8 | lerna-debug.log* 9 | .pnpm-debug.log* 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | 13 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 14 | 15 | # Runtime data 16 | 17 | pids 18 | _.pid 19 | _.seed 20 | \*.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | 28 | coverage 29 | \*.lcov 30 | 31 | # nyc test coverage 32 | 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 | 37 | .grunt 38 | 39 | # Bower dependency directory (https://bower.io/) 40 | 41 | bower_components 42 | 43 | # node-waf configuration 44 | 45 | .lock-wscript 46 | 47 | # Compiled binary addons (https://nodejs.org/api/addons.html) 48 | 49 | build/Release 50 | 51 | # Dependency directories 52 | 53 | node_modules/ 54 | jspm_packages/ 55 | 56 | # Snowpack dependency directory (https://snowpack.dev/) 57 | 58 | web_modules/ 59 | 60 | # TypeScript cache 61 | 62 | \*.tsbuildinfo 63 | 64 | # Optional npm cache directory 65 | 66 | .npm 67 | 68 | # Optional eslint cache 69 | 70 | .eslintcache 71 | 72 | # Optional stylelint cache 73 | 74 | .stylelintcache 75 | 76 | # Microbundle cache 77 | 78 | .rpt2_cache/ 79 | .rts2_cache_cjs/ 80 | .rts2_cache_es/ 81 | .rts2_cache_umd/ 82 | 83 | # Optional REPL history 84 | 85 | .node_repl_history 86 | 87 | # Output of 'npm pack' 88 | 89 | \*.tgz 90 | 91 | # Yarn Integrity file 92 | 93 | .yarn-integrity 94 | 95 | # dotenv environment variable files 96 | 97 | .env 98 | .env.development.local 99 | .env.test.local 100 | .env.production.local 101 | .env.local 102 | 103 | # parcel-bundler cache (https://parceljs.org/) 104 | 105 | .cache 106 | .parcel-cache 107 | 108 | # Next.js build output 109 | 110 | .next 111 | out 112 | 113 | # Nuxt.js build / generate output 114 | 115 | .nuxt 116 | dist 117 | 118 | # Gatsby files 119 | 120 | .cache/ 121 | 122 | # Comment in the public line in if your project uses Gatsby and not Next.js 123 | 124 | # https://nextjs.org/blog/next-9-1#public-directory-support 125 | 126 | # public 127 | 128 | # vuepress build output 129 | 130 | .vuepress/dist 131 | 132 | # vuepress v2.x temp and cache directory 133 | 134 | .temp 135 | .cache 136 | 137 | # Docusaurus cache and generated files 138 | 139 | .docusaurus 140 | 141 | # Serverless directories 142 | 143 | .serverless/ 144 | 145 | # FuseBox cache 146 | 147 | .fusebox/ 148 | 149 | # DynamoDB Local files 150 | 151 | .dynamodb/ 152 | 153 | # TernJS port file 154 | 155 | .tern-port 156 | 157 | # Stores VSCode versions used for testing VSCode extensions 158 | 159 | .vscode-test 160 | 161 | # yarn v2 162 | 163 | .yarn/cache 164 | .yarn/unplugged 165 | .yarn/build-state.yml 166 | .yarn/install-state.gz 167 | .pnp.\* 168 | 169 | # wrangler project 170 | 171 | .wrangler 172 | .dev.vars 173 | 174 | # idea 175 | .idea/* 176 | !.idea/copyright -------------------------------------------------------------------------------- /.idea/copyright/Copyright.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "useTabs": false, 7 | "endOfLine": "auto" 8 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 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 Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | tiktxk - Open Source, Privacy First TikTok Downloader 633 | Copyright (C) 2022 Britmoji 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # tiktxk 4 | 5 | An open source, privacy first Cloudflare Worker for generating embeddable TikTok links. 6 | 7 | Replace the o with x and you'll get served the video! 8 | 9 | Before: 10 | https://www.tiktok.com/@mxmtoon/video/7354154112285527339 11 | 12 | After: 13 | https://www.tiktxk.com/@mxmtoon/video/7354154112285527339 14 | 15 | --- 16 | 17 | brought to you by [britmoji](https://britmoji.org) :) 18 | 19 | support: https://github.com/Britmoji/tiktxk/issues/new 20 | 21 | [*uptime guaranteed. if not, you've probably got bigger problems...*](https://www.cloudflarestatus.com/) -------------------------------------------------------------------------------- /britmoji-made-it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Britmoji/tiktxk/c5e189f7fb792b88c823b89be876da1769726231/britmoji-made-it.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tiktxk", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "An open source, privacy first Cloudflare Worker for generating embeddable TikTok links.", 6 | "license": "AGPL-3.0-or-later", 7 | "scripts": { 8 | "start": "wrangler dev", 9 | "deploy": "wrangler deploy", 10 | "tunnel": "cloudflared tunnel run --url http://127.0.0.1:8787", 11 | "lint:fix": "pnpm --silent lint:prettier:fix && pnpm --silent lint:eslint:fix", 12 | "lint:prettier:fix": "prettier -w \"src/**/*.{js,jsx,ts,tsx}\" -u", 13 | "lint:eslint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"" 14 | }, 15 | "devDependencies": { 16 | "@cloudflare/workers-types": "^4.20240405.0", 17 | "@eslint/js": "^9.0.0", 18 | "@typescript-eslint/eslint-plugin": "^7.6.0", 19 | "@typescript-eslint/parser": "^7.6.0", 20 | "eslint": "^8.57.0", 21 | "eslint-config-prettier": "^8.10.0", 22 | "eslint-plugin-prettier": "^5.1.3", 23 | "prettier": "^3.2.5", 24 | "typescript": "^5.4.5", 25 | "typescript-eslint": "^7.6.0", 26 | "wrangler": "^3.50.0" 27 | }, 28 | "homepage": "https://github.com/Britmoji/tiktxk#readme", 29 | "author": "Britmoji Incorporated ", 30 | "repository": { 31 | "type": "git", 32 | "url": "git+https://github.com/Britmoji/tiktxk.git" 33 | }, 34 | "bugs": { 35 | "url": "https://github.com/Britmoji/tiktxk/issues" 36 | }, 37 | "dependencies": { 38 | "hono": "^4.2.4", 39 | "toucan-js": "^3.3.1", 40 | "uuid": "^9.0.1" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | hono: 9 | specifier: ^4.2.4 10 | version: 4.2.4 11 | toucan-js: 12 | specifier: ^3.3.1 13 | version: 3.3.1 14 | uuid: 15 | specifier: ^9.0.1 16 | version: 9.0.1 17 | 18 | devDependencies: 19 | '@cloudflare/workers-types': 20 | specifier: ^4.20240405.0 21 | version: 4.20240405.0 22 | '@eslint/js': 23 | specifier: ^9.0.0 24 | version: 9.0.0 25 | '@typescript-eslint/eslint-plugin': 26 | specifier: ^7.6.0 27 | version: 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@9.0.0)(typescript@5.4.5) 28 | '@typescript-eslint/parser': 29 | specifier: ^7.6.0 30 | version: 7.6.0(eslint@9.0.0)(typescript@5.4.5) 31 | eslint: 32 | specifier: ^9.0.0 33 | version: 9.0.0 34 | eslint-config-prettier: 35 | specifier: ^9.1.0 36 | version: 9.1.0(eslint@9.0.0) 37 | eslint-plugin-prettier: 38 | specifier: ^5.1.3 39 | version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@9.0.0)(prettier@3.2.5) 40 | prettier: 41 | specifier: ^3.2.5 42 | version: 3.2.5 43 | typescript: 44 | specifier: ^5.4.5 45 | version: 5.4.5 46 | typescript-eslint: 47 | specifier: ^7.6.0 48 | version: 7.6.0(eslint@9.0.0)(typescript@5.4.5) 49 | wrangler: 50 | specifier: ^3.50.0 51 | version: 3.50.0(@cloudflare/workers-types@4.20240405.0) 52 | 53 | packages: 54 | 55 | /@aashutoshrathi/word-wrap@1.2.6: 56 | resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 57 | engines: {node: '>=0.10.0'} 58 | dev: true 59 | 60 | /@cloudflare/kv-asset-handler@0.3.1: 61 | resolution: {integrity: sha512-lKN2XCfKCmpKb86a1tl4GIwsJYDy9TGuwjhDELLmpKygQhw8X2xR4dusgpC5Tg7q1pB96Eb0rBo81kxSILQMwA==} 62 | dependencies: 63 | mime: 3.0.0 64 | dev: true 65 | 66 | /@cloudflare/workerd-darwin-64@1.20240405.0: 67 | resolution: {integrity: sha512-ut8kwpHmlz9dNSjoov6v1b6jS50J46Mj9QcMA0t1Hne36InaQk/qqPSd12fN5p2GesZ9OOBJvBdDsTblVdyJ1w==} 68 | engines: {node: '>=16'} 69 | cpu: [x64] 70 | os: [darwin] 71 | requiresBuild: true 72 | dev: true 73 | optional: true 74 | 75 | /@cloudflare/workerd-darwin-arm64@1.20240405.0: 76 | resolution: {integrity: sha512-x3A3Ym+J2DH1uYnw0aedeKOTnUebEo312+Aladv7bFri97pjRJcqVbYhMtOHLkHjwYn7bpKSY2eL5iM+0XT29A==} 77 | engines: {node: '>=16'} 78 | cpu: [arm64] 79 | os: [darwin] 80 | requiresBuild: true 81 | dev: true 82 | optional: true 83 | 84 | /@cloudflare/workerd-linux-64@1.20240405.0: 85 | resolution: {integrity: sha512-3tYpfjtxEQ0R30Pna7OF3Bz0CTx30hc0QNtH61KnkvXtaeYMkWutSKQKXIuVlPa/7v1MHp+8ViBXMflmS7HquA==} 86 | engines: {node: '>=16'} 87 | cpu: [x64] 88 | os: [linux] 89 | requiresBuild: true 90 | dev: true 91 | optional: true 92 | 93 | /@cloudflare/workerd-linux-arm64@1.20240405.0: 94 | resolution: {integrity: sha512-NpKZlvmdgcX/m4tP5zM91AfJpZrue2/GRA+Sl3szxAivu2uE5jDVf5SS9dzqzCVfPrdhylqH7yeL4U/cafFNOg==} 95 | engines: {node: '>=16'} 96 | cpu: [arm64] 97 | os: [linux] 98 | requiresBuild: true 99 | dev: true 100 | optional: true 101 | 102 | /@cloudflare/workerd-windows-64@1.20240405.0: 103 | resolution: {integrity: sha512-REBeJMxvUCjwuEVzSSIBtzAyM69QjToab8qBst0S9vdih+9DObym4dw8CevdBQhDbFrHiyL9E6pAZpLPNHVgCw==} 104 | engines: {node: '>=16'} 105 | cpu: [x64] 106 | os: [win32] 107 | requiresBuild: true 108 | dev: true 109 | optional: true 110 | 111 | /@cloudflare/workers-types@4.20240405.0: 112 | resolution: {integrity: sha512-sEVOhyOgXUwfLkgHqbLZa/sfkSYrh7/zLmI6EZNibPaVPvAnAcItbNNl3SAlLyLKuwf8m4wAIAgu9meKWCvXjg==} 113 | dev: true 114 | 115 | /@cspotcode/source-map-support@0.8.1: 116 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 117 | engines: {node: '>=12'} 118 | dependencies: 119 | '@jridgewell/trace-mapping': 0.3.9 120 | dev: true 121 | 122 | /@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19): 123 | resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} 124 | peerDependencies: 125 | esbuild: '*' 126 | dependencies: 127 | esbuild: 0.17.19 128 | dev: true 129 | 130 | /@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19): 131 | resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} 132 | peerDependencies: 133 | esbuild: '*' 134 | dependencies: 135 | esbuild: 0.17.19 136 | escape-string-regexp: 4.0.0 137 | rollup-plugin-node-polyfills: 0.2.1 138 | dev: true 139 | 140 | /@esbuild/android-arm64@0.17.19: 141 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} 142 | engines: {node: '>=12'} 143 | cpu: [arm64] 144 | os: [android] 145 | requiresBuild: true 146 | dev: true 147 | optional: true 148 | 149 | /@esbuild/android-arm@0.17.19: 150 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} 151 | engines: {node: '>=12'} 152 | cpu: [arm] 153 | os: [android] 154 | requiresBuild: true 155 | dev: true 156 | optional: true 157 | 158 | /@esbuild/android-x64@0.17.19: 159 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} 160 | engines: {node: '>=12'} 161 | cpu: [x64] 162 | os: [android] 163 | requiresBuild: true 164 | dev: true 165 | optional: true 166 | 167 | /@esbuild/darwin-arm64@0.17.19: 168 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} 169 | engines: {node: '>=12'} 170 | cpu: [arm64] 171 | os: [darwin] 172 | requiresBuild: true 173 | dev: true 174 | optional: true 175 | 176 | /@esbuild/darwin-x64@0.17.19: 177 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} 178 | engines: {node: '>=12'} 179 | cpu: [x64] 180 | os: [darwin] 181 | requiresBuild: true 182 | dev: true 183 | optional: true 184 | 185 | /@esbuild/freebsd-arm64@0.17.19: 186 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} 187 | engines: {node: '>=12'} 188 | cpu: [arm64] 189 | os: [freebsd] 190 | requiresBuild: true 191 | dev: true 192 | optional: true 193 | 194 | /@esbuild/freebsd-x64@0.17.19: 195 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} 196 | engines: {node: '>=12'} 197 | cpu: [x64] 198 | os: [freebsd] 199 | requiresBuild: true 200 | dev: true 201 | optional: true 202 | 203 | /@esbuild/linux-arm64@0.17.19: 204 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} 205 | engines: {node: '>=12'} 206 | cpu: [arm64] 207 | os: [linux] 208 | requiresBuild: true 209 | dev: true 210 | optional: true 211 | 212 | /@esbuild/linux-arm@0.17.19: 213 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} 214 | engines: {node: '>=12'} 215 | cpu: [arm] 216 | os: [linux] 217 | requiresBuild: true 218 | dev: true 219 | optional: true 220 | 221 | /@esbuild/linux-ia32@0.17.19: 222 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} 223 | engines: {node: '>=12'} 224 | cpu: [ia32] 225 | os: [linux] 226 | requiresBuild: true 227 | dev: true 228 | optional: true 229 | 230 | /@esbuild/linux-loong64@0.17.19: 231 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} 232 | engines: {node: '>=12'} 233 | cpu: [loong64] 234 | os: [linux] 235 | requiresBuild: true 236 | dev: true 237 | optional: true 238 | 239 | /@esbuild/linux-mips64el@0.17.19: 240 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} 241 | engines: {node: '>=12'} 242 | cpu: [mips64el] 243 | os: [linux] 244 | requiresBuild: true 245 | dev: true 246 | optional: true 247 | 248 | /@esbuild/linux-ppc64@0.17.19: 249 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} 250 | engines: {node: '>=12'} 251 | cpu: [ppc64] 252 | os: [linux] 253 | requiresBuild: true 254 | dev: true 255 | optional: true 256 | 257 | /@esbuild/linux-riscv64@0.17.19: 258 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} 259 | engines: {node: '>=12'} 260 | cpu: [riscv64] 261 | os: [linux] 262 | requiresBuild: true 263 | dev: true 264 | optional: true 265 | 266 | /@esbuild/linux-s390x@0.17.19: 267 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} 268 | engines: {node: '>=12'} 269 | cpu: [s390x] 270 | os: [linux] 271 | requiresBuild: true 272 | dev: true 273 | optional: true 274 | 275 | /@esbuild/linux-x64@0.17.19: 276 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} 277 | engines: {node: '>=12'} 278 | cpu: [x64] 279 | os: [linux] 280 | requiresBuild: true 281 | dev: true 282 | optional: true 283 | 284 | /@esbuild/netbsd-x64@0.17.19: 285 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} 286 | engines: {node: '>=12'} 287 | cpu: [x64] 288 | os: [netbsd] 289 | requiresBuild: true 290 | dev: true 291 | optional: true 292 | 293 | /@esbuild/openbsd-x64@0.17.19: 294 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} 295 | engines: {node: '>=12'} 296 | cpu: [x64] 297 | os: [openbsd] 298 | requiresBuild: true 299 | dev: true 300 | optional: true 301 | 302 | /@esbuild/sunos-x64@0.17.19: 303 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} 304 | engines: {node: '>=12'} 305 | cpu: [x64] 306 | os: [sunos] 307 | requiresBuild: true 308 | dev: true 309 | optional: true 310 | 311 | /@esbuild/win32-arm64@0.17.19: 312 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} 313 | engines: {node: '>=12'} 314 | cpu: [arm64] 315 | os: [win32] 316 | requiresBuild: true 317 | dev: true 318 | optional: true 319 | 320 | /@esbuild/win32-ia32@0.17.19: 321 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} 322 | engines: {node: '>=12'} 323 | cpu: [ia32] 324 | os: [win32] 325 | requiresBuild: true 326 | dev: true 327 | optional: true 328 | 329 | /@esbuild/win32-x64@0.17.19: 330 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} 331 | engines: {node: '>=12'} 332 | cpu: [x64] 333 | os: [win32] 334 | requiresBuild: true 335 | dev: true 336 | optional: true 337 | 338 | /@eslint-community/eslint-utils@4.4.0(eslint@9.0.0): 339 | resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 340 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 341 | peerDependencies: 342 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 343 | dependencies: 344 | eslint: 9.0.0 345 | eslint-visitor-keys: 3.4.3 346 | dev: true 347 | 348 | /@eslint-community/regexpp@4.10.0: 349 | resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} 350 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 351 | dev: true 352 | 353 | /@eslint/eslintrc@3.0.2: 354 | resolution: {integrity: sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==} 355 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 356 | dependencies: 357 | ajv: 6.12.6 358 | debug: 4.3.4 359 | espree: 10.0.1 360 | globals: 14.0.0 361 | ignore: 5.3.1 362 | import-fresh: 3.3.0 363 | js-yaml: 4.1.0 364 | minimatch: 3.1.2 365 | strip-json-comments: 3.1.1 366 | transitivePeerDependencies: 367 | - supports-color 368 | dev: true 369 | 370 | /@eslint/js@9.0.0: 371 | resolution: {integrity: sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==} 372 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 373 | dev: true 374 | 375 | /@fastify/busboy@2.1.1: 376 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 377 | engines: {node: '>=14'} 378 | dev: true 379 | 380 | /@humanwhocodes/config-array@0.12.3: 381 | resolution: {integrity: sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==} 382 | engines: {node: '>=10.10.0'} 383 | dependencies: 384 | '@humanwhocodes/object-schema': 2.0.3 385 | debug: 4.3.4 386 | minimatch: 3.1.2 387 | transitivePeerDependencies: 388 | - supports-color 389 | dev: true 390 | 391 | /@humanwhocodes/module-importer@1.0.1: 392 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 393 | engines: {node: '>=12.22'} 394 | dev: true 395 | 396 | /@humanwhocodes/object-schema@2.0.3: 397 | resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} 398 | dev: true 399 | 400 | /@jridgewell/resolve-uri@3.1.2: 401 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 402 | engines: {node: '>=6.0.0'} 403 | dev: true 404 | 405 | /@jridgewell/sourcemap-codec@1.4.15: 406 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 407 | dev: true 408 | 409 | /@jridgewell/trace-mapping@0.3.9: 410 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 411 | dependencies: 412 | '@jridgewell/resolve-uri': 3.1.2 413 | '@jridgewell/sourcemap-codec': 1.4.15 414 | dev: true 415 | 416 | /@nodelib/fs.scandir@2.1.5: 417 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 418 | engines: {node: '>= 8'} 419 | dependencies: 420 | '@nodelib/fs.stat': 2.0.5 421 | run-parallel: 1.2.0 422 | dev: true 423 | 424 | /@nodelib/fs.stat@2.0.5: 425 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 426 | engines: {node: '>= 8'} 427 | dev: true 428 | 429 | /@nodelib/fs.walk@1.2.8: 430 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 431 | engines: {node: '>= 8'} 432 | dependencies: 433 | '@nodelib/fs.scandir': 2.1.5 434 | fastq: 1.17.1 435 | dev: true 436 | 437 | /@pkgr/core@0.1.1: 438 | resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} 439 | engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} 440 | dev: true 441 | 442 | /@sentry/core@7.76.0: 443 | resolution: {integrity: sha512-M+ptkCTeCNf6fn7p2MmEb1Wd9/JXUWxIT/0QEc+t11DNR4FYy1ZP2O9Zb3Zp2XacO7ORrlL3Yc+VIfl5JTgjfw==} 444 | engines: {node: '>=8'} 445 | dependencies: 446 | '@sentry/types': 7.76.0 447 | '@sentry/utils': 7.76.0 448 | dev: false 449 | 450 | /@sentry/integrations@7.76.0: 451 | resolution: {integrity: sha512-4ea0PNZrGN9wKuE/8bBCRrxxw4Cq5T710y8rhdKHAlSUpbLqr/atRF53h8qH3Fi+ec0m38PB+MivKem9zUwlwA==} 452 | engines: {node: '>=8'} 453 | dependencies: 454 | '@sentry/core': 7.76.0 455 | '@sentry/types': 7.76.0 456 | '@sentry/utils': 7.76.0 457 | localforage: 1.10.0 458 | dev: false 459 | 460 | /@sentry/types@7.76.0: 461 | resolution: {integrity: sha512-vj6z+EAbVrKAXmJPxSv/clpwS9QjPqzkraMFk2hIdE/kii8s8kwnkBwTSpIrNc8GnzV3qYC4r3qD+BXDxAGPaw==} 462 | engines: {node: '>=8'} 463 | dev: false 464 | 465 | /@sentry/utils@7.76.0: 466 | resolution: {integrity: sha512-40jFD+yfQaKpFYINghdhovzec4IEpB7aAuyH/GtE7E0gLpcqnC72r55krEIVILfqIR2Mlr5OKUzyeoCyWAU/yw==} 467 | engines: {node: '>=8'} 468 | dependencies: 469 | '@sentry/types': 7.76.0 470 | dev: false 471 | 472 | /@types/json-schema@7.0.15: 473 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 474 | dev: true 475 | 476 | /@types/node-forge@1.3.11: 477 | resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} 478 | dependencies: 479 | '@types/node': 20.11.27 480 | dev: true 481 | 482 | /@types/node@20.11.27: 483 | resolution: {integrity: sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==} 484 | dependencies: 485 | undici-types: 5.26.5 486 | dev: true 487 | 488 | /@types/semver@7.5.8: 489 | resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} 490 | dev: true 491 | 492 | /@typescript-eslint/eslint-plugin@7.6.0(@typescript-eslint/parser@7.6.0)(eslint@9.0.0)(typescript@5.4.5): 493 | resolution: {integrity: sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==} 494 | engines: {node: ^18.18.0 || >=20.0.0} 495 | peerDependencies: 496 | '@typescript-eslint/parser': ^7.0.0 497 | eslint: ^8.56.0 498 | typescript: '*' 499 | peerDependenciesMeta: 500 | typescript: 501 | optional: true 502 | dependencies: 503 | '@eslint-community/regexpp': 4.10.0 504 | '@typescript-eslint/parser': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 505 | '@typescript-eslint/scope-manager': 7.6.0 506 | '@typescript-eslint/type-utils': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 507 | '@typescript-eslint/utils': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 508 | '@typescript-eslint/visitor-keys': 7.6.0 509 | debug: 4.3.4 510 | eslint: 9.0.0 511 | graphemer: 1.4.0 512 | ignore: 5.3.1 513 | natural-compare: 1.4.0 514 | semver: 7.6.0 515 | ts-api-utils: 1.3.0(typescript@5.4.5) 516 | typescript: 5.4.5 517 | transitivePeerDependencies: 518 | - supports-color 519 | dev: true 520 | 521 | /@typescript-eslint/parser@7.6.0(eslint@9.0.0)(typescript@5.4.5): 522 | resolution: {integrity: sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==} 523 | engines: {node: ^18.18.0 || >=20.0.0} 524 | peerDependencies: 525 | eslint: ^8.56.0 526 | typescript: '*' 527 | peerDependenciesMeta: 528 | typescript: 529 | optional: true 530 | dependencies: 531 | '@typescript-eslint/scope-manager': 7.6.0 532 | '@typescript-eslint/types': 7.6.0 533 | '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) 534 | '@typescript-eslint/visitor-keys': 7.6.0 535 | debug: 4.3.4 536 | eslint: 9.0.0 537 | typescript: 5.4.5 538 | transitivePeerDependencies: 539 | - supports-color 540 | dev: true 541 | 542 | /@typescript-eslint/scope-manager@7.6.0: 543 | resolution: {integrity: sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==} 544 | engines: {node: ^18.18.0 || >=20.0.0} 545 | dependencies: 546 | '@typescript-eslint/types': 7.6.0 547 | '@typescript-eslint/visitor-keys': 7.6.0 548 | dev: true 549 | 550 | /@typescript-eslint/type-utils@7.6.0(eslint@9.0.0)(typescript@5.4.5): 551 | resolution: {integrity: sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==} 552 | engines: {node: ^18.18.0 || >=20.0.0} 553 | peerDependencies: 554 | eslint: ^8.56.0 555 | typescript: '*' 556 | peerDependenciesMeta: 557 | typescript: 558 | optional: true 559 | dependencies: 560 | '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) 561 | '@typescript-eslint/utils': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 562 | debug: 4.3.4 563 | eslint: 9.0.0 564 | ts-api-utils: 1.3.0(typescript@5.4.5) 565 | typescript: 5.4.5 566 | transitivePeerDependencies: 567 | - supports-color 568 | dev: true 569 | 570 | /@typescript-eslint/types@7.6.0: 571 | resolution: {integrity: sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==} 572 | engines: {node: ^18.18.0 || >=20.0.0} 573 | dev: true 574 | 575 | /@typescript-eslint/typescript-estree@7.6.0(typescript@5.4.5): 576 | resolution: {integrity: sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==} 577 | engines: {node: ^18.18.0 || >=20.0.0} 578 | peerDependencies: 579 | typescript: '*' 580 | peerDependenciesMeta: 581 | typescript: 582 | optional: true 583 | dependencies: 584 | '@typescript-eslint/types': 7.6.0 585 | '@typescript-eslint/visitor-keys': 7.6.0 586 | debug: 4.3.4 587 | globby: 11.1.0 588 | is-glob: 4.0.3 589 | minimatch: 9.0.4 590 | semver: 7.6.0 591 | ts-api-utils: 1.3.0(typescript@5.4.5) 592 | typescript: 5.4.5 593 | transitivePeerDependencies: 594 | - supports-color 595 | dev: true 596 | 597 | /@typescript-eslint/utils@7.6.0(eslint@9.0.0)(typescript@5.4.5): 598 | resolution: {integrity: sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==} 599 | engines: {node: ^18.18.0 || >=20.0.0} 600 | peerDependencies: 601 | eslint: ^8.56.0 602 | dependencies: 603 | '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0) 604 | '@types/json-schema': 7.0.15 605 | '@types/semver': 7.5.8 606 | '@typescript-eslint/scope-manager': 7.6.0 607 | '@typescript-eslint/types': 7.6.0 608 | '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) 609 | eslint: 9.0.0 610 | semver: 7.6.0 611 | transitivePeerDependencies: 612 | - supports-color 613 | - typescript 614 | dev: true 615 | 616 | /@typescript-eslint/visitor-keys@7.6.0: 617 | resolution: {integrity: sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==} 618 | engines: {node: ^18.18.0 || >=20.0.0} 619 | dependencies: 620 | '@typescript-eslint/types': 7.6.0 621 | eslint-visitor-keys: 3.4.3 622 | dev: true 623 | 624 | /acorn-jsx@5.3.2(acorn@8.11.3): 625 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 626 | peerDependencies: 627 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 628 | dependencies: 629 | acorn: 8.11.3 630 | dev: true 631 | 632 | /acorn-walk@8.3.2: 633 | resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} 634 | engines: {node: '>=0.4.0'} 635 | dev: true 636 | 637 | /acorn@8.11.3: 638 | resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} 639 | engines: {node: '>=0.4.0'} 640 | hasBin: true 641 | dev: true 642 | 643 | /ajv@6.12.6: 644 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 645 | dependencies: 646 | fast-deep-equal: 3.1.3 647 | fast-json-stable-stringify: 2.1.0 648 | json-schema-traverse: 0.4.1 649 | uri-js: 4.4.1 650 | dev: true 651 | 652 | /ansi-regex@5.0.1: 653 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 654 | engines: {node: '>=8'} 655 | dev: true 656 | 657 | /ansi-styles@4.3.0: 658 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 659 | engines: {node: '>=8'} 660 | dependencies: 661 | color-convert: 2.0.1 662 | dev: true 663 | 664 | /anymatch@3.1.3: 665 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 666 | engines: {node: '>= 8'} 667 | dependencies: 668 | normalize-path: 3.0.0 669 | picomatch: 2.3.1 670 | dev: true 671 | 672 | /argparse@2.0.1: 673 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 674 | dev: true 675 | 676 | /array-union@2.1.0: 677 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 678 | engines: {node: '>=8'} 679 | dev: true 680 | 681 | /as-table@1.0.55: 682 | resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} 683 | dependencies: 684 | printable-characters: 1.0.42 685 | dev: true 686 | 687 | /balanced-match@1.0.2: 688 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 689 | dev: true 690 | 691 | /binary-extensions@2.3.0: 692 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 693 | engines: {node: '>=8'} 694 | dev: true 695 | 696 | /blake3-wasm@2.1.5: 697 | resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} 698 | dev: true 699 | 700 | /brace-expansion@1.1.11: 701 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 702 | dependencies: 703 | balanced-match: 1.0.2 704 | concat-map: 0.0.1 705 | dev: true 706 | 707 | /brace-expansion@2.0.1: 708 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 709 | dependencies: 710 | balanced-match: 1.0.2 711 | dev: true 712 | 713 | /braces@3.0.2: 714 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 715 | engines: {node: '>=8'} 716 | dependencies: 717 | fill-range: 7.0.1 718 | dev: true 719 | 720 | /callsites@3.1.0: 721 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 722 | engines: {node: '>=6'} 723 | dev: true 724 | 725 | /capnp-ts@0.7.0: 726 | resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} 727 | dependencies: 728 | debug: 4.3.4 729 | tslib: 2.6.2 730 | transitivePeerDependencies: 731 | - supports-color 732 | dev: true 733 | 734 | /chalk@4.1.2: 735 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 736 | engines: {node: '>=10'} 737 | dependencies: 738 | ansi-styles: 4.3.0 739 | supports-color: 7.2.0 740 | dev: true 741 | 742 | /chokidar@3.6.0: 743 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 744 | engines: {node: '>= 8.10.0'} 745 | dependencies: 746 | anymatch: 3.1.3 747 | braces: 3.0.2 748 | glob-parent: 5.1.2 749 | is-binary-path: 2.1.0 750 | is-glob: 4.0.3 751 | normalize-path: 3.0.0 752 | readdirp: 3.6.0 753 | optionalDependencies: 754 | fsevents: 2.3.3 755 | dev: true 756 | 757 | /color-convert@2.0.1: 758 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 759 | engines: {node: '>=7.0.0'} 760 | dependencies: 761 | color-name: 1.1.4 762 | dev: true 763 | 764 | /color-name@1.1.4: 765 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 766 | dev: true 767 | 768 | /commander@12.0.0: 769 | resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} 770 | engines: {node: '>=18'} 771 | dev: true 772 | 773 | /concat-map@0.0.1: 774 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 775 | dev: true 776 | 777 | /cookie@0.5.0: 778 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 779 | engines: {node: '>= 0.6'} 780 | dev: true 781 | 782 | /cross-spawn@7.0.3: 783 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 784 | engines: {node: '>= 8'} 785 | dependencies: 786 | path-key: 3.1.1 787 | shebang-command: 2.0.0 788 | which: 2.0.2 789 | dev: true 790 | 791 | /data-uri-to-buffer@2.0.2: 792 | resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} 793 | dev: true 794 | 795 | /debug@4.3.4: 796 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 797 | engines: {node: '>=6.0'} 798 | peerDependencies: 799 | supports-color: '*' 800 | peerDependenciesMeta: 801 | supports-color: 802 | optional: true 803 | dependencies: 804 | ms: 2.1.2 805 | dev: true 806 | 807 | /deep-is@0.1.4: 808 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 809 | dev: true 810 | 811 | /dir-glob@3.0.1: 812 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 813 | engines: {node: '>=8'} 814 | dependencies: 815 | path-type: 4.0.0 816 | dev: true 817 | 818 | /esbuild@0.17.19: 819 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} 820 | engines: {node: '>=12'} 821 | hasBin: true 822 | requiresBuild: true 823 | optionalDependencies: 824 | '@esbuild/android-arm': 0.17.19 825 | '@esbuild/android-arm64': 0.17.19 826 | '@esbuild/android-x64': 0.17.19 827 | '@esbuild/darwin-arm64': 0.17.19 828 | '@esbuild/darwin-x64': 0.17.19 829 | '@esbuild/freebsd-arm64': 0.17.19 830 | '@esbuild/freebsd-x64': 0.17.19 831 | '@esbuild/linux-arm': 0.17.19 832 | '@esbuild/linux-arm64': 0.17.19 833 | '@esbuild/linux-ia32': 0.17.19 834 | '@esbuild/linux-loong64': 0.17.19 835 | '@esbuild/linux-mips64el': 0.17.19 836 | '@esbuild/linux-ppc64': 0.17.19 837 | '@esbuild/linux-riscv64': 0.17.19 838 | '@esbuild/linux-s390x': 0.17.19 839 | '@esbuild/linux-x64': 0.17.19 840 | '@esbuild/netbsd-x64': 0.17.19 841 | '@esbuild/openbsd-x64': 0.17.19 842 | '@esbuild/sunos-x64': 0.17.19 843 | '@esbuild/win32-arm64': 0.17.19 844 | '@esbuild/win32-ia32': 0.17.19 845 | '@esbuild/win32-x64': 0.17.19 846 | dev: true 847 | 848 | /escape-string-regexp@4.0.0: 849 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 850 | engines: {node: '>=10'} 851 | dev: true 852 | 853 | /eslint-config-prettier@9.1.0(eslint@9.0.0): 854 | resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} 855 | hasBin: true 856 | peerDependencies: 857 | eslint: '>=7.0.0' 858 | dependencies: 859 | eslint: 9.0.0 860 | dev: true 861 | 862 | /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@9.0.0)(prettier@3.2.5): 863 | resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} 864 | engines: {node: ^14.18.0 || >=16.0.0} 865 | peerDependencies: 866 | '@types/eslint': '>=8.0.0' 867 | eslint: '>=8.0.0' 868 | eslint-config-prettier: '*' 869 | prettier: '>=3.0.0' 870 | peerDependenciesMeta: 871 | '@types/eslint': 872 | optional: true 873 | eslint-config-prettier: 874 | optional: true 875 | dependencies: 876 | eslint: 9.0.0 877 | eslint-config-prettier: 9.1.0(eslint@9.0.0) 878 | prettier: 3.2.5 879 | prettier-linter-helpers: 1.0.0 880 | synckit: 0.8.8 881 | dev: true 882 | 883 | /eslint-scope@8.0.1: 884 | resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} 885 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 886 | dependencies: 887 | esrecurse: 4.3.0 888 | estraverse: 5.3.0 889 | dev: true 890 | 891 | /eslint-visitor-keys@3.4.3: 892 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 893 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 894 | dev: true 895 | 896 | /eslint-visitor-keys@4.0.0: 897 | resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} 898 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 899 | dev: true 900 | 901 | /eslint@9.0.0: 902 | resolution: {integrity: sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==} 903 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 904 | hasBin: true 905 | dependencies: 906 | '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0) 907 | '@eslint-community/regexpp': 4.10.0 908 | '@eslint/eslintrc': 3.0.2 909 | '@eslint/js': 9.0.0 910 | '@humanwhocodes/config-array': 0.12.3 911 | '@humanwhocodes/module-importer': 1.0.1 912 | '@nodelib/fs.walk': 1.2.8 913 | ajv: 6.12.6 914 | chalk: 4.1.2 915 | cross-spawn: 7.0.3 916 | debug: 4.3.4 917 | escape-string-regexp: 4.0.0 918 | eslint-scope: 8.0.1 919 | eslint-visitor-keys: 4.0.0 920 | espree: 10.0.1 921 | esquery: 1.5.0 922 | esutils: 2.0.3 923 | fast-deep-equal: 3.1.3 924 | file-entry-cache: 8.0.0 925 | find-up: 5.0.0 926 | glob-parent: 6.0.2 927 | graphemer: 1.4.0 928 | ignore: 5.3.1 929 | imurmurhash: 0.1.4 930 | is-glob: 4.0.3 931 | is-path-inside: 3.0.3 932 | json-stable-stringify-without-jsonify: 1.0.1 933 | levn: 0.4.1 934 | lodash.merge: 4.6.2 935 | minimatch: 3.1.2 936 | natural-compare: 1.4.0 937 | optionator: 0.9.3 938 | strip-ansi: 6.0.1 939 | text-table: 0.2.0 940 | transitivePeerDependencies: 941 | - supports-color 942 | dev: true 943 | 944 | /espree@10.0.1: 945 | resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} 946 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 947 | dependencies: 948 | acorn: 8.11.3 949 | acorn-jsx: 5.3.2(acorn@8.11.3) 950 | eslint-visitor-keys: 4.0.0 951 | dev: true 952 | 953 | /esquery@1.5.0: 954 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 955 | engines: {node: '>=0.10'} 956 | dependencies: 957 | estraverse: 5.3.0 958 | dev: true 959 | 960 | /esrecurse@4.3.0: 961 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 962 | engines: {node: '>=4.0'} 963 | dependencies: 964 | estraverse: 5.3.0 965 | dev: true 966 | 967 | /estraverse@5.3.0: 968 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 969 | engines: {node: '>=4.0'} 970 | dev: true 971 | 972 | /estree-walker@0.6.1: 973 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} 974 | dev: true 975 | 976 | /esutils@2.0.3: 977 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 978 | engines: {node: '>=0.10.0'} 979 | dev: true 980 | 981 | /exit-hook@2.2.1: 982 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} 983 | engines: {node: '>=6'} 984 | dev: true 985 | 986 | /fast-deep-equal@3.1.3: 987 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 988 | dev: true 989 | 990 | /fast-diff@1.3.0: 991 | resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} 992 | dev: true 993 | 994 | /fast-glob@3.3.2: 995 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 996 | engines: {node: '>=8.6.0'} 997 | dependencies: 998 | '@nodelib/fs.stat': 2.0.5 999 | '@nodelib/fs.walk': 1.2.8 1000 | glob-parent: 5.1.2 1001 | merge2: 1.4.1 1002 | micromatch: 4.0.5 1003 | dev: true 1004 | 1005 | /fast-json-stable-stringify@2.1.0: 1006 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1007 | dev: true 1008 | 1009 | /fast-levenshtein@2.0.6: 1010 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 1011 | dev: true 1012 | 1013 | /fastq@1.17.1: 1014 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 1015 | dependencies: 1016 | reusify: 1.0.4 1017 | dev: true 1018 | 1019 | /file-entry-cache@8.0.0: 1020 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 1021 | engines: {node: '>=16.0.0'} 1022 | dependencies: 1023 | flat-cache: 4.0.1 1024 | dev: true 1025 | 1026 | /fill-range@7.0.1: 1027 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1028 | engines: {node: '>=8'} 1029 | dependencies: 1030 | to-regex-range: 5.0.1 1031 | dev: true 1032 | 1033 | /find-up@5.0.0: 1034 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 1035 | engines: {node: '>=10'} 1036 | dependencies: 1037 | locate-path: 6.0.0 1038 | path-exists: 4.0.0 1039 | dev: true 1040 | 1041 | /flat-cache@4.0.1: 1042 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 1043 | engines: {node: '>=16'} 1044 | dependencies: 1045 | flatted: 3.3.1 1046 | keyv: 4.5.4 1047 | dev: true 1048 | 1049 | /flatted@3.3.1: 1050 | resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} 1051 | dev: true 1052 | 1053 | /fs.realpath@1.0.0: 1054 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 1055 | dev: true 1056 | 1057 | /fsevents@2.3.3: 1058 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1059 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1060 | os: [darwin] 1061 | requiresBuild: true 1062 | dev: true 1063 | optional: true 1064 | 1065 | /function-bind@1.1.2: 1066 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1067 | dev: true 1068 | 1069 | /get-source@2.0.12: 1070 | resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} 1071 | dependencies: 1072 | data-uri-to-buffer: 2.0.2 1073 | source-map: 0.6.1 1074 | dev: true 1075 | 1076 | /glob-parent@5.1.2: 1077 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1078 | engines: {node: '>= 6'} 1079 | dependencies: 1080 | is-glob: 4.0.3 1081 | dev: true 1082 | 1083 | /glob-parent@6.0.2: 1084 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1085 | engines: {node: '>=10.13.0'} 1086 | dependencies: 1087 | is-glob: 4.0.3 1088 | dev: true 1089 | 1090 | /glob-to-regexp@0.4.1: 1091 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 1092 | dev: true 1093 | 1094 | /glob@8.1.0: 1095 | resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} 1096 | engines: {node: '>=12'} 1097 | dependencies: 1098 | fs.realpath: 1.0.0 1099 | inflight: 1.0.6 1100 | inherits: 2.0.4 1101 | minimatch: 5.1.6 1102 | once: 1.4.0 1103 | dev: true 1104 | 1105 | /globals@14.0.0: 1106 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 1107 | engines: {node: '>=18'} 1108 | dev: true 1109 | 1110 | /globby@11.1.0: 1111 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1112 | engines: {node: '>=10'} 1113 | dependencies: 1114 | array-union: 2.1.0 1115 | dir-glob: 3.0.1 1116 | fast-glob: 3.3.2 1117 | ignore: 5.3.1 1118 | merge2: 1.4.1 1119 | slash: 3.0.0 1120 | dev: true 1121 | 1122 | /graphemer@1.4.0: 1123 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 1124 | dev: true 1125 | 1126 | /has-flag@4.0.0: 1127 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1128 | engines: {node: '>=8'} 1129 | dev: true 1130 | 1131 | /hasown@2.0.2: 1132 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1133 | engines: {node: '>= 0.4'} 1134 | dependencies: 1135 | function-bind: 1.1.2 1136 | dev: true 1137 | 1138 | /hono@4.2.4: 1139 | resolution: {integrity: sha512-2T5Ahxh8tT0ISKCrNeA+OIwfD5W4EZ00iIMYBBCuiIivr+sOrZYOphinARSG7wL3nFsY6zkFHMMZbcR9CzEzug==} 1140 | engines: {node: '>=16.0.0'} 1141 | dev: false 1142 | 1143 | /ignore@5.3.1: 1144 | resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} 1145 | engines: {node: '>= 4'} 1146 | dev: true 1147 | 1148 | /immediate@3.0.6: 1149 | resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} 1150 | dev: false 1151 | 1152 | /import-fresh@3.3.0: 1153 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1154 | engines: {node: '>=6'} 1155 | dependencies: 1156 | parent-module: 1.0.1 1157 | resolve-from: 4.0.0 1158 | dev: true 1159 | 1160 | /imurmurhash@0.1.4: 1161 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1162 | engines: {node: '>=0.8.19'} 1163 | dev: true 1164 | 1165 | /inflight@1.0.6: 1166 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 1167 | dependencies: 1168 | once: 1.4.0 1169 | wrappy: 1.0.2 1170 | dev: true 1171 | 1172 | /inherits@2.0.4: 1173 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1174 | dev: true 1175 | 1176 | /is-binary-path@2.1.0: 1177 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1178 | engines: {node: '>=8'} 1179 | dependencies: 1180 | binary-extensions: 2.3.0 1181 | dev: true 1182 | 1183 | /is-core-module@2.13.1: 1184 | resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} 1185 | dependencies: 1186 | hasown: 2.0.2 1187 | dev: true 1188 | 1189 | /is-extglob@2.1.1: 1190 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1191 | engines: {node: '>=0.10.0'} 1192 | dev: true 1193 | 1194 | /is-glob@4.0.3: 1195 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1196 | engines: {node: '>=0.10.0'} 1197 | dependencies: 1198 | is-extglob: 2.1.1 1199 | dev: true 1200 | 1201 | /is-number@7.0.0: 1202 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1203 | engines: {node: '>=0.12.0'} 1204 | dev: true 1205 | 1206 | /is-path-inside@3.0.3: 1207 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 1208 | engines: {node: '>=8'} 1209 | dev: true 1210 | 1211 | /isexe@2.0.0: 1212 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1213 | dev: true 1214 | 1215 | /js-yaml@4.1.0: 1216 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1217 | hasBin: true 1218 | dependencies: 1219 | argparse: 2.0.1 1220 | dev: true 1221 | 1222 | /json-buffer@3.0.1: 1223 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 1224 | dev: true 1225 | 1226 | /json-schema-traverse@0.4.1: 1227 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1228 | dev: true 1229 | 1230 | /json-stable-stringify-without-jsonify@1.0.1: 1231 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1232 | dev: true 1233 | 1234 | /json5@2.2.3: 1235 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1236 | engines: {node: '>=6'} 1237 | hasBin: true 1238 | dev: true 1239 | 1240 | /keyv@4.5.4: 1241 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 1242 | dependencies: 1243 | json-buffer: 3.0.1 1244 | dev: true 1245 | 1246 | /levn@0.4.1: 1247 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1248 | engines: {node: '>= 0.8.0'} 1249 | dependencies: 1250 | prelude-ls: 1.2.1 1251 | type-check: 0.4.0 1252 | dev: true 1253 | 1254 | /lie@3.1.1: 1255 | resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} 1256 | dependencies: 1257 | immediate: 3.0.6 1258 | dev: false 1259 | 1260 | /localforage@1.10.0: 1261 | resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} 1262 | dependencies: 1263 | lie: 3.1.1 1264 | dev: false 1265 | 1266 | /locate-path@6.0.0: 1267 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1268 | engines: {node: '>=10'} 1269 | dependencies: 1270 | p-locate: 5.0.0 1271 | dev: true 1272 | 1273 | /lodash.merge@4.6.2: 1274 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1275 | dev: true 1276 | 1277 | /lru-cache@6.0.0: 1278 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1279 | engines: {node: '>=10'} 1280 | dependencies: 1281 | yallist: 4.0.0 1282 | dev: true 1283 | 1284 | /magic-string@0.25.9: 1285 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 1286 | dependencies: 1287 | sourcemap-codec: 1.4.8 1288 | dev: true 1289 | 1290 | /merge2@1.4.1: 1291 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1292 | engines: {node: '>= 8'} 1293 | dev: true 1294 | 1295 | /micromatch@4.0.5: 1296 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1297 | engines: {node: '>=8.6'} 1298 | dependencies: 1299 | braces: 3.0.2 1300 | picomatch: 2.3.1 1301 | dev: true 1302 | 1303 | /mime@3.0.0: 1304 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} 1305 | engines: {node: '>=10.0.0'} 1306 | hasBin: true 1307 | dev: true 1308 | 1309 | /miniflare@3.20240405.1: 1310 | resolution: {integrity: sha512-oShOR/ckr9JTO1bkPQH0nXvuSgJjoE+E5+M1tvP01Q8Z+Q0GJnzU2+FDYUH8yIK/atHv7snU8yy0X6KWVn1YdQ==} 1311 | engines: {node: '>=16.13'} 1312 | hasBin: true 1313 | dependencies: 1314 | '@cspotcode/source-map-support': 0.8.1 1315 | acorn: 8.11.3 1316 | acorn-walk: 8.3.2 1317 | capnp-ts: 0.7.0 1318 | exit-hook: 2.2.1 1319 | glob-to-regexp: 0.4.1 1320 | stoppable: 1.1.0 1321 | undici: 5.28.2 1322 | workerd: 1.20240405.0 1323 | ws: 8.16.0 1324 | youch: 3.3.3 1325 | zod: 3.22.4 1326 | transitivePeerDependencies: 1327 | - bufferutil 1328 | - supports-color 1329 | - utf-8-validate 1330 | dev: true 1331 | 1332 | /minimatch@3.1.2: 1333 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1334 | dependencies: 1335 | brace-expansion: 1.1.11 1336 | dev: true 1337 | 1338 | /minimatch@5.1.6: 1339 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} 1340 | engines: {node: '>=10'} 1341 | dependencies: 1342 | brace-expansion: 2.0.1 1343 | dev: true 1344 | 1345 | /minimatch@9.0.4: 1346 | resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} 1347 | engines: {node: '>=16 || 14 >=14.17'} 1348 | dependencies: 1349 | brace-expansion: 2.0.1 1350 | dev: true 1351 | 1352 | /ms@2.1.2: 1353 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1354 | dev: true 1355 | 1356 | /mustache@4.2.0: 1357 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 1358 | hasBin: true 1359 | dev: true 1360 | 1361 | /nanoid@3.3.7: 1362 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 1363 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1364 | hasBin: true 1365 | dev: true 1366 | 1367 | /natural-compare@1.4.0: 1368 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1369 | dev: true 1370 | 1371 | /node-forge@1.3.1: 1372 | resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} 1373 | engines: {node: '>= 6.13.0'} 1374 | dev: true 1375 | 1376 | /normalize-path@3.0.0: 1377 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1378 | engines: {node: '>=0.10.0'} 1379 | dev: true 1380 | 1381 | /once@1.4.0: 1382 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1383 | dependencies: 1384 | wrappy: 1.0.2 1385 | dev: true 1386 | 1387 | /optionator@0.9.3: 1388 | resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 1389 | engines: {node: '>= 0.8.0'} 1390 | dependencies: 1391 | '@aashutoshrathi/word-wrap': 1.2.6 1392 | deep-is: 0.1.4 1393 | fast-levenshtein: 2.0.6 1394 | levn: 0.4.1 1395 | prelude-ls: 1.2.1 1396 | type-check: 0.4.0 1397 | dev: true 1398 | 1399 | /p-limit@3.1.0: 1400 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1401 | engines: {node: '>=10'} 1402 | dependencies: 1403 | yocto-queue: 0.1.0 1404 | dev: true 1405 | 1406 | /p-locate@5.0.0: 1407 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1408 | engines: {node: '>=10'} 1409 | dependencies: 1410 | p-limit: 3.1.0 1411 | dev: true 1412 | 1413 | /parent-module@1.0.1: 1414 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1415 | engines: {node: '>=6'} 1416 | dependencies: 1417 | callsites: 3.1.0 1418 | dev: true 1419 | 1420 | /path-exists@4.0.0: 1421 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1422 | engines: {node: '>=8'} 1423 | dev: true 1424 | 1425 | /path-key@3.1.1: 1426 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1427 | engines: {node: '>=8'} 1428 | dev: true 1429 | 1430 | /path-parse@1.0.7: 1431 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1432 | dev: true 1433 | 1434 | /path-to-regexp@6.2.1: 1435 | resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} 1436 | dev: true 1437 | 1438 | /path-type@4.0.0: 1439 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1440 | engines: {node: '>=8'} 1441 | dev: true 1442 | 1443 | /picomatch@2.3.1: 1444 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1445 | engines: {node: '>=8.6'} 1446 | dev: true 1447 | 1448 | /prelude-ls@1.2.1: 1449 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1450 | engines: {node: '>= 0.8.0'} 1451 | dev: true 1452 | 1453 | /prettier-linter-helpers@1.0.0: 1454 | resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} 1455 | engines: {node: '>=6.0.0'} 1456 | dependencies: 1457 | fast-diff: 1.3.0 1458 | dev: true 1459 | 1460 | /prettier@3.2.5: 1461 | resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} 1462 | engines: {node: '>=14'} 1463 | hasBin: true 1464 | dev: true 1465 | 1466 | /printable-characters@1.0.42: 1467 | resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} 1468 | dev: true 1469 | 1470 | /punycode@2.3.1: 1471 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1472 | engines: {node: '>=6'} 1473 | dev: true 1474 | 1475 | /queue-microtask@1.2.3: 1476 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1477 | dev: true 1478 | 1479 | /readdirp@3.6.0: 1480 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1481 | engines: {node: '>=8.10.0'} 1482 | dependencies: 1483 | picomatch: 2.3.1 1484 | dev: true 1485 | 1486 | /resolve-from@4.0.0: 1487 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1488 | engines: {node: '>=4'} 1489 | dev: true 1490 | 1491 | /resolve.exports@2.0.2: 1492 | resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} 1493 | engines: {node: '>=10'} 1494 | dev: true 1495 | 1496 | /resolve@1.22.8: 1497 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1498 | hasBin: true 1499 | dependencies: 1500 | is-core-module: 2.13.1 1501 | path-parse: 1.0.7 1502 | supports-preserve-symlinks-flag: 1.0.0 1503 | dev: true 1504 | 1505 | /reusify@1.0.4: 1506 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1507 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1508 | dev: true 1509 | 1510 | /rollup-plugin-inject@3.0.2: 1511 | resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} 1512 | deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. 1513 | dependencies: 1514 | estree-walker: 0.6.1 1515 | magic-string: 0.25.9 1516 | rollup-pluginutils: 2.8.2 1517 | dev: true 1518 | 1519 | /rollup-plugin-node-polyfills@0.2.1: 1520 | resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} 1521 | dependencies: 1522 | rollup-plugin-inject: 3.0.2 1523 | dev: true 1524 | 1525 | /rollup-pluginutils@2.8.2: 1526 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} 1527 | dependencies: 1528 | estree-walker: 0.6.1 1529 | dev: true 1530 | 1531 | /run-parallel@1.2.0: 1532 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1533 | dependencies: 1534 | queue-microtask: 1.2.3 1535 | dev: true 1536 | 1537 | /safe-stable-stringify@2.4.3: 1538 | resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} 1539 | engines: {node: '>=10'} 1540 | dev: true 1541 | 1542 | /selfsigned@2.4.1: 1543 | resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} 1544 | engines: {node: '>=10'} 1545 | dependencies: 1546 | '@types/node-forge': 1.3.11 1547 | node-forge: 1.3.1 1548 | dev: true 1549 | 1550 | /semver@7.6.0: 1551 | resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} 1552 | engines: {node: '>=10'} 1553 | hasBin: true 1554 | dependencies: 1555 | lru-cache: 6.0.0 1556 | dev: true 1557 | 1558 | /shebang-command@2.0.0: 1559 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1560 | engines: {node: '>=8'} 1561 | dependencies: 1562 | shebang-regex: 3.0.0 1563 | dev: true 1564 | 1565 | /shebang-regex@3.0.0: 1566 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1567 | engines: {node: '>=8'} 1568 | dev: true 1569 | 1570 | /slash@3.0.0: 1571 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1572 | engines: {node: '>=8'} 1573 | dev: true 1574 | 1575 | /source-map@0.6.1: 1576 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1577 | engines: {node: '>=0.10.0'} 1578 | dev: true 1579 | 1580 | /sourcemap-codec@1.4.8: 1581 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 1582 | deprecated: Please use @jridgewell/sourcemap-codec instead 1583 | dev: true 1584 | 1585 | /stacktracey@2.1.8: 1586 | resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} 1587 | dependencies: 1588 | as-table: 1.0.55 1589 | get-source: 2.0.12 1590 | dev: true 1591 | 1592 | /stoppable@1.1.0: 1593 | resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} 1594 | engines: {node: '>=4', npm: '>=6'} 1595 | dev: true 1596 | 1597 | /strip-ansi@6.0.1: 1598 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1599 | engines: {node: '>=8'} 1600 | dependencies: 1601 | ansi-regex: 5.0.1 1602 | dev: true 1603 | 1604 | /strip-json-comments@3.1.1: 1605 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1606 | engines: {node: '>=8'} 1607 | dev: true 1608 | 1609 | /supports-color@7.2.0: 1610 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1611 | engines: {node: '>=8'} 1612 | dependencies: 1613 | has-flag: 4.0.0 1614 | dev: true 1615 | 1616 | /supports-preserve-symlinks-flag@1.0.0: 1617 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1618 | engines: {node: '>= 0.4'} 1619 | dev: true 1620 | 1621 | /synckit@0.8.8: 1622 | resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} 1623 | engines: {node: ^14.18.0 || >=16.0.0} 1624 | dependencies: 1625 | '@pkgr/core': 0.1.1 1626 | tslib: 2.6.2 1627 | dev: true 1628 | 1629 | /text-table@0.2.0: 1630 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1631 | dev: true 1632 | 1633 | /to-regex-range@5.0.1: 1634 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1635 | engines: {node: '>=8.0'} 1636 | dependencies: 1637 | is-number: 7.0.0 1638 | dev: true 1639 | 1640 | /toucan-js@3.3.1: 1641 | resolution: {integrity: sha512-9BpkHb/Pzsrtl1ItNq9OEQPnuUHwzce0nV2uG+DYFiQ4fPyiA6mKTBcDwQzcvNkfSER038U+8TzvdkCev+Maww==} 1642 | dependencies: 1643 | '@sentry/core': 7.76.0 1644 | '@sentry/integrations': 7.76.0 1645 | '@sentry/types': 7.76.0 1646 | '@sentry/utils': 7.76.0 1647 | dev: false 1648 | 1649 | /ts-api-utils@1.3.0(typescript@5.4.5): 1650 | resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} 1651 | engines: {node: '>=16'} 1652 | peerDependencies: 1653 | typescript: '>=4.2.0' 1654 | dependencies: 1655 | typescript: 5.4.5 1656 | dev: true 1657 | 1658 | /ts-json-schema-generator@1.5.1: 1659 | resolution: {integrity: sha512-apX5qG2+NA66j7b4AJm8q/DpdTeOsjfh7A3LpKsUiil0FepkNwtN28zYgjrsiiya2/OPhsr/PSjX5FUYg79rCg==} 1660 | engines: {node: '>=10.0.0'} 1661 | hasBin: true 1662 | dependencies: 1663 | '@types/json-schema': 7.0.15 1664 | commander: 12.0.0 1665 | glob: 8.1.0 1666 | json5: 2.2.3 1667 | normalize-path: 3.0.0 1668 | safe-stable-stringify: 2.4.3 1669 | typescript: 5.4.5 1670 | dev: true 1671 | 1672 | /tslib@2.6.2: 1673 | resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} 1674 | dev: true 1675 | 1676 | /type-check@0.4.0: 1677 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1678 | engines: {node: '>= 0.8.0'} 1679 | dependencies: 1680 | prelude-ls: 1.2.1 1681 | dev: true 1682 | 1683 | /typescript-eslint@7.6.0(eslint@9.0.0)(typescript@5.4.5): 1684 | resolution: {integrity: sha512-LY6vH6F1l5jpGqRtU+uK4+mOecIb4Cd4kaz1hAiJrgnNiHUA8wiw8BkJyYS+MRLM69F1QuSKwtGlQqnGl1Rc6w==} 1685 | engines: {node: ^18.18.0 || >=20.0.0} 1686 | peerDependencies: 1687 | eslint: ^8.56.0 1688 | typescript: '*' 1689 | peerDependenciesMeta: 1690 | typescript: 1691 | optional: true 1692 | dependencies: 1693 | '@typescript-eslint/eslint-plugin': 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@9.0.0)(typescript@5.4.5) 1694 | '@typescript-eslint/parser': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 1695 | '@typescript-eslint/utils': 7.6.0(eslint@9.0.0)(typescript@5.4.5) 1696 | eslint: 9.0.0 1697 | typescript: 5.4.5 1698 | transitivePeerDependencies: 1699 | - supports-color 1700 | dev: true 1701 | 1702 | /typescript@5.4.5: 1703 | resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} 1704 | engines: {node: '>=14.17'} 1705 | hasBin: true 1706 | dev: true 1707 | 1708 | /undici-types@5.26.5: 1709 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 1710 | dev: true 1711 | 1712 | /undici@5.28.2: 1713 | resolution: {integrity: sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==} 1714 | engines: {node: '>=14.0'} 1715 | dependencies: 1716 | '@fastify/busboy': 2.1.1 1717 | dev: true 1718 | 1719 | /uri-js@4.4.1: 1720 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1721 | dependencies: 1722 | punycode: 2.3.1 1723 | dev: true 1724 | 1725 | /uuid@9.0.1: 1726 | resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} 1727 | hasBin: true 1728 | dev: false 1729 | 1730 | /which@2.0.2: 1731 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1732 | engines: {node: '>= 8'} 1733 | hasBin: true 1734 | dependencies: 1735 | isexe: 2.0.0 1736 | dev: true 1737 | 1738 | /workerd@1.20240405.0: 1739 | resolution: {integrity: sha512-AWrOSBh4Ll7sBWHuh0aywm8hDkKqsZmcwnDB0PVGszWZM5mndNBI5iJ/8haXVpdoyqkJQEVdhET9JDi4yU8tRg==} 1740 | engines: {node: '>=16'} 1741 | hasBin: true 1742 | requiresBuild: true 1743 | optionalDependencies: 1744 | '@cloudflare/workerd-darwin-64': 1.20240405.0 1745 | '@cloudflare/workerd-darwin-arm64': 1.20240405.0 1746 | '@cloudflare/workerd-linux-64': 1.20240405.0 1747 | '@cloudflare/workerd-linux-arm64': 1.20240405.0 1748 | '@cloudflare/workerd-windows-64': 1.20240405.0 1749 | dev: true 1750 | 1751 | /wrangler@3.50.0(@cloudflare/workers-types@4.20240405.0): 1752 | resolution: {integrity: sha512-JlLuch+6DtaC5HGp8YD9Au++XvMv34g3ySdlB5SyPbaObELi8P9ZID5vgyf9AA75djzxL7cuNOk1YdKCJEuq0w==} 1753 | engines: {node: '>=16.17.0'} 1754 | hasBin: true 1755 | peerDependencies: 1756 | '@cloudflare/workers-types': ^4.20240405.0 1757 | peerDependenciesMeta: 1758 | '@cloudflare/workers-types': 1759 | optional: true 1760 | dependencies: 1761 | '@cloudflare/kv-asset-handler': 0.3.1 1762 | '@cloudflare/workers-types': 4.20240405.0 1763 | '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) 1764 | '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) 1765 | blake3-wasm: 2.1.5 1766 | chokidar: 3.6.0 1767 | esbuild: 0.17.19 1768 | miniflare: 3.20240405.1 1769 | nanoid: 3.3.7 1770 | path-to-regexp: 6.2.1 1771 | resolve: 1.22.8 1772 | resolve.exports: 2.0.2 1773 | selfsigned: 2.4.1 1774 | source-map: 0.6.1 1775 | ts-json-schema-generator: 1.5.1 1776 | xxhash-wasm: 1.0.2 1777 | optionalDependencies: 1778 | fsevents: 2.3.3 1779 | transitivePeerDependencies: 1780 | - bufferutil 1781 | - supports-color 1782 | - utf-8-validate 1783 | dev: true 1784 | 1785 | /wrappy@1.0.2: 1786 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1787 | dev: true 1788 | 1789 | /ws@8.16.0: 1790 | resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} 1791 | engines: {node: '>=10.0.0'} 1792 | peerDependencies: 1793 | bufferutil: ^4.0.1 1794 | utf-8-validate: '>=5.0.2' 1795 | peerDependenciesMeta: 1796 | bufferutil: 1797 | optional: true 1798 | utf-8-validate: 1799 | optional: true 1800 | dev: true 1801 | 1802 | /xxhash-wasm@1.0.2: 1803 | resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} 1804 | dev: true 1805 | 1806 | /yallist@4.0.0: 1807 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1808 | dev: true 1809 | 1810 | /yocto-queue@0.1.0: 1811 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1812 | engines: {node: '>=10'} 1813 | dev: true 1814 | 1815 | /youch@3.3.3: 1816 | resolution: {integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==} 1817 | dependencies: 1818 | cookie: 0.5.0 1819 | mustache: 4.2.0 1820 | stacktracey: 2.1.8 1821 | dev: true 1822 | 1823 | /zod@3.22.4: 1824 | resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} 1825 | dev: true 1826 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | export const Constants = { 20 | HOST_URL: "https://tiktxk.com", 21 | }; 22 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Hono } from "hono"; 20 | import { logger } from "hono/logger"; 21 | import { etag } from "hono/etag"; 22 | import { Bindings, StatusError } from "./types/cloudflare"; 23 | import { StatusCode } from "hono/utils/http-status"; 24 | import { addTikTokRoutes } from "./routes/tiktok"; 25 | import { addIndexRoutes } from "./routes"; 26 | import { addEmbedRoutes } from "@/routes/embed"; 27 | import { addMetaRoutes } from "@/routes/meta"; 28 | import { Constants } from "./constants"; 29 | import { Toucan } from "toucan-js"; 30 | import { prettyJSON } from "hono/pretty-json"; 31 | import { GenericDiscordEmbed, isDiscord } from "@/util/discord"; 32 | 33 | const app = new Hono<{ Bindings: Bindings }>(); 34 | 35 | app.use("*", etag(), logger(), prettyJSON()); 36 | 37 | // Add routes 38 | addIndexRoutes(app); 39 | addEmbedRoutes(app); 40 | addMetaRoutes(app); 41 | addTikTokRoutes(app); 42 | 43 | // Add error handlers 44 | const errorComment = 45 | `If you're here, and have no idea what this nerd shit is, something went wrong when 46 | trying to embed a TikTok video. We don't support slideshows or LIVE videos, and we can't 47 | show videos that are private, or have been deleted. Sorry! Something wrong? 48 | Open an issue on GitHub at ${Constants.HOST_URL}/issue <3`.replace(/\s+/g, " "); 49 | 50 | const handle404: Parameters["0"] = (c) => 51 | c.json({ 52 | message: "Not Found", 53 | success: false, 54 | 55 | routes: app.routes 56 | .filter((r) => r.path !== "*") 57 | .map((r) => ({ 58 | path: r.path, 59 | method: r.method, 60 | })), 61 | }); 62 | 63 | app.notFound(handle404); 64 | 65 | app.onError((err, c) => { 66 | // Create a random identifiable error ID 67 | const requestId = Array.from(Array(10), () => 68 | Math.floor(Math.random() * 36).toString(36), 69 | ).join(""); 70 | 71 | if (err instanceof StatusError) { 72 | // If the request is from Discord, we should render an embed 73 | // as the response 74 | if (isDiscord(c.req)) { 75 | return c.html( 76 | , 81 | ); 82 | } 83 | 84 | // If the error is a 404, handle it as such 85 | if (err.status == 404) return handle404(c) as Response; 86 | 87 | // Otherwise just set the status code 88 | c.status(err.status as StatusCode); 89 | } else { 90 | // If the error is not a StatusError, log it to the console 91 | console.error(err); 92 | 93 | // Handle Discord embeds 94 | if (isDiscord(c.req)) { 95 | c.html( 96 | , 101 | ); 102 | } else { 103 | c.status(500); 104 | } 105 | } 106 | 107 | if (c.env?.SENTRY_DSN && !(err instanceof StatusError)) { 108 | try { 109 | const sentry = new Toucan({ 110 | dsn: c.env.SENTRY_DSN, 111 | context: c.executionCtx, 112 | request: c.req.raw, 113 | }); 114 | 115 | sentry.setExtra("request_id", requestId); 116 | sentry.captureException(err); 117 | } catch (e) { 118 | console.error("Failed to send error to Sentry", e); 119 | } 120 | } 121 | 122 | return c.json({ 123 | _comment: errorComment, 124 | error: err.message, 125 | success: false, 126 | }); 127 | }); 128 | 129 | // noinspection JSUnusedGlobalSymbols 130 | export default app; 131 | -------------------------------------------------------------------------------- /src/routes/embed.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Hono } from "hono"; 20 | import { Bindings, StatusError } from "@/types/cloudflare"; 21 | 22 | export const addEmbedRoutes = (app: Hono<{ Bindings: Bindings }>) => { 23 | app.get("/internal/embed", async (c) => { 24 | const authorName = c.req.query("authorName"); 25 | if (!authorName) throw new StatusError(400, "Missing authorName"); 26 | 27 | const authorUrl = c.req.query("authorUrl"); 28 | return c.json({ 29 | author_name: authorName, 30 | author_url: authorUrl, 31 | provider_name: "TikTxk - Embed using s/o/x", 32 | provider_url: "https://github.com/britmoji/tiktxk", 33 | title: "TikTok Embed", 34 | type: "link", 35 | version: "1.0", 36 | }); 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from "hono"; 2 | import { respondDiscord } from "@/util/discord"; 3 | import { getBaseURL } from "@/util/http"; 4 | import { Bindings } from "@/types/cloudflare"; 5 | 6 | export const addIndexRoutes = (app: Hono<{ Bindings: Bindings }>) => { 7 | // Home page 8 | app.get("/", (c) => 9 | respondDiscord( 10 | c, 11 | () => ({ 12 | title: "TikTxk", 13 | description: 14 | "TikTxk fixes TikTok's broken embeds in Discord, allowing you to play videos directly without leaving the app. To get started, send any TikTok link, and type s/o/x to fix its stupid lil' embed. Enjoy!", 15 | }), 16 | () => c.redirect("https://github.com/Britmoji/tiktxk"), 17 | ), 18 | ); 19 | 20 | // Crab (very important) 21 | app.get("/crab", (c) => 22 | respondDiscord( 23 | c, 24 | () => ({ title: "🦀", description: "fuck it. crab in the code." }), 25 | () => c.text("🦀"), 26 | ), 27 | ); 28 | 29 | // Report an issue 30 | app.get("/issue", (c) => 31 | respondDiscord( 32 | c, 33 | () => ({ 34 | title: "Report an issue", 35 | description: "To report an issue, go to https://tiktxk.com/issue", 36 | }), 37 | () => c.redirect("https://github.com/Britmoji/tiktxk/issues/new"), 38 | ), 39 | ); 40 | }; 41 | -------------------------------------------------------------------------------- /src/routes/meta.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Hono } from "hono"; 20 | import { tiktok } from "@/util/tiktok"; 21 | import { Bindings, StatusError } from "@/types/cloudflare"; 22 | 23 | export const addMetaRoutes = (app: Hono<{ Bindings: Bindings }>) => { 24 | // Video metadata 25 | app.get("/meta/:videoId/video", async (c) => { 26 | const videoId = c.req.param("videoId"); 27 | const details = await tiktok.details(videoId); 28 | if (!details) throw new StatusError(404, "UNKNOWN_AWEME"); 29 | 30 | return c.redirect(details.video.url); 31 | }); 32 | 33 | // Image metadata 34 | app.get("/meta/:videoId/image/:index", async (c) => { 35 | const videoId = c.req.param("videoId"); 36 | const index = parseInt(c.req.param("index")) || 0; 37 | const details = await tiktok.details(videoId); 38 | if (!details) throw new StatusError(404, "UNKNOWN_AWEME"); 39 | 40 | if (details.imagePost?.images?.length) { 41 | return c.redirect(details.imagePost.images[index].url); 42 | } 43 | 44 | return c.redirect(details.image.url); 45 | }); 46 | 47 | // Audio metadata 48 | app.get("/meta/:videoId/audio", async (c) => { 49 | const videoId = c.req.param("videoId"); 50 | const details = await tiktok.details(videoId); 51 | if (!details) throw new StatusError(404, "UNKNOWN_AWEME"); 52 | 53 | return c.redirect(details.audio.url); 54 | }); 55 | 56 | // All metadata 57 | app.get("/meta/:videoId", async (c) => { 58 | const videoId = c.req.param("videoId"); 59 | const details = await tiktok.details(videoId); 60 | if (!details) throw new StatusError(404, "UNKNOWN_AWEME"); 61 | 62 | return c.json(details); 63 | }); 64 | }; 65 | -------------------------------------------------------------------------------- /src/routes/tiktok.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Context, Handler, Hono } from "hono"; 20 | import { AdaptedItemDetails, tiktok } from "@/util/tiktok"; 21 | import { get } from "@/util/http"; 22 | import { Bindings, StatusError } from "@/types/cloudflare"; 23 | import { formatNumber } from "@/util/numbers"; 24 | import { Constants } from "@/constants"; 25 | import { DiscordEmbedData, respondDiscord } from "@/util/discord"; 26 | import { Fragment } from "hono/jsx"; 27 | 28 | const createDiscordEmbed = (data: AdaptedItemDetails): DiscordEmbedData => { 29 | // Format the numbers 30 | const likes = formatNumber(data.statistics.likes, 1); 31 | const comments = formatNumber(data.statistics.comments, 1); 32 | 33 | // Determine the preview component for the media type 34 | const previewComponent = ( 35 | 36 | {!data.imagePost && } 37 | {data.imagePost 38 | ? data.imagePost.images 39 | .slice(0, 4) // Only show the first 4 images 40 | .map((_, index) => ) 41 | : null} 42 | 43 | ); 44 | 45 | // Format the headings 46 | const authorName = `@${data.author.username}${ 47 | data.imagePost ? ` (slideshow)` : "" 48 | }`; 49 | const authorUrl = `https://tiktok.com/@${data.author.username}`; 50 | 51 | // noinspection HtmlRequiredTitleElement 52 | return { 53 | author: { name: authorName, url: authorUrl }, 54 | title: `❤️ ${likes} 💬 ${comments}`, 55 | url: `https://tiktok.com/@${data.author.username}/video/${data.id}`, 56 | component: previewComponent as unknown as Element | undefined, 57 | }; 58 | }; 59 | 60 | const VideoPreview = ({ tiktok }: { tiktok: AdaptedItemDetails }) => ( 61 | 62 | 66 | 67 | 68 | 72 | 73 | 74 | ); 75 | 76 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 77 | const ImagePreview = ({ 78 | tiktok, 79 | index, 80 | }: { 81 | tiktok: AdaptedItemDetails; 82 | index: number; 83 | }) => ( 84 | 85 | 89 | 90 | 94 | 98 | 99 | 100 | 101 | ); 102 | 103 | export const addTikTokRoutes = (app: Hono<{ Bindings: Bindings }>) => { 104 | const videoIdRegex = 105 | /https:\/\/www\.tiktok\.com\/@[^/]+\/(video|photo)\/(?\d+)/; 106 | 107 | // Main renderer 108 | const render = (c: Context, data: AdaptedItemDetails) => 109 | respondDiscord( 110 | c, 111 | () => createDiscordEmbed(data), 112 | () => 113 | c.redirect( 114 | `https://www.tiktok.com/@${data.author.username}/video/${data.id}`, 115 | ), 116 | ); 117 | 118 | // E.g. https://www.tiktok.com/@username/video/1234567891234567891 119 | const handleUsernameVideo: Handler = async (c) => { 120 | // const username = c.req.param("username"); // includes @ 121 | const videoId = c.req.param("videoId"); 122 | 123 | // Lookup details 124 | const details = await tiktok.details(videoId); 125 | if (!details) throw new StatusError(404, "UNKNOWN_AWEME"); 126 | 127 | return render(c, details); 128 | }; 129 | 130 | // E.g. https://www.tiktok.com/t/ZTRav7308 131 | // E.g. https://vm.tiktok.com/ZTRav7308/ 132 | const handleRedirect: (param: string) => Handler = 133 | (param: string) => async (c) => { 134 | const videoId = c.req.param(param); 135 | 136 | // Redirect to the page 137 | const res = await get(`https://www.tiktok.com/t/${videoId}/`); 138 | 139 | // Parse video ID from url 140 | const match = videoIdRegex.exec(res.url); 141 | if (!match || !match.groups) { 142 | throw new StatusError(400, "FAILED_TO_PARSE_VIDEO_ID"); 143 | } 144 | 145 | // Lookup details 146 | const details = await tiktok.details(match.groups?.id); 147 | if (!details) { 148 | throw new StatusError(404, "UNKNOWN_AWEME"); 149 | } 150 | 151 | return render(c, details); 152 | }; 153 | 154 | // https://www.tiktok.com/@username/video/1234567891234567891 155 | app.get("/*/video/:videoId", handleUsernameVideo); 156 | app.get("/*/video/:videoId/", handleUsernameVideo); 157 | 158 | // https://vm.tiktok.com/ZTRav7308/ 159 | app.get("/:vmId", handleRedirect("vmId")); 160 | app.get("/:vmId/", handleRedirect("vmId")); 161 | 162 | // https://www.tiktok.com/t/ZTRav7308 163 | app.get("/t/:videoId", handleRedirect("videoId")); 164 | app.get("/t/:videoId/", handleRedirect("videoId")); 165 | }; 166 | -------------------------------------------------------------------------------- /src/types/cloudflare.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Constants } from "@/constants"; 20 | 21 | export class StatusError extends Error { 22 | private static readonly DEFAULT_MESSAGE = `An unknown error occurred, please report this issue at ${Constants.HOST_URL}/issue, and include the request ID.`; 23 | 24 | public static readonly LANG = { 25 | UNKNOWN_AWEME: 26 | "The video could not be found. Either it was deleted, or TikTok has removed it.", 27 | FAILED_TO_PARSE_VIDEO_ID: 28 | "The video ID could not be parsed, is it a valid TikTok URL?", 29 | MISSING_VIDEO_ID: "The video ID is missing from the request.", 30 | }; 31 | 32 | private static readonly STATUSES = new Map([ 33 | [400, "Bad Request"], 34 | [401, "Unauthorized"], 35 | [403, "Forbidden"], 36 | [404, "Not Found"], 37 | [405, "Method Not Allowed"], 38 | ]); 39 | 40 | constructor( 41 | public status: number, 42 | message?: string | keyof typeof StatusError.LANG, 43 | ) { 44 | super( 45 | message 46 | ? StatusError.LANG[message] || message 47 | : StatusError.STATUSES.get(status) || StatusError.DEFAULT_MESSAGE, 48 | ); 49 | } 50 | } 51 | 52 | export type Bindings = { 53 | SENTRY_DSN?: string; 54 | }; 55 | -------------------------------------------------------------------------------- /src/util/discord.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2023 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Constants } from "@/constants"; 20 | import { FC } from "hono/jsx"; 21 | import { Context, HonoRequest } from "hono"; 22 | 23 | export type DiscordEmbedData = { 24 | title?: string; 25 | color?: string; 26 | description?: string; 27 | url?: string; 28 | 29 | author?: { 30 | name: string; 31 | url?: string; 32 | }; 33 | 34 | component?: Element; 35 | }; 36 | 37 | export const GenericDiscordEmbed: FC = ( 38 | embed: DiscordEmbedData, 39 | ) => { 40 | // Build the embed url 41 | const authorName = embed.author?.name ?? "TikTxk"; 42 | const authorUrl = embed.author?.url ?? Constants.HOST_URL; 43 | 44 | const url = new URL(`${Constants.HOST_URL}/internal/embed`); 45 | url.searchParams.set("authorName", authorName); 46 | url.searchParams.set("authorUrl", authorUrl); 47 | console.log(embed); 48 | 49 | // noinspection HtmlRequiredTitleElement 50 | return ( 51 | 52 | 53 | {/* Site Metadata */} 54 | 55 | 56 | 57 | 58 | 0.5 ? "#69C9D0" : "#EE1D52")} 61 | /> 62 | 63 | {/* Preview Metadata */} 64 | {embed.component} 65 | 66 | {/* The additional oembed is pulled by Discord to enable improved embeds. */} 67 | {embed.author && ( 68 | 73 | )} 74 | 75 | 76 | ); 77 | }; 78 | 79 | /** 80 | * Checks if the request is from Discord. 81 | * 82 | * @param req The request to check. 83 | * @returns True if the request is from Discord. 84 | */ 85 | export const isDiscord = (req: HonoRequest): boolean => { 86 | const raw = req.query("raw") === "true"; 87 | return req.header("User-Agent")?.includes("Discordbot") === true && !raw; 88 | }; 89 | 90 | /** 91 | * Respond with two different results depending on if the request is from Discord. 92 | * 93 | * @param ctx The request context. 94 | * @param embed Lazy function that returns the embed to respond with. 95 | * @param handler The handler to call if the request is not from Discord. 96 | * @returns The response. 97 | */ 98 | export const respondDiscord = ( 99 | ctx: Context, 100 | embed: () => DiscordEmbedData, 101 | handler: () => Response | Promise, 102 | ): Response | Promise => { 103 | if (isDiscord(ctx.req)) { 104 | return ctx.html(); 105 | } else { 106 | return handler(); 107 | } 108 | }; 109 | -------------------------------------------------------------------------------- /src/util/http.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { Context } from "hono"; 20 | 21 | // I am not a 🤖 22 | export const get = async (url: string) => { 23 | return await fetch(url, { 24 | headers: { 25 | "User-Agent": 26 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", 27 | }, 28 | }); 29 | }; 30 | 31 | export const getBaseURL = (ctx: Context) => { 32 | const url = new URL(ctx.req.url); 33 | return `https://${url.host}`; 34 | }; 35 | -------------------------------------------------------------------------------- /src/util/math.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2024 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | export const randomInt = (min: number, max: number) => 20 | Math.floor(Math.random() * (max - min + 1)) + min; 21 | 22 | export const randomBigInt = (min: bigint, max: bigint) => 23 | BigInt( 24 | Math.floor(Math.random() * (Number(max) - Number(min) + 1)) + Number(min), 25 | ); 26 | -------------------------------------------------------------------------------- /src/util/numbers.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | export const formatNumber = (num, digits) => { 20 | const lookup = [ 21 | { value: 1, symbol: "" }, 22 | { value: 1e3, symbol: "k" }, 23 | { value: 1e6, symbol: "M" }, 24 | { value: 1e9, symbol: "G" }, 25 | { value: 1e12, symbol: "T" }, 26 | { value: 1e15, symbol: "P" }, 27 | { value: 1e18, symbol: "E" }, 28 | ]; 29 | 30 | const rx = /\.0+$|(\.[0-9]*[1-9])0+$/; 31 | const item = lookup 32 | .slice() 33 | .reverse() 34 | .find(function (item) { 35 | return num >= item.value; 36 | }); 37 | 38 | return item 39 | ? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol 40 | : "0"; 41 | }; 42 | -------------------------------------------------------------------------------- /src/util/tiktok.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * tiktxk - Open Source, Privacy First TikTok Embeds 3 | * Copyright (C) 2022 Britmoji 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import { randomBigInt, randomInt } from "@/util/math"; 20 | import { v4 as uuidv4 } from "uuid"; 21 | 22 | class TikTokAPI { 23 | /** 24 | * Fetch the item details of a public TikTok, either from the 25 | * internal API, or fallback to the public API. 26 | * 27 | * @param videoID The video ID 28 | */ 29 | async details(videoID: string): Promise { 30 | // Fetch internal details 31 | const internal = await this.internalDetails(videoID); 32 | const internalDetails = internal?.aweme_list.filter( 33 | (value) => value.aweme_id === videoID, 34 | )[0]; 35 | 36 | if (internalDetails) return this.adaptInternal(internalDetails); 37 | return undefined; 38 | } 39 | 40 | /** 41 | * Parse the internal APIs aweme details into our 42 | * generic format. 43 | * 44 | * @param details The aweme details 45 | * @private Internal use only 46 | */ 47 | private adaptInternal(details: Aweme): AdaptedItemDetails { 48 | const videoPlayUrls = details?.video?.play_addr.url_list ?? []; 49 | const audioPlayUrls = details?.music?.play_url.url_list ?? []; 50 | 51 | const thumbnail = 52 | details.image_post_info?.images[0]?.display_image?.url_list || 53 | details.video?.cover?.url_list || 54 | []; 55 | 56 | // Adapt the data 57 | return { 58 | id: details.aweme_id, 59 | video: { 60 | url: videoPlayUrls[videoPlayUrls?.length - 1], 61 | height: details.video?.play_addr.height ?? 1080, 62 | width: details.video?.play_addr.width ?? 1920, 63 | }, 64 | image: { 65 | url: thumbnail[thumbnail?.length - 1], 66 | }, 67 | audio: { 68 | url: audioPlayUrls[audioPlayUrls?.length - 1], 69 | }, 70 | author: { 71 | username: details.author?.unique_id, 72 | }, 73 | statistics: { 74 | likes: details.statistics?.digg_count ?? 0, 75 | comments: details.statistics?.comment_count ?? 0, 76 | }, 77 | imagePost: details.image_post_info 78 | ? { 79 | images: details.image_post_info.images.map((image) => ({ 80 | url: image.display_image.url_list[ 81 | image.display_image.url_list.length - 1 82 | ], 83 | width: image.display_image.width, 84 | height: image.display_image.height, 85 | })), 86 | } 87 | : undefined, 88 | src: { 89 | type: "internal", 90 | data: details, 91 | }, 92 | }; 93 | } 94 | 95 | async internalDetails( 96 | videoID: string, 97 | ): Promise { 98 | // Throw if the video ID is not a number 99 | if (isNaN(Number(videoID))) return undefined; 100 | 101 | // Based off yt-dlp tiktok extractor. https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/tiktok.py 102 | // Turns out the only parameter you need is aid (which appears to influence some fields in the output, 103 | // maybe for compatibility with older app versions?). 104 | // The User-Agent isn't strictly required, but some appear to be blacklisted. This one (based off yt-dlp) should be good. 105 | const appName = "musical_ly"; 106 | const appId = 0; //_AID = 0 # aweme = 1128, trill = 1180, musical_ly = 1233, universal = 0; 107 | const appVersion = "34.1.2"; 108 | const appManifestVersion = "2023401020"; 109 | const userAgent = `com.zhiliaoapp.musically/${appVersion} (Linux; U; Android 13; en_US; Pixel 7; Build/TD1A.220804.031; Cronet/58.0.2991.0)`; 110 | 111 | // TODO: Cache working app iid 112 | const appInstallIds = ["7355728856979392262"]; 113 | 114 | for (const iid of appInstallIds) { 115 | const queryString = new URLSearchParams({ 116 | // Provide the Aweme ID 117 | aweme_id: videoID, 118 | 119 | // App install ID 120 | iid, 121 | last_install_time: ( 122 | Math.floor(Date.now() / 1000) - randomInt(86400, 1123200) 123 | ).toString(), 124 | 125 | // Versioning 126 | aid: appId.toString(), 127 | app_name: appName, 128 | version_code: appVersion 129 | .split(".") 130 | .map((v) => v.padStart(2, "0")) 131 | .join(""), // 34.1.2 -> 340102 132 | version_name: appVersion, 133 | manifest_version_code: appManifestVersion, 134 | update_version_code: appManifestVersion, 135 | ab_version: appVersion, 136 | build_number: appVersion, 137 | 138 | // General 139 | ssmix: "a", 140 | channel: "googleplay", 141 | resolution: "1080*2400", 142 | dpi: "420", 143 | language: "en", 144 | os: "android", 145 | os_api: "29", 146 | os_version: "13", 147 | ac: "wifi", 148 | is_pad: "0", 149 | current_region: "US", 150 | app_type: "normal", 151 | sys_region: "US", 152 | timezone_name: "America/New_York", 153 | residence: "US", 154 | app_language: "en", 155 | timezone_offset: "-14400", 156 | host_abi: "armeabi-v7a", 157 | locale: "en", 158 | ac2: "wifi5g", 159 | uoo: "1", 160 | op_region: "US", 161 | region: "US", 162 | carrier_region: "US", 163 | 164 | // Derivative 165 | _rticket: Math.floor(Date.now()).toString(), 166 | // Random UUID 167 | cdid: uuidv4().toString(), 168 | // Random 16 character hex string 169 | opeudid: [...Array(16)] 170 | .map(() => Math.floor(Math.random() * 16).toString(16)) 171 | .join(""), 172 | ts: Math.floor(Date.now() / 1000).toString(), 173 | 174 | // Device meta 175 | // Shoutout: https://github.com/yt-dlp/yt-dlp/issues/9506#issuecomment-2020074295 176 | device_id: randomBigInt( 177 | 7250000000000000000n, 178 | 7351147085025500000n, 179 | ).toString(), 180 | device_type: "Pixel 7", 181 | device_brand: "Google", 182 | device_platform: "android", 183 | }); 184 | 185 | const res = await fetch( 186 | `https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/?${queryString.toString()}`, 187 | { 188 | headers: { 189 | // Hello, it's me, a human! 🤖 190 | "User-Agent": userAgent, 191 | }, 192 | cf: { 193 | cacheEverything: true, 194 | cacheTtlByStatus: { 195 | "200-299": 60 * 60, 196 | "400-499": 5, 197 | "500-599": 0, 198 | }, 199 | }, 200 | }, 201 | ); 202 | 203 | if (res.headers.get("Content-Length") === "0") continue; 204 | return res.json(); 205 | } 206 | 207 | return undefined; 208 | } 209 | } 210 | 211 | /** 212 | * Modern TikTok API 213 | */ 214 | //region Modern TikTok API 215 | export interface InternalItemDetail { 216 | aweme_list: Aweme[]; 217 | } 218 | 219 | export interface Aweme { 220 | aweme_id: string; 221 | music: { 222 | play_url: AssetDetail; 223 | }; 224 | author: { 225 | unique_id: string; 226 | }; 227 | video?: { 228 | // Prefer the last video in the url list 229 | // No format, but we can get it from the url 230 | play_addr: AssetDetail; 231 | cover: AssetDetail; 232 | }; 233 | image_post_info?: { 234 | images: { 235 | display_image: AssetDetail; 236 | }[]; 237 | }; 238 | statistics: { 239 | digg_count: number; 240 | comment_count: number; 241 | share_count: number; 242 | play_count: number; 243 | }; 244 | } 245 | 246 | export interface AssetDetail { 247 | uri: string; 248 | url_list: string[]; 249 | 250 | height: number; 251 | width: number; 252 | } 253 | 254 | //endregion 255 | 256 | /** 257 | * Adapted TikTok API 258 | */ 259 | //region Adapted TikTok API 260 | export interface MediaSource { 261 | url: string; 262 | width?: number; 263 | height?: number; 264 | } 265 | 266 | export interface AdaptedItemDetails { 267 | id: string; 268 | 269 | video: MediaSource; 270 | image: MediaSource; 271 | audio: MediaSource; 272 | 273 | statistics: { 274 | likes: number; 275 | comments: number; 276 | }; 277 | 278 | author: { 279 | username: string; 280 | }; 281 | 282 | imagePost?: { 283 | images: MediaSource[]; 284 | }; 285 | 286 | src: { 287 | type: "internal"; 288 | data: Aweme; 289 | }; 290 | } 291 | 292 | //endregion 293 | 294 | export const tiktok = new TikTokAPI(); 295 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "strict": true, 5 | "noEmit": true, 6 | "target": "es2021", 7 | "lib": [ 8 | "es2021" 9 | ], 10 | "module": "es2022", 11 | "skipLibCheck": true, 12 | "noImplicitAny": false, 13 | "esModuleInterop": true, 14 | "resolveJsonModule": true, 15 | "moduleResolution": "node", 16 | "allowSyntheticDefaultImports": true, 17 | "jsx": "react-jsx", 18 | "jsxImportSource": "hono/jsx", 19 | "types": [ 20 | "@cloudflare/workers-types" 21 | ], 22 | "paths": { 23 | "@/*": [ 24 | "./src/*" 25 | ] 26 | } 27 | }, 28 | "exclude": [ 29 | "node_modules" 30 | ], 31 | "include": [ 32 | "src" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "tiktxk" 2 | main = "src/index.tsx" 3 | workers_dev = true 4 | compatibility_date = "2022-09-24" 5 | account_id = "dd8e8772744b6e34e14fb0b77054ac41" --------------------------------------------------------------------------------