summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE674
-rw-r--r--_worker.js1564
-rw-r--r--package-lock.json1673
-rw-r--r--package.json17
-rw-r--r--proxy.txt20
-rw-r--r--wrangler.toml15
6 files changed, 3963 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/_worker.js b/_worker.js
new file mode 100644
index 0000000..7cc30d6
--- /dev/null
+++ b/_worker.js
@@ -0,0 +1,1564 @@
+// @ts-ignore
+import { connect } from 'cloudflare:sockets';
+
+// 建议修改为自己的 UUID
+let userID = '7597a4e5-bee0-470d-b50d-ebf412c00b47';
+
+// 生成配置文件的 Cloudflare 优选 IP (www.gov.se speed.cloudflare.com等使用Cloudflare CDN的网站也可以)
+const bestCFIP = "www.visa.com.hk"
+
+// 用于 Cloudflare 网站的代理 IP
+const proxyIPs = ['cdn.xn--b6gac.eu.org', 'cdn-all.xn--b6gac.eu.org']; // (https://github.com/HappyLeslieAlexander/Cloudflare_VLESS/blob/main/proxyip.txt 中的地址也可以)
+let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
+
+let dohURL = 'https://cloudflare-dns.com/dns-query'; // https://cloudflare-dns.com/dns-query or https://dns.google/dns-query
+
+// v2board api environment variables
+let nodeId = ''; // 1
+
+let apiToken = ''; //abcdefghijklmnopqrstuvwxyz123456
+
+let apiHost = ''; // api.v2board.com
+
+if (!isValidUUID(userID)) {
+ throw new Error('uuid is not valid');
+}
+
+export default {
+ /**
+ * @param {import("@cloudflare/workers-types").Request} request
+ * @param {{UID: string, PROXYIP: string, DNS_RESOLVER_URL: string, NODE_ID: int, API_HOST: string, API_TOKEN: string}} env
+ * @param {import("@cloudflare/workers-types").ExecutionContext} ctx
+ * @returns {Promise<Response>}
+ */
+ async fetch(request, env, ctx) {
+ try {
+ userID = env.UID || userID;
+ proxyIP = env.PROXYIP || proxyIP;
+ dohURL = env.DNS_RESOLVER_URL || dohURL;
+ nodeId = env.NODE_ID || nodeId;
+ apiToken = env.API_TOKEN || apiToken;
+ apiHost = env.API_HOST || apiHost;
+ const upgradeHeader = request.headers.get('Upgrade');
+ if (!upgradeHeader || upgradeHeader !== 'websocket') {
+ const url = new URL(request.url);
+ switch (url.pathname) {
+ case '/cf':
+ return new Response(JSON.stringify(request.cf, null, 4), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json;charset=utf-8",
+ },
+ });
+ case '/connect': // for test connect to Cloudflare socket
+ const [hostname, port] = ['cloudflare.com', '80'];
+ console.log(`Connecting to ${hostname}:${port}...`);
+
+ try {
+ const socket = await connect({
+ hostname: hostname,
+ port: parseInt(port, 10),
+ });
+
+ const writer = socket.writable.getWriter();
+
+ try {
+ await writer.write(new TextEncoder().encode('GET / HTTP/1.1\r\nHost: ' + hostname + '\r\n\r\n'));
+ } catch (writeError) {
+ writer.releaseLock();
+ await socket.close();
+ return new Response(writeError.message, { status: 500 });
+ }
+
+ writer.releaseLock();
+
+ const reader = socket.readable.getReader();
+ let value;
+
+ try {
+ const result = await reader.read();
+ value = result.value;
+ } catch (readError) {
+ await reader.releaseLock();
+ await socket.close();
+ return new Response(readError.message, { status: 500 });
+ }
+
+ await reader.releaseLock();
+ await socket.close();
+
+ return new Response(new TextDecoder().decode(value), { status: 200 });
+ } catch (connectError) {
+ return new Response(connectError.message, { status: 500 });
+ }
+ case `/${userID}`: {
+ const vlessConfig = getVLESSConfig(userID, request.headers.get('Host'));
+ return new Response(`${vlessConfig}`, {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain;charset=utf-8",
+ }
+ });
+ }
+ case `/${userID}/base64`: {
+ const base64Config = getBase64Config(userID, request.headers.get('Host'));
+ return new Response(`${base64Config}`, {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain;charset=utf-8",
+ }
+ });
+ }
+ case `/${userID}/clash`: {
+ const clashConfig = getClashConfig(userID, request.headers.get('Host'));
+ return new Response(`${clashConfig}`, {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain;charset=utf-8",
+ }
+ });
+ }
+ case `/${userID}/sb`: {
+ const singConfig = getSingConfig(userID, request.headers.get('Host'));
+ return new Response(`${singConfig}`, {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json;charset=utf-8",
+ }
+ });
+ }
+ default:
+ // return new Response('Not found', { status: 404 });
+ // For any other path, reverse proxy to 'www.visa.com.hk' and return the original response
+ url.hostname = 'www.visa.com.hk';
+ url.protocol = 'https:';
+ request = new Request(url, request);
+ return await fetch(request);
+ }
+ } else {
+ return await vlessOverWSHandler(request);
+ }
+ } catch (err) {
+ /** @type {Error} */ let e = err;
+ return new Response(e.toString());
+ }
+ },
+};
+
+
+
+
+/**
+ *
+ * @param {import("@cloudflare/workers-types").Request} request
+ */
+async function vlessOverWSHandler(request) {
+
+ /** @type {import("@cloudflare/workers-types").WebSocket[]} */
+ // @ts-ignore
+ const webSocketPair = new WebSocketPair();
+ const [client, webSocket] = Object.values(webSocketPair);
+
+ webSocket.accept();
+
+ let address = '';
+ let portWithRandomLog = '';
+ const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) => {
+ console.log(`[${address}:${portWithRandomLog}] ${info}`, event || '');
+ };
+ const earlyDataHeader = request.headers.get('sec-websocket-protocol') || '';
+
+ const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log);
+
+ /** @type {{ value: import("@cloudflare/workers-types").Socket | null}}*/
+ let remoteSocketWapper = {
+ value: null,
+ };
+ let udpStreamWrite = null;
+ let isDns = false;
+
+ // ws --> remote
+ readableWebSocketStream.pipeTo(new WritableStream({
+ async write(chunk, controller) {
+ if (isDns && udpStreamWrite) {
+ return udpStreamWrite(chunk);
+ }
+ if (remoteSocketWapper.value) {
+ const writer = remoteSocketWapper.value.writable.getWriter()
+ await writer.write(chunk);
+ writer.releaseLock();
+ return;
+ }
+
+ const {
+ hasError,
+ message,
+ portRemote = 443,
+ addressRemote = '',
+ rawDataIndex,
+ vlessVersion = new Uint8Array([0, 0]),
+ isUDP,
+ } = await processVlessHeader(chunk, userID);
+ address = addressRemote;
+ portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? 'udp ' : 'tcp '
+ } `;
+ if (hasError) {
+ // controller.error(message);
+ throw new Error(message); // Cloudflare seems has bug, controller.error will not end stream
+ // webSocket.close(1000, message);
+ return;
+ }
+ // if UDP but port not DNS port, close it
+ if (isUDP) {
+ if (portRemote === 53) {
+ isDns = true;
+ } else {
+ // controller.error('UDP proxy only enable for DNS which is port 53');
+ throw new Error('UDP proxy only enable for DNS which is port 53'); // Cloudflare seems has bug, controller.error will not end stream
+ return;
+ }
+ }
+ // ["version", "附加信息长度 N"]
+ const vlessResponseHeader = new Uint8Array([vlessVersion[0], 0]);
+ const rawClientData = chunk.slice(rawDataIndex);
+
+ // TODO: support udp here when Cloudflare runtime has udp support
+ if (isDns) {
+ const { write } = await handleUDPOutBound(webSocket, vlessResponseHeader, log);
+ udpStreamWrite = write;
+ udpStreamWrite(rawClientData);
+ return;
+ }
+ handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log);
+ },
+ close() {
+ log(`readableWebSocketStream is close`);
+ },
+ abort(reason) {
+ log(`readableWebSocketStream is abort`, JSON.stringify(reason));
+ },
+ })).catch((err) => {
+ log('readableWebSocketStream pipeTo error', err);
+ });
+
+ return new Response(null, {
+ status: 101,
+ // @ts-ignore
+ webSocket: client,
+ });
+}
+
+let apiResponseCache = null;
+let cacheTimeout = null;
+
+/**
+ * Fetches the API response from the server and caches it for future use.
+ * @returns {Promise<object|null>} A Promise that resolves to the API response object or null if there was an error.
+ */
+async function fetchApiResponse() {
+ const requestOptions = {
+ method: 'GET',
+ redirect: 'follow'
+ };
+
+ try {
+ const response = await fetch(`https://${apiHost}/api/v1/server/UniProxy/user?node_id=${nodeId}&node_type=v2ray&token=${apiToken}`, requestOptions);
+
+ if (!response.ok) {
+ console.error('Error: Network response was not ok');
+ return null;
+ }
+ const apiResponse = await response.json();
+ apiResponseCache = apiResponse;
+
+ // Refresh the cache every 5 minutes (300000 milliseconds)
+ if (cacheTimeout) {
+ clearTimeout(cacheTimeout);
+ }
+ cacheTimeout = setTimeout(() => fetchApiResponse(), 300000);
+
+ return apiResponse;
+ } catch (error) {
+ console.error('Error:', error);
+ return null;
+ }
+}
+
+/**
+ * Returns the cached API response if it exists, otherwise fetches the API response from the server and caches it for future use.
+ * @returns {Promise<object|null>} A Promise that resolves to the cached API response object or the fetched API response object, or null if there was an error.
+ */
+async function getApiResponse() {
+ if (!apiResponseCache) {
+ return await fetchApiResponse();
+ }
+ return apiResponseCache;
+}
+
+/**
+ * Checks if a given UUID is present in the API response.
+ * @param {string} targetUuid The UUID to search for.
+ * @returns {Promise<boolean>} A Promise that resolves to true if the UUID is present in the API response, false otherwise.
+ */
+async function checkUuidInApiResponse(targetUuid) {
+ // Check if any of the environment variables are empty
+ if (!nodeId || !apiToken || !apiHost) {
+ return false;
+ }
+
+ try {
+ const apiResponse = await getApiResponse();
+ if (!apiResponse) {
+ return false;
+ }
+ const isUuidInResponse = apiResponse.users.some(user => user.uuid === targetUuid);
+ return isUuidInResponse;
+ } catch (error) {
+ console.error('Error:', error);
+ return false;
+ }
+}
+
+// Usage example:
+// const targetUuid = "65590e04-a94c-4c59-a1f2-571bce925aad";
+// checkUuidInApiResponse(targetUuid).then(result => console.log(result));
+
+/**
+ * Handles outbound TCP connections.
+ *
+ * @param {any} remoteSocket
+ * @param {string} addressRemote The remote address to connect to.
+ * @param {number} portRemote The remote port to connect to.
+ * @param {Uint8Array} rawClientData The raw client data to write.
+ * @param {import("@cloudflare/workers-types").WebSocket} webSocket The WebSocket to pass the remote socket to.
+ * @param {Uint8Array} vlessResponseHeader The VLESS response header.
+ * @param {function} log The logging function.
+ * @returns {Promise<void>} The remote socket.
+ */
+async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,) {
+ async function connectAndWrite(address, port) {
+ /** @type {import("@cloudflare/workers-types").Socket} */
+ const tcpSocket = connect({
+ hostname: address,
+ port: port,
+ });
+ remoteSocket.value = tcpSocket;
+ log(`connected to ${address}:${port}`);
+ const writer = tcpSocket.writable.getWriter();
+ await writer.write(rawClientData); // first write, nomal is tls client hello
+ writer.releaseLock();
+ return tcpSocket;
+ }
+
+ // if the Cloudflare connect tcp socket have no incoming data, we retry to redirect ip
+ async function retry() {
+ const tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote)
+ // no matter retry success or not, close websocket
+ tcpSocket.closed.catch(error => {
+ console.log('retry tcpSocket closed error', error);
+ }).finally(() => {
+ safeCloseWebSocket(webSocket);
+ })
+ remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log);
+ }
+
+ const tcpSocket = await connectAndWrite(addressRemote, portRemote);
+
+ // when remoteSocket is ready, pass to websocket
+ // remote--> ws
+ remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, retry, log);
+}
+
+/**
+ *
+ * @param {import("@cloudflare/workers-types").WebSocket} webSocketServer
+ * @param {string} earlyDataHeader for ws 0rtt
+ * @param {(info: string)=> void} log for ws 0rtt
+ */
+function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) {
+ let readableStreamCancel = false;
+ const stream = new ReadableStream({
+ start(controller) {
+ webSocketServer.addEventListener('message', (event) => {
+ if (readableStreamCancel) {
+ return;
+ }
+ const message = event.data;
+ controller.enqueue(message);
+ });
+
+ // The event means that the client closed the client -> server stream.
+ // However, the server -> client stream is still open until you call close() on the server side.
+ // The WebSocket protocol says that a separate close message must be sent in each direction to fully close the socket.
+ webSocketServer.addEventListener('close', () => {
+ // client send close, need close server
+ // if stream is cancel, skip controller.close
+ safeCloseWebSocket(webSocketServer);
+ if (readableStreamCancel) {
+ return;
+ }
+ controller.close();
+ }
+ );
+ webSocketServer.addEventListener('error', (err) => {
+ log('webSocketServer has error');
+ controller.error(err);
+ }
+ );
+ // for ws 0rtt
+ const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
+ if (error) {
+ controller.error(error);
+ } else if (earlyData) {
+ controller.enqueue(earlyData);
+ }
+ },
+
+ pull(controller) {
+ // if ws can stop read if stream is full, we can implement backpressure
+ // https://streams.spec.whatwg.org/#example-rs-push-backpressure
+ },
+ cancel(reason) {
+ // 1. pipe WritableStream has error, this cancel will called, so ws handle server close into here
+ // 2. if readableStream is cancel, all controller.close/enqueue need skip,
+ // 3. but from testing controller.error still work even if readableStream is cancel
+ if (readableStreamCancel) {
+ return;
+ }
+ log(`ReadableStream was canceled, due to ${reason}`)
+ readableStreamCancel = true;
+ safeCloseWebSocket(webSocketServer);
+ }
+ });
+
+ return stream;
+
+}
+
+// https://xtls.github.io/development/protocols/vless.html
+// https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw
+
+/**
+ *
+ * @param { ArrayBuffer} vlessBuffer
+ * @param {string} userID
+ * @returns
+ */
+async function processVlessHeader(
+ vlessBuffer,
+ userID
+) {
+ if (vlessBuffer.byteLength < 24) {
+ return {
+ hasError: true,
+ message: 'invalid data',
+ };
+ }
+ const version = new Uint8Array(vlessBuffer.slice(0, 1));
+ let isValidUser = false;
+ let isUDP = false;
+ const slicedBuffer = new Uint8Array(vlessBuffer.slice(1, 17));
+ const slicedBufferString = stringify(slicedBuffer);
+
+ const uuids = userID.includes(',') ? userID.split(",") : [userID];
+
+ const checkUuidInApi = await checkUuidInApiResponse(slicedBufferString);
+ isValidUser = uuids.some(userUuid => checkUuidInApi || slicedBufferString === userUuid.trim());
+
+ console.log(`checkUuidInApi: ${await checkUuidInApiResponse(slicedBufferString)}, userID: ${slicedBufferString}`);
+
+ if (!isValidUser) {
+ return {
+ hasError: true,
+ message: 'invalid user',
+ };
+ }
+
+ const optLength = new Uint8Array(vlessBuffer.slice(17, 18))[0];
+ //skip opt for now
+
+ const command = new Uint8Array(
+ vlessBuffer.slice(18 + optLength, 18 + optLength + 1)
+ )[0];
+
+ // 0x01 TCP
+ // 0x02 UDP
+ // 0x03 MUX
+ if (command === 1) {
+ } else if (command === 2) {
+ isUDP = true;
+ } else {
+ return {
+ hasError: true,
+ message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`,
+ };
+ }
+ const portIndex = 18 + optLength + 1;
+ const portBuffer = vlessBuffer.slice(portIndex, portIndex + 2);
+ // port is big-Endian in raw data etc 80 == 0x005d
+ const portRemote = new DataView(portBuffer).getUint16(0);
+
+ let addressIndex = portIndex + 2;
+ const addressBuffer = new Uint8Array(
+ vlessBuffer.slice(addressIndex, addressIndex + 1)
+ );
+
+ // 1--> ipv4 addressLength =4
+ // 2--> domain name addressLength=addressBuffer[1]
+ // 3--> ipv6 addressLength =16
+ const addressType = addressBuffer[0];
+ let addressLength = 0;
+ let addressValueIndex = addressIndex + 1;
+ let addressValue = '';
+ switch (addressType) {
+ case 1:
+ addressLength = 4;
+ addressValue = new Uint8Array(
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
+ ).join('.');
+ break;
+ case 2:
+ addressLength = new Uint8Array(
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + 1)
+ )[0];
+ addressValueIndex += 1;
+ addressValue = new TextDecoder().decode(
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
+ );
+ break;
+ case 3:
+ addressLength = 16;
+ const dataView = new DataView(
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
+ );
+ // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
+ const ipv6 = [];
+ for (let i = 0; i < 8; i++) {
+ ipv6.push(dataView.getUint16(i * 2).toString(16));
+ }
+ addressValue = ipv6.join(':');
+ // seems no need add [] for ipv6
+ break;
+ default:
+ return {
+ hasError: true,
+ message: `invild addressType is ${addressType}`,
+ };
+ }
+ if (!addressValue) {
+ return {
+ hasError: true,
+ message: `addressValue is empty, addressType is ${addressType}`,
+ };
+ }
+
+ return {
+ hasError: false,
+ addressRemote: addressValue,
+ addressType,
+ portRemote,
+ rawDataIndex: addressValueIndex + addressLength,
+ vlessVersion: version,
+ isUDP,
+ };
+}
+
+
+/**
+ *
+ * @param {import("@cloudflare/workers-types").Socket} remoteSocket
+ * @param {import("@cloudflare/workers-types").WebSocket} webSocket
+ * @param {ArrayBuffer} vlessResponseHeader
+ * @param {(() => Promise<void>) | null} retry
+ * @param {*} log
+ */
+async function remoteSocketToWS(remoteSocket, webSocket, vlessResponseHeader, retry, log) {
+ // remote--> ws
+ let remoteChunkCount = 0;
+ let chunks = [];
+ /** @type {ArrayBuffer | null} */
+ let vlessHeader = vlessResponseHeader;
+ let hasIncomingData = false; // check if remoteSocket has incoming data
+ await remoteSocket.readable
+ .pipeTo(
+ new WritableStream({
+ start() {
+ },
+ /**
+ *
+ * @param {Uint8Array} chunk
+ * @param {*} controller
+ */
+ async write(chunk, controller) {
+ hasIncomingData = true;
+ // remoteChunkCount++;
+ if (webSocket.readyState !== WS_READY_STATE_OPEN) {
+ controller.error(
+ 'webSocket.readyState is not open, maybe close'
+ );
+ }
+ if (vlessHeader) {
+ webSocket.send(await new Blob([vlessHeader, chunk]).arrayBuffer());
+ vlessHeader = null;
+ } else {
+ // seems no need rate limit this, Cloudflare seems fix this??..
+ // if (remoteChunkCount > 20000) {
+ // // Cloudflare one package is 4096 byte(4kb), 4096 * 20000 = 80M
+ // await delay(1);
+ // }
+ webSocket.send(chunk);
+ }
+ },
+ close() {
+ log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`);
+ // safeCloseWebSocket(webSocket); // no need server close websocket frist for some case will casue HTTP ERR_CONTENT_LENGTH_MISMATCH issue, client will send close event anyway.
+ },
+ abort(reason) {
+ console.error(`remoteConnection!.readable abort`, reason);
+ },
+ })
+ )
+ .catch((error) => {
+ console.error(
+ `remoteSocketToWS has exception `,
+ error.stack || error
+ );
+ safeCloseWebSocket(webSocket);
+ });
+
+ // seems is Cloudflare connect socket have error,
+ // 1. Socket.closed will have error
+ // 2. Socket.readable will be close without any data coming
+ if (hasIncomingData === false && retry) {
+ log(`retry`)
+ retry();
+ }
+}
+
+/**
+ *
+ * @param {string} base64Str
+ * @returns
+ */
+function base64ToArrayBuffer(base64Str) {
+ if (!base64Str) {
+ return { error: null };
+ }
+ try {
+ // go use modified Base64 for URL rfc4648 which js atob not support
+ base64Str = base64Str.replace(/-/g, '+').replace(/_/g, '/');
+ const decode = atob(base64Str);
+ const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0));
+ return { earlyData: arryBuffer.buffer, error: null };
+ } catch (error) {
+ return { error };
+ }
+}
+
+/**
+ * This is not real UUID validation
+ * @param {string} uuid
+ */
+function isValidUUID(uuid) {
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+ return uuidRegex.test(uuid);
+}
+
+const WS_READY_STATE_OPEN = 1;
+const WS_READY_STATE_CLOSING = 2;
+/**
+ * Normally, WebSocket will not has exceptions when close.
+ * @param {import("@cloudflare/workers-types").WebSocket} socket
+ */
+function safeCloseWebSocket(socket) {
+ try {
+ if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) {
+ socket.close();
+ }
+ } catch (error) {
+ console.error('safeCloseWebSocket error', error);
+ }
+}
+
+const byteToHex = [];
+for (let i = 0; i < 256; ++i) {
+ byteToHex.push((i + 256).toString(16).slice(1));
+}
+function unsafeStringify(arr, offset = 0) {
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
+}
+function stringify(arr, offset = 0) {
+ const uuid = unsafeStringify(arr, offset);
+ if (!isValidUUID(uuid)) {
+ throw TypeError("Stringified UUID is invalid");
+ }
+ return uuid;
+}
+
+
+/**
+ *
+ * @param {import("@cloudflare/workers-types").WebSocket} webSocket
+ * @param {ArrayBuffer} vlessResponseHeader
+ * @param {(string)=> void} log
+ */
+async function handleUDPOutBound(webSocket, vlessResponseHeader, log) {
+
+ let isVlessHeaderSent = false;
+ const transformStream = new TransformStream({
+ start(controller) {
+
+ },
+ transform(chunk, controller) {
+ // udp message 2 byte is the the length of udp data
+ // TODO: this should have bug, beacsue maybe udp chunk can be in two websocket message
+ for (let index = 0; index < chunk.byteLength;) {
+ const lengthBuffer = chunk.slice(index, index + 2);
+ const udpPakcetLength = new DataView(lengthBuffer).getUint16(0);
+ const udpData = new Uint8Array(
+ chunk.slice(index + 2, index + 2 + udpPakcetLength)
+ );
+ index = index + 2 + udpPakcetLength;
+ controller.enqueue(udpData);
+ }
+ },
+ flush(controller) {
+ }
+ });
+
+ // only handle dns udp for now
+ transformStream.readable.pipeTo(new WritableStream({
+ async write(chunk) {
+ const resp = await fetch(dohURL, // dns server url
+ {
+ method: 'POST',
+ headers: {
+ 'content-type': 'application/dns-message',
+ },
+ body: chunk,
+ })
+ const dnsQueryResult = await resp.arrayBuffer();
+ const udpSize = dnsQueryResult.byteLength;
+ // console.log([...new Uint8Array(dnsQueryResult)].map((x) => x.toString(16)));
+ const udpSizeBuffer = new Uint8Array([(udpSize >> 8) & 0xff, udpSize & 0xff]);
+ if (webSocket.readyState === WS_READY_STATE_OPEN) {
+ log(`doh success and dns message length is ${udpSize}`);
+ if (isVlessHeaderSent) {
+ webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer());
+ } else {
+ webSocket.send(await new Blob([vlessResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer());
+ isVlessHeaderSent = true;
+ }
+ }
+ }
+ })).catch((error) => {
+ log('dns udp has error' + error)
+ });
+
+ const writer = transformStream.writable.getWriter();
+
+ return {
+ /**
+ *
+ * @param {Uint8Array} chunk
+ */
+ write(chunk) {
+ writer.write(chunk);
+ }
+ };
+}
+
+/**
+ *
+ * @param {string} userID
+ * @param {string | null} hostName
+ * @returns {string}
+ */
+function getVLESSConfig(userID, hostName) {
+ const vlessLink = `vless://${userID}\u0040${bestCFIP}:80?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Workers/Pages`
+ const vlessTlsLink = `vless://${userID}\u0040${bestCFIP}:443?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Workers/Pages-TLS`
+ return `
+下面是非 TLS 端口的节点信息及节点分享链接,可使用 Cloudflare 支持的非 TLS 端口:
+
+地址:${hostName} 或 Cloudflare 优选 IP
+端口:80 或 Cloudflare 支持的非 TLS 端口
+UUID:${userID}
+传输:ws
+伪装域名:${hostName}
+路径:/?ed=2048
+
+${vlessLink}
+
+下面是 TLS 端口的节点信息及节点分享链接,可使用 Cloudflare 支持的 TLS 端口:
+
+地址:${hostName} 或 Cloudflare 优选 IP
+端口:443 或 Cloudflare 支持的 TLS 端口
+UUID:${userID}
+传输:ws
+传输层安全:TLS
+伪装域名:${hostName}
+路径:/?ed=2048
+SNI 域名:${hostName}
+
+${vlessTlsLink}
+
+Base64 通用节点订阅链接:https://${hostName}/${userID}/base64
+Clash 配置文件订阅链接:https://${hostName}/${userID}/clash
+Sing-box 配置文件订阅链接:https://${hostName}/${userID}/sb
+
+提示:部分地区有 Cloudflare 默认域名被污染的情况,除非打开客户端的 TLS 分片功能,否则无法使用 TLS 端口的节点
+如为 Pages 部署的节点则只能使用 TLS 端口的节点
+---------------------------------------------------------------
+捐赠
+加密货币
+TRON
+TY7n1xwiHCBqcQqGH1cxjTQqZTuTXbzB4S
+Ethereum
+0xed57e7237e88cec19d3fd12a0d26bacb1dcc247b
+Polygon
+0xed57e7237e88cec19d3fd12a0d26bacb1dcc247b
+TON
+UQC4r4gxAIbOTEEZGG-C1Ffn9inRo24J7qw3U0dFfaIfKyFr
+---------------------------------------------------------------
+联系
+Telegram: https://t.me/Depressed_LeslieAlexander/
+E-mail: https://github.com/HappyLeslieAlexander/
+项目地址: https://github.com/HappyLeslieAlexander/Cloudflare_VLESS/
+By Leslie Alexander
+`;
+}
+
+function getBase64Config(userID, hostName) {
+ const vlessLinks = btoa(`vless://${userID}\u0040${bestCFIP}:80?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-80\nvless://${userID}\u0040${bestCFIP}:8080?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-8080\nvless://${userID}\u0040${bestCFIP}:8880?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-8880\nvless://${userID}\u0040${bestCFIP}:2052?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-2052\nvless://${userID}\u0040${bestCFIP}:2082?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-2082\nvless://${userID}\u0040${bestCFIP}:2086?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-2086\nvless://${userID}\u0040${bestCFIP}:2095?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-2095\nvless://${userID}\u0040${bestCFIP}:443?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-443\nvless://${userID}\u0040${bestCFIP}:2053?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-2053\nvless://${userID}\u0040${bestCFIP}:2083?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-2083\nvless://${userID}\u0040${bestCFIP}:2087?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-2087\nvless://${userID}\u0040${bestCFIP}:2096?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-2096\nvless://${userID}\u0040${bestCFIP}:8443?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#Leslie-Cloudflare-vless-TLS-8443`);
+
+ return `${vlessLinks}`
+}
+
+function getClashConfig(userID, hostName) {
+ return `port: 7890
+allow-lan: true
+mode: rule
+log-level: info
+unified-delay: true
+global-client-fingerprint: chrome
+dns:
+ enable: true
+ listen: :53
+ ipv6: true
+ enhanced-mode: fake-ip
+ fake-ip-range: 198.18.0.1/16
+ default-nameserver:
+ - 223.5.5.5
+ - 1.1.1.1
+ nameserver:
+ - https://dns.alidns.com/dns-query
+ - https://cloudflare-dns.com/dns-query
+ fallback:
+ - https://cloudflare-dns.com/dns-query
+ fallback-filter:
+ geoip: true
+ geoip-code: CN
+ ipcidr:
+ - 240.0.0.0/4
+
+proxies:
+- name: Cloudflare-vless-80
+ type: vless
+ server: ${bestCFIP}
+ port: 80
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-8080
+ type: vless
+ server: ${bestCFIP}
+ port: 8080
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-8880
+ type: vless
+ server: ${bestCFIP}
+ port: 8880
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-2052
+ type: vless
+ server: ${bestCFIP}
+ port: 2052
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-2082
+ type: vless
+ server: ${bestCFIP}
+ port: 2082
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-2086
+ type: vless
+ server: ${bestCFIP}
+ port: 2086
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-2095
+ type: vless
+ server: ${bestCFIP}
+ port: 2095
+ uuid: ${userID}
+ udp: false
+ tls: false
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-443
+ type: vless
+ server: ${bestCFIP}
+ port: 443
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-2053
+ type: vless
+ server: ${bestCFIP}
+ port: 2053
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-2083
+ type: vless
+ server: ${bestCFIP}
+ port: 2083
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-2087
+ type: vless
+ server: ${bestCFIP}
+ port: 2087
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-2096
+ type: vless
+ server: ${bestCFIP}
+ port: 2096
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+- name: Cloudflare-vless-tls-8443
+ type: vless
+ server: ${bestCFIP}
+ port: 8443
+ uuid: ${userID}
+ udp: false
+ tls: true
+ network: ws
+ servername: ${hostName}
+ ws-opts:
+ path: "/?ed=2048"
+ headers:
+ Host: ${hostName}
+
+proxy-groups:
+- name: 负载均衡
+ type: load-balance
+ url: http://www.gstatic.com/generate_204
+ interval: 300
+ proxies:
+ - Cloudflare-vless-80
+ - Cloudflare-vless-8080
+ - Cloudflare-vless-8880
+ - Cloudflare-vless-2052
+ - Cloudflare-vless-2082
+ - Cloudflare-vless-2086
+ - Cloudflare-vless-2095
+ - Cloudflare-vless-tls-443
+ - Cloudflare-vless-tls-2053
+ - Cloudflare-vless-tls-2083
+ - Cloudflare-vless-tls-2087
+ - Cloudflare-vless-tls-2096
+ - Cloudflare-vless-tls-8443
+
+- name: 自动选择
+ type: url-test
+ url: http://www.gstatic.com/generate_204
+ interval: 300
+ tolerance: 50
+ proxies:
+ - Cloudflare-vless-80
+ - Cloudflare-vless-8080
+ - Cloudflare-vless-8880
+ - Cloudflare-vless-2052
+ - Cloudflare-vless-2082
+ - Cloudflare-vless-2086
+ - Cloudflare-vless-2095
+ - Cloudflare-vless-tls-443
+ - Cloudflare-vless-tls-2053
+ - Cloudflare-vless-tls-2083
+ - Cloudflare-vless-tls-2087
+ - Cloudflare-vless-tls-2096
+ - Cloudflare-vless-tls-8443
+
+- name: 🌍选择代理
+ type: select
+ proxies:
+ - 负载均衡
+ - 自动选择
+ - DIRECT
+ - Cloudflare-vless-80
+ - Cloudflare-vless-8080
+ - Cloudflare-vless-8880
+ - Cloudflare-vless-2052
+ - Cloudflare-vless-2082
+ - Cloudflare-vless-2086
+ - Cloudflare-vless-2095
+ - Cloudflare-vless-tls-443
+ - Cloudflare-vless-tls-2053
+ - Cloudflare-vless-tls-2083
+ - Cloudflare-vless-tls-2087
+ - Cloudflare-vless-tls-2096
+ - Cloudflare-vless-tls-8443
+
+rules:
+ - GEOIP,LAN,DIRECT
+ - GEOIP,CN,DIRECT
+ - MATCH,🌍选择代理`
+}
+
+function getSingConfig(userID, hostName) {
+ return `{
+ "log": {
+ "disabled": false,
+ "level": "info",
+ "timestamp": true
+ },
+ "experimental": {
+ "clash_api": {
+ "external_controller": "127.0.0.1:9090",
+ "external_ui": "ui",
+ "external_ui_download_url": "",
+ "external_ui_download_detour": "",
+ "secret": "",
+ "default_mode": "Rule"
+ },
+ "cache_file": {
+ "enabled": true,
+ "path": "cache.db",
+ "store_fakeip": true
+ }
+ },
+ "dns": {
+ "fakeip": {
+ "enabled": true,
+ "inet4_range": "198.18.0.0/15",
+ "inet6_range": "fc00::/18"
+ },
+ "independent_cache": true,
+ "rules": [
+ {
+ "outbound": [
+ "any"
+ ],
+ "server": "local"
+ },
+ {
+ "query_type": [
+ "A",
+ "AAAA"
+ ],
+ "rewrite_ttl": 1,
+ "server": "fakeip"
+ },
+ {
+ "clash_mode": "global",
+ "server": "remote"
+ },
+ {
+ "clash_mode": "direct",
+ "server": "local"
+ },
+ {
+ "rule_set": "geosite-cn",
+ "server": "local"
+ }
+ ],
+ "servers": [
+ {
+ "address": "https://cloudflare-dns.com/dns-query",
+ "detour": "select",
+ "tag": "remote"
+ },
+ {
+ "address": "https://dns.alidns.com/dns-query",
+ "detour": "direct",
+ "tag": "local"
+ },
+ {
+ "address": "rcode://success",
+ "tag": "block"
+ },
+ {
+ "address": "fakeip",
+ "tag": "fakeip"
+ }
+ ],
+ "strategy": "prefer_ipv4"
+ },
+ "experimental": {
+ "cache_file": {
+ "enabled": true
+ },
+ "clash_api": {
+ "external_controller": "127.0.0.1:9090",
+ "secret": ""
+ }
+ },
+ "inbounds": [
+ {
+ "auto_route": true,
+ "domain_strategy": "prefer_ipv4",
+ "endpoint_independent_nat": true,
+ "inet4_address": "172.19.0.1/30",
+ "inet6_address": "2001:0470:f9da:fdfa::1/64",
+ "mtu": 9000,
+ "sniff": true,
+ "strict_route": true,
+ "type": "tun"
+ },
+ {
+ "domain_strategy": "prefer_ipv4",
+ "listen": "127.0.0.1",
+ "listen_port": 2333,
+ "tag": "socks-in",
+ "type": "socks",
+ "users": []
+ },
+ {
+ "domain_strategy": "prefer_ipv4",
+ "listen": "127.0.0.1",
+ "listen_port": 2334,
+ "tag": "mixed-in",
+ "type": "mixed",
+ "users": []
+ }
+ ],
+ "log": {},
+ "outbounds": [
+ {
+ "tag": "select",
+ "type": "selector",
+ "default": "urltest",
+ "outbounds": [
+ "urltest",
+ "Cloudflare-vless-80",
+ "Cloudflare-vless-8080",
+ "Cloudflare-vless-8880",
+ "Cloudflare-vless-2052",
+ "Cloudflare-vless-2082",
+ "Cloudflare-vless-2086",
+ "Cloudflare-vless-2095",
+ "Cloudflare-vless-tls-443",
+ "Cloudflare-vless-tls-2053",
+ "Cloudflare-vless-tls-2083",
+ "Cloudflare-vless-tls-2087",
+ "Cloudflare-vless-tls-2096",
+ "Cloudflare-vless-tls-8443"
+ ]
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 80,
+ "tag": "Cloudflare-vless-80",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 8080,
+ "tag": "Cloudflare-vless-8080",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 8880,
+ "tag": "Cloudflare-vless-8880",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2052,
+ "tag": "Cloudflare-vless-2052",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2082,
+ "tag": "Cloudflare-vless-2082",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2086,
+ "tag": "Cloudflare-vless-2086",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2095,
+ "tag": "Cloudflare-vless-2095",
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 443,
+ "tag": "Cloudflare-vless-tls-443",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2053,
+ "tag": "Cloudflare-vless-tls-2053",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2083,
+ "tag": "Cloudflare-vless-tls-2083",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2087,
+ "tag": "Cloudflare-vless-tls-2087",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 2096,
+ "tag": "Cloudflare-vless-tls-2096",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "server": "www.visa.com.hk",
+ "server_port": 8443,
+ "tag": "Cloudflare-vless-tls-8443",
+ "tls": {
+ "enabled": true,
+ "server_name": "${hostName}"
+ },
+ "transport": {
+ "headers": {
+ "Host": [
+ "${hostName}"
+ ]
+ },
+ "path": "/?ed=2048",
+ "type": "ws"
+ },
+ "type": "vless",
+ "uuid": "${userID}",
+ "packet_encoding": "xudp"
+ },
+ {
+ "tag": "urltest",
+ "type": "urltest",
+ "outbounds": [
+ "Cloudflare-vless-80",
+ "Cloudflare-vless-8080",
+ "Cloudflare-vless-8880",
+ "Cloudflare-vless-2052",
+ "Cloudflare-vless-2082",
+ "Cloudflare-vless-2086",
+ "Cloudflare-vless-2095",
+ "Cloudflare-vless-tls-443",
+ "Cloudflare-vless-tls-2053",
+ "Cloudflare-vless-tls-2083",
+ "Cloudflare-vless-tls-2087",
+ "Cloudflare-vless-tls-2096",
+ "Cloudflare-vless-tls-8443"
+ ]
+ },
+ {
+ "tag": "direct",
+ "type": "direct"
+ },
+ {
+ "tag": "block",
+ "type": "block"
+ },
+ {
+ "tag": "dns-out",
+ "type": "dns"
+ }
+ ],
+ "route": {
+ "auto_detect_interface": true,
+ "rule_set": [
+ {
+ "format": "binary",
+ "tag": "geoip-cn",
+ "type": "remote",
+ "url": "https://mirror.ghproxy.com/https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
+ },
+ {
+ "format": "binary",
+ "tag": "geosite-cn",
+ "type": "remote",
+ "url": "https://mirror.ghproxy.com/https://raw.githubusercontent.com/xmdhs/sing-geosite/rule-set-Loyalsoldier/geosite-geolocation-cn.srs"
+ }
+ ],
+ "rules": [
+ {
+ "outbound": "dns-out",
+ "port": 53
+ },
+ {
+ "clash_mode": "direct",
+ "outbound": "direct"
+ },
+ {
+ "clash_mode": "global",
+ "outbound": "select"
+ },
+ {
+ "ip_is_private": true,
+ "outbound": "direct"
+ },
+ {
+ "outbound": "direct",
+ "rule_set": "geoip-cn"
+ }
+ ]
+ }
+}`;
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..b8381bc
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1673 @@
+{
+ "name": "edtunnel",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "edtunnel",
+ "version": "1.0.0",
+ "license": "ISC",
+ "devDependencies": {
+ "@cloudflare/workers-types": "^4.20230710.1",
+ "wrangler": "^3.2.0"
+ }
+ },
+ "node_modules/@cloudflare/kv-asset-handler": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz",
+ "integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==",
+ "dev": true,
+ "dependencies": {
+ "mime": "^3.0.0"
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-64": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230710.0.tgz",
+ "integrity": "sha512-TDEgTfzTkveW+U0qtg9/60PXbl2klnEso0oio501zAnY2SOC1x7M0qb8UkhvjHFUVpwdykUzTPWPIWFBcF1ibA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-arm64": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230710.0.tgz",
+ "integrity": "sha512-dxBwnKcj7TiM1JGiODg0LASa25A9P0XLeMkmF8YCECZoq+3QLH/uY4Vbm1xeEy8iXUZrt/uYN72bBE83vY4HIQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-64": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230710.0.tgz",
+ "integrity": "sha512-WrKZwL76i51jQLFpSxklpRSm2s8T9Xf6tVzQaiLTtpguKZSF/CTAyjjEOVfS7FXk+Te8lyAJAFQnj5QHoJ3pzA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-arm64": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230710.0.tgz",
+ "integrity": "sha512-eWdbOoqFqQ4m1/Wwy2dRDaOVXjOmWGjwBliU8pvm2m9RjfRTdfik7z6E3vOkalxqJDHiJ0f8SUykKz2oM1lD0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-windows-64": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230710.0.tgz",
+ "integrity": "sha512-P5ihH98Pb72HrsVsvb/HCSezvAvEtPeVQVBKgIclNE9e0fkA4zX9QMzBBFvLy3yr0YLf4r7MO2tNnt7JFnheGA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workers-types": {
+ "version": "4.20230710.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230710.1.tgz",
+ "integrity": "sha512-VqEY/ZqyHKBn6ivdePSWebpqojwbCXVEuwLkMYHs0UoOAqcGylkVcabdZYdQJKeNxXcOUZ9UBId/x9UsPUm2XQ==",
+ "dev": true
+ },
+ "node_modules/@esbuild-plugins/node-globals-polyfill": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz",
+ "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==",
+ "dev": true,
+ "peerDependencies": {
+ "esbuild": "*"
+ }
+ },
+ "node_modules/@esbuild-plugins/node-modules-polyfill": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz",
+ "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^4.0.0",
+ "rollup-plugin-node-polyfills": "^0.2.1"
+ },
+ "peerDependencies": {
+ "esbuild": "*"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.3.tgz",
+ "integrity": "sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.3.tgz",
+ "integrity": "sha512-RolFVeinkeraDvN/OoRf1F/lP0KUfGNb5jxy/vkIMeRRChkrX/HTYN6TYZosRJs3a1+8wqpxAo5PI5hFmxyPRg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.3.tgz",
+ "integrity": "sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.3.tgz",
+ "integrity": "sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.3.tgz",
+ "integrity": "sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.3.tgz",
+ "integrity": "sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.3.tgz",
+ "integrity": "sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.3.tgz",
+ "integrity": "sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.3.tgz",
+ "integrity": "sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.3.tgz",
+ "integrity": "sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.3.tgz",
+ "integrity": "sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.3.tgz",
+ "integrity": "sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.3.tgz",
+ "integrity": "sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.3.tgz",
+ "integrity": "sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.3.tgz",
+ "integrity": "sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.3.tgz",
+ "integrity": "sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.3.tgz",
+ "integrity": "sha512-AzbsJqiHEq1I/tUvOfAzCY15h4/7Ivp3ff/o1GpP16n48JMNAtbW0qui2WCgoIZArEHD0SUQ95gvR0oSO7ZbdA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.3.tgz",
+ "integrity": "sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.3.tgz",
+ "integrity": "sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.3.tgz",
+ "integrity": "sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.3.tgz",
+ "integrity": "sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.3.tgz",
+ "integrity": "sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/as-table": {
+ "version": "1.0.55",
+ "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz",
+ "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==",
+ "dev": true,
+ "dependencies": {
+ "printable-characters": "^1.0.42"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/better-sqlite3": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.4.0.tgz",
+ "integrity": "sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "prebuild-install": "^7.1.0"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/blake3-wasm": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
+ "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "dev": true
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dev": true,
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/capnp-ts": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz",
+ "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.1",
+ "tslib": "^2.2.0"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "dev": true
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
+ "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.3.tgz",
+ "integrity": "sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.16.3",
+ "@esbuild/android-arm64": "0.16.3",
+ "@esbuild/android-x64": "0.16.3",
+ "@esbuild/darwin-arm64": "0.16.3",
+ "@esbuild/darwin-x64": "0.16.3",
+ "@esbuild/freebsd-arm64": "0.16.3",
+ "@esbuild/freebsd-x64": "0.16.3",
+ "@esbuild/linux-arm": "0.16.3",
+ "@esbuild/linux-arm64": "0.16.3",
+ "@esbuild/linux-ia32": "0.16.3",
+ "@esbuild/linux-loong64": "0.16.3",
+ "@esbuild/linux-mips64el": "0.16.3",
+ "@esbuild/linux-ppc64": "0.16.3",
+ "@esbuild/linux-riscv64": "0.16.3",
+ "@esbuild/linux-s390x": "0.16.3",
+ "@esbuild/linux-x64": "0.16.3",
+ "@esbuild/netbsd-x64": "0.16.3",
+ "@esbuild/openbsd-x64": "0.16.3",
+ "@esbuild/sunos-x64": "0.16.3",
+ "@esbuild/win32-arm64": "0.16.3",
+ "@esbuild/win32-ia32": "0.16.3",
+ "@esbuild/win32-x64": "0.16.3"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
+ "dev": true
+ },
+ "node_modules/exit-hook": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz",
+ "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-source": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
+ "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==",
+ "dev": true,
+ "dependencies": {
+ "data-uri-to-buffer": "^2.0.0",
+ "source-map": "^0.6.1"
+ }
+ },
+ "node_modules/get-source/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "dev": true
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "dev": true
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "dev": true
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
+ "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+ "dev": true,
+ "dependencies": {
+ "sourcemap-codec": "^1.4.8"
+ }
+ },
+ "node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/miniflare": {
+ "version": "3.20230710.0",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230710.0.tgz",
+ "integrity": "sha512-kVxJoJFeepK+rGJp9UN0D8d3sL6hjFbzd3qcLUUUKosp0ouoleOa6uPNK0b8fEBWWqFUD2W4V4ziN7UvXFB4pg==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-walk": "^8.2.0",
+ "better-sqlite3": "^8.1.0",
+ "capnp-ts": "^0.7.0",
+ "exit-hook": "^2.2.1",
+ "glob-to-regexp": "^0.4.1",
+ "http-cache-semantics": "^4.1.0",
+ "kleur": "^4.1.5",
+ "set-cookie-parser": "^2.6.0",
+ "source-map-support": "0.5.21",
+ "stoppable": "^1.1.0",
+ "undici": "^5.13.0",
+ "workerd": "1.20230710.0",
+ "ws": "^8.11.0",
+ "youch": "^3.2.2",
+ "zod": "^3.20.6"
+ },
+ "engines": {
+ "node": ">=16.13"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mustache": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
+ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
+ "dev": true,
+ "bin": {
+ "mustache": "bin/mustache"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "dev": true
+ },
+ "node_modules/node-abi": {
+ "version": "3.45.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz",
+ "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
+ "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+ "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+ "dev": true,
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/printable-characters": {
+ "version": "1.0.42",
+ "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
+ "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
+ "dev": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rollup-plugin-inject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz",
+ "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==",
+ "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.",
+ "dev": true,
+ "dependencies": {
+ "estree-walker": "^0.6.1",
+ "magic-string": "^0.25.3",
+ "rollup-pluginutils": "^2.8.1"
+ }
+ },
+ "node_modules/rollup-plugin-node-polyfills": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz",
+ "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==",
+ "dev": true,
+ "dependencies": {
+ "rollup-plugin-inject": "^3.0.0"
+ }
+ },
+ "node_modules/rollup-pluginutils": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+ "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
+ "dev": true,
+ "dependencies": {
+ "estree-walker": "^0.6.1"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/selfsigned": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz",
+ "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==",
+ "dev": true,
+ "dependencies": {
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+ "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
+ "dev": true
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "deprecated": "Please use @jridgewell/sourcemap-codec instead",
+ "dev": true
+ },
+ "node_modules/stacktracey": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz",
+ "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==",
+ "dev": true,
+ "dependencies": {
+ "as-table": "^1.0.36",
+ "get-source": "^2.0.12"
+ }
+ },
+ "node_modules/stoppable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
+ "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dev": true,
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
+ "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
+ "dev": true
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/undici": {
+ "version": "5.22.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz",
+ "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==",
+ "dev": true,
+ "dependencies": {
+ "busboy": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/workerd": {
+ "version": "1.20230710.0",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230710.0.tgz",
+ "integrity": "sha512-4iC+8w3UNixJ+b6GA2VOG2B6rnfSbSnm7Fnvsvq9iJuolG34fnD9xrfaXu6oN7H3Wyby3z8OIm0fy3szTvuRcg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "workerd": "bin/workerd"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "@cloudflare/workerd-darwin-64": "1.20230710.0",
+ "@cloudflare/workerd-darwin-arm64": "1.20230710.0",
+ "@cloudflare/workerd-linux-64": "1.20230710.0",
+ "@cloudflare/workerd-linux-arm64": "1.20230710.0",
+ "@cloudflare/workerd-windows-64": "1.20230710.0"
+ }
+ },
+ "node_modules/wrangler": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.2.0.tgz",
+ "integrity": "sha512-Fne5c91uolV4+E0B60F/meWbD/sr/oSPBfr6x1gapu6I7Ipu5uUt29K/fuGRgXRQcVVKnd5k3fS++ruuLODoxA==",
+ "dev": true,
+ "dependencies": {
+ "@cloudflare/kv-asset-handler": "^0.2.0",
+ "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
+ "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
+ "blake3-wasm": "^2.1.5",
+ "chokidar": "^3.5.3",
+ "esbuild": "0.16.3",
+ "miniflare": "3.20230710.0",
+ "nanoid": "^3.3.3",
+ "path-to-regexp": "^6.2.0",
+ "selfsigned": "^2.0.1",
+ "source-map": "^0.7.4",
+ "xxhash-wasm": "^1.0.1"
+ },
+ "bin": {
+ "wrangler": "bin/wrangler.js",
+ "wrangler2": "bin/wrangler.js"
+ },
+ "engines": {
+ "node": ">=16.13.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/ws": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xxhash-wasm": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
+ "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/youch": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/youch/-/youch-3.2.3.tgz",
+ "integrity": "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==",
+ "dev": true,
+ "dependencies": {
+ "cookie": "^0.5.0",
+ "mustache": "^4.2.0",
+ "stacktracey": "^2.1.8"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.21.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
+ "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9cd9537
--- /dev/null
+++ b/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "edtunnel",
+ "version": "1.0.0",
+ "description": "A tunnel for the edgetunnel project to allow deployed applications to cloudflare pages and workers to be accessed via a custom domain.",
+ "main": "_worker.js",
+ "scripts": {
+ "deploy": "wrangler deploy",
+ "build": "wrangler deploy",
+ "dev": "wrangler dev --remote"
+ },
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "@cloudflare/workers-types": "^4.20230710.1",
+ "wrangler": "^3.2.0"
+ }
+} \ No newline at end of file
diff --git a/proxy.txt b/proxy.txt
new file mode 100644
index 0000000..d0089af
--- /dev/null
+++ b/proxy.txt
@@ -0,0 +1,20 @@
+cdn-all.xn--b6gac.eu.org
+cdn.xn--b6gac.eu.org
+cdn-b100.xn--b6gac.eu.org
+bestproxy.onecf.eu.org
+ipdb.rr.nu
+
+proxyip.fxxk.dedyn.io
+IP落地区域: 美国 维护频率: 12小时/次
+proxyip.sg.fxxk.dedyn.io
+IP落地区域: 新加坡 维护频率: 12小时/次
+proxyip.jp.fxxk.dedyn.io
+IP落地区域: 日本 维护频率: 12小时/次
+proxyip.hk.fxxk.dedyn.io
+IP落地区域: 香港 维护频率: 12小时/次
+proxyip.aliyun.fxxk.dedyn.io
+IP落地区域: 阿里云 维护频率: 4小时/次
+proxyip.oracle.fxxk.dedyn.io
+IP落地区域: 甲骨文 维护频率: 4小时/次
+proxyip.digitalocean.fxxk.dedyn.io
+IP落地区域: 数码海 维护频率: 4小时/次
diff --git a/wrangler.toml b/wrangler.toml
new file mode 100644
index 0000000..b3eb61d
--- /dev/null
+++ b/wrangler.toml
@@ -0,0 +1,15 @@
+name = "cf-worker-ws-dev" # todo
+#name = "cf-worker-connect-test" # todo
+#main = "test/worker/cf-cdn-cgi-trace2.js"
+#main = "test/worker/worker-connect-test.js"
+main = "_worker.js"
+compatibility_date = "2024-07-19"
+
+[vars]
+UUID = "7597a4e5-bee0-470d-b50d-ebf412c00b47"
+# PROXYIP = "1.2.3.4"
+# DNS_RESOLVER_URL = "https://cloudflare-dns.com/dns-query"
+# NODE_ID = "1"
+# API_TOKEN = "example_dev_token"
+# API_HOST = "api.v2board.com"
+# UUID = "1b6c1745-992e-4aac-8685-266c090e50ea,89b64978-6244-4bf3-bf64-67ade4ce5c8f"