├── .github
├── actions
│ └── bump-manifest-version.js
└── workflows
│ └── cd.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── fxmanifest.lua
├── game
├── client
│ ├── bootstrap.ts
│ ├── event.ts
│ ├── tsconfig.json
│ ├── types.ts
│ └── utils.ts
├── nui
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── capture-stream.ts
│ │ ├── capture.ts
│ │ ├── main.ts
│ │ ├── style.css
│ │ ├── types.ts
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ └── vite.config.js
├── package.json
├── scripts
│ ├── esbuild.config.js
│ ├── handle-build.js
│ └── node-paths.js
└── server
│ ├── bootstrap.ts
│ ├── context.ts
│ ├── event.ts
│ ├── export.ts
│ ├── koa-router.ts
│ ├── multer.ts
│ ├── tsconfig.json
│ ├── types.ts
│ └── upload-store.ts
├── package.json
├── packages
├── gameview
│ ├── index.ts
│ ├── package.json
│ ├── tsconfig.json
│ └── webgl.ts
├── react
│ ├── index.ts
│ ├── package.json
│ ├── tsconfig.json
│ ├── useCaptureScreen.ts
│ └── utils.ts
└── typescript-config
│ ├── base.json
│ ├── package.json
│ └── react.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── turbo.json
/.github/actions/bump-manifest-version.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 |
3 | const version = process.env.TGT_RELEASE_VERSION;
4 | const newVersion = version.replace("v", "");
5 |
6 | const manifestFile = fs.readFileSync("fxmanifest.lua", { encoding: "utf8" });
7 |
8 | const newFileContent = manifestFile.replace(
9 | /\bversion\s+(.*)$/gm,
10 | `version '${newVersion}'`
11 | );
12 |
13 | fs.writeFileSync("fxmanifest.lua", newFileContent);
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | permissions:
4 | contents: write
5 |
6 | on:
7 | push:
8 | tags:
9 | - "v*.*.*"
10 |
11 | jobs:
12 | create-release:
13 | name: Build and Create Tagged release
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Install archive tools
18 | run: sudo apt install zip
19 |
20 | - name: Checkout source code
21 | uses: actions/checkout@v4
22 | with:
23 | fetch-depth: 0
24 | ref: ${{ github.event.repository.default_branch }}
25 |
26 | - name: Install pnpm
27 | uses: pnpm/action-setup@v4.0.0
28 | with:
29 | version: 9.11.0
30 |
31 | - name: Get variables
32 | id: get_vars
33 | run: |
34 | echo '::set-output name=SHORT_SHA::$(git rev-parse --short HEAD)'
35 | echo '::set-output name=DATE::$(date +'%D')'
36 |
37 | - name: Setup node
38 | uses: actions/setup-node@v4
39 | with:
40 | node-version: 21.x
41 | cache: "pnpm"
42 |
43 | - name: Install dependencies
44 | run: pnpm i --frozen-lockfile
45 |
46 | - name: Run build
47 | run: pnpm build
48 | env:
49 | CI: false
50 |
51 | - name: Bump manifest version
52 | run: node .github/actions/bump-manifest-version.js
53 | env:
54 | TGT_RELEASE_VERSION: ${{ github.ref_name }}
55 |
56 | - name: Push manifest change
57 | uses: EndBug/add-and-commit@v8
58 | with:
59 | add: fxmanifest.lua
60 | push: true
61 | author_name: Manifest Bumper
62 | message: "chore: bump manifest version to ${{ github.ref_name }}"
63 |
64 | - name: Update tag ref
65 | uses: EndBug/latest-tag@latest
66 | with:
67 | ref: ${{ github.ref_name }}
68 |
69 | - name: Bundle files
70 | run: |
71 | mkdir -p ./temp/screencapture
72 | mkdir -p ./temp/screencapture/game
73 | mkdir -p ./temp/screencapture/game/nui
74 | cp ./{README.md,LICENSE,fxmanifest.lua} ./temp/screencapture
75 | cp -r ./game/dist ./temp/screencapture/game/dist
76 | cp -r ./game/nui/dist ./temp/screencapture/game/nui/dist
77 | cd ./temp && zip -r ../screencapture.zip ./screencapture
78 |
79 | - name: Create Release
80 | uses: "marvinpinto/action-automatic-releases@v1.2.1"
81 | id: auto_release
82 | with:
83 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
84 | title: "${{ env.RELEASE_VERSION }}"
85 | prerelease: false
86 | files: screencapture.zip
87 |
88 | env:
89 | CI: false
90 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .turbo
4 | .idea
5 | router-local.ts
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "jsxSingleQuote": false,
3 | "singleQuote": true,
4 | "useTabs": false,
5 | "semi": true,
6 | "tabWidth": 2,
7 | "printWidth": 120,
8 | "bracketSpacing": true
9 | }
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ScreenCapture
2 |
3 | ScreenCapture is a being built as a replacement for screenshot-basic in FiveM.
4 |
5 | ## Why build something new?
6 |
7 | I'll explain this later, but breifly - Screenshot-Basic is no longer maintained, has it's issues. It's a nightmare for almost everyone to get up and running for some reason (blame FXServer yarn) and it's not up-to-date with anything.
8 |
9 | ## How to use
10 |
11 | You can use the server-side exports, or the `screenshot-basic` backwards compatiable client-export: `requestScreenshotUpload`.
12 |
13 | ### JavaScript / TypeScript
14 |
15 | Converting Base64 to Blob/Buffer is easy enough with Node, but Lua ScRT in FiveM doesn't really offer that functionality, so if you wish to use the `serverCapture` export, you'll need to use Base64. More on that later.
16 |
17 | ### serverCapture (server-side export)
18 |
19 | | Parameter | Type | Description |
20 | | ---------- | ------------------------ | ------------------------------------------------------------------------- |
21 | | `source` | string | Player to capture |
22 | | `options` | object/table | Configuration options for the capture |
23 | | `callback` | function | A function invoked with the captured data |
24 | | `dataType` | string (default: base64) | What data should be returned through the callback: `'base64'` or `'blob'` |
25 |
26 | #### Options
27 |
28 | The `options` argument accepts an object with the following fields:
29 |
30 | | Field | Type | Default | Description |
31 | | ----------- | -------------- | -------- | ------------------------------------------------------------------------- |
32 | | `headers` | `object/table` | `null` | Optional HTTP headers to include in the capture request. |
33 | | `formField` | `string` | `null` | The form field name to be used when uploading the captured data. |
34 | | `filename` | `string` | `null` | Specifies the name of the file when saving or transmitting captured data. |
35 | | `encoding` | `string` | `'webp'` | Specifies the encoding format for the captured image (e.g., `'webp'`). |
36 |
37 | ```ts
38 | RegisterCommand(
39 | 'capture',
40 | (_: string, args: string[]) => {
41 | exp.screencapture.serverCapture(
42 | args[0],
43 | { encoding: 'webp' },
44 | (data: string | Buffer) => {
45 | data = Buffer.from(data as ArrayBuffer);
46 |
47 | fs.writeFileSync('./blob_image.webp', data);
48 | console.log(`File saved`);
49 | },
50 | 'blob',
51 | );
52 | },
53 | false,
54 | );
55 | ```
56 |
57 | ### remoteUpload (server-side export)
58 |
59 | | Parameter | Type | Description |
60 | | ---------- | ------------------------ | ------------------------------------------------------------------------ |
61 | | `source` | string | Player to capture |
62 | | `url` | string | The upload URL |
63 | | `options` | object/table | Configuration options for the capture |
64 | | `callback` | function | Callback returning the HTTP response in JSON |
65 | | `dataType` | string (default: base64) | What data type should be used to upload the file: `'base64'` or `'blob'` |
66 |
67 | #### Options
68 |
69 | The `options` argument accepts an object with the following fields:
70 |
71 | | Field | Type | Default | Description |
72 | | ----------- | -------------- | -------- | ------------------------------------------------------------------------- |
73 | | `headers` | `object/table` | `null` | Optional HTTP headers to include in the capture request. |
74 | | `formField` | `string` | `null` | The form field name to be used when uploading the captured data. |
75 | | `filename` | `string` | `null` | Specifies the name of the file when saving or transmitting captured data. |
76 | | `encoding` | `string` | `'webp'` | Specifies the encoding format for the captured image (e.g., `'webp'`). |
77 |
78 | ```ts
79 | RegisterCommand(
80 | 'remoteCapture',
81 | (_: string, args: string[]) => {
82 | exp.screencapture.remoteUpload(
83 | args[0],
84 | 'https://api.fivemanage.com/api/image',
85 | {
86 | encoding: 'webp',
87 | headers: {
88 | Authorization: '',
89 | },
90 | },
91 | (data: any) => {
92 | console.log(data);
93 | },
94 | 'blob',
95 | );
96 | },
97 | false,
98 | );
99 | ```
100 |
101 | ## Lua example with `remoteUpload`
102 |
103 | ```lua
104 | exports.screencapture:remoteUpload(args[1], "https://api.fivemanage.com/api/image", {
105 | encoding = "webp",
106 | headers = {
107 | ["Authorization"] = ""
108 | }
109 | }, function(data)
110 | print(data.url)
111 | end, "blob")
112 | ```
113 |
114 | ## Screenshot Basic compatibility
115 |
116 | ### This is NOT recommend to use, as you risk expsoing tokens to clients.
117 |
118 | ### requestScreenshotUpload (client-side export)
119 |
120 | ```lua
121 | exports['screencapture']:requestScreenshotUpload('https://api.fivemanage.com/api/image', 'file', {
122 | headers = {
123 | ["Authorization"] = API_TOKEN
124 | },
125 | encoding = "webp"
126 | }, function(data)
127 | local resp = json.decode(data)
128 | print(resp.url);
129 | TriggerEvent('chat:addMessage', { template = '
', args = { resp.url } })
130 | end)
131 | ```
132 |
133 | ## What will this include?
134 |
135 | 1. Server exports both for getting image data and uploading images/videos from the server
136 | 2. Client exports (maybe)
137 | 3. Upload images or videos from NUI, just more secure.
138 | 4. React, Svelt and Vue packages + publishing all internal packages like @screencapture/gameview (SoonTM)
139 |
--------------------------------------------------------------------------------
/fxmanifest.lua:
--------------------------------------------------------------------------------
1 | fx_version 'bodacious'
2 |
3 | version '0.3.2'
4 |
5 | game "gta5"
6 |
7 | client_script "game/dist/client.js"
8 | server_script "game/dist/server.js"
9 |
10 | ui_page "game/nui/dist/index.html"
11 | files {
12 | "game/nui/dist/index.html",
13 | "game/nui/dist/**/*",
14 | }
--------------------------------------------------------------------------------
/game/client/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { netEventController } from './event';
2 | import { CaptureRequest, RequestScreenshotUploadCB } from './types';
3 | import { uuidv4 } from './utils';
4 |
5 | const clientCaptureMap = new Map();
6 |
7 | onNet('screencapture:captureScreen', (token: string, options: object, dataType: string) => {
8 | SendNUIMessage({
9 | ...options,
10 | uploadToken: token,
11 | dataType,
12 | action: 'capture',
13 | serverEndpoint: `http://${GetCurrentServerEndpoint()}/${GetCurrentResourceName()}/image`,
14 | });
15 | });
16 |
17 | onNet('screencapture:INTERNAL_uploadComplete', (response: unknown, correlationId: string) => {
18 | const callback = clientCaptureMap.get(correlationId);
19 | if (callback) {
20 | callback(response);
21 | clientCaptureMap.delete(correlationId);
22 | }
23 | });
24 |
25 | global.exports(
26 | 'requestScreenshotUpload',
27 | async (
28 | url: string,
29 | formField: string,
30 | optionsOrCB: CaptureRequest | RequestScreenshotUploadCB,
31 | callback: RequestScreenshotUploadCB,
32 | ) => {
33 | // forgive me
34 | const isOptions = typeof optionsOrCB === 'object' && optionsOrCB !== null;
35 | const realOptions = isOptions
36 | ? (optionsOrCB as CaptureRequest)
37 | : ({ headers: {}, encoding: 'webp' } as CaptureRequest);
38 | const realCallback = isOptions
39 | ? (callback as RequestScreenshotUploadCB)
40 | : (optionsOrCB as RequestScreenshotUploadCB);
41 |
42 | const correlationId = uuidv4();
43 | clientCaptureMap.set(correlationId, realCallback);
44 |
45 | const token = await netEventController('screencapture:INTERNAL_requestUploadToken', {
46 | ...realOptions,
47 | formField,
48 | url,
49 | correlationId,
50 | });
51 |
52 | if (!token) {
53 | return console.error('Failed to get upload token');
54 | }
55 |
56 | return createImageCaptureMessage({
57 | ...realOptions,
58 | formField,
59 | url,
60 | uploadToken: token,
61 | dataType: 'blob',
62 | });
63 | },
64 | );
65 |
66 | function createImageCaptureMessage(options: CaptureRequest) {
67 | SendNUIMessage({
68 | ...options,
69 | action: 'capture',
70 | serverEndpoint: `http://${GetCurrentServerEndpoint()}/${GetCurrentResourceName()}/image`,
71 | });
72 | }
73 |
74 | /* onNet("screencapture:captureStream", (token: string, options: object) => {
75 | SendNUIMessage({
76 | ...options,
77 | uploadToken: token,
78 | action: 'capture-stream-start',
79 | serverEndpoint: `http://${GetCurrentServerEndpoint()}/${GetCurrentResourceName()}/stream`,
80 | });
81 | }) */
82 |
83 | /* onNet("screencapture:INTERNAL:stopCaptureStream", () => {
84 | SendNUIMessage({
85 | action: 'capture-stream-stop',
86 | })
87 | }) */
88 |
--------------------------------------------------------------------------------
/game/client/event.ts:
--------------------------------------------------------------------------------
1 | import { uuidv4 } from './utils';
2 |
3 | export function uniqueId() {
4 | return uuidv4();
5 | }
6 |
7 | export async function netEventController(event: string, ...args: any[]): Promise {
8 | return new Promise((resolve) => {
9 | const eventId = uniqueId();
10 | const listenName = `${event}:${eventId}`;
11 |
12 | emitNet(event, listenName, ...args);
13 |
14 | const eventListener = (data: TResponse) => {
15 | removeEventListener(listenName, eventListener);
16 | resolve(data);
17 | };
18 |
19 | onNet(listenName, eventListener);
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/game/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@screencapture/typescript-config/base.json",
3 | "compilerOptions": {
4 | "types": ["@types/node", "@citizenfx/client"],
5 | "moduleResolution": "node",
6 | "module": "CommonJS"
7 | },
8 | "include": ["**/*.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/game/client/types.ts:
--------------------------------------------------------------------------------
1 | export type RequestScreenshotUploadCB = (response: unknown) => void;
2 |
3 | type Encoding = 'webp' | 'jpg' | 'png';
4 |
5 | export type CaptureRequest = {
6 | action: 'capture';
7 | url: string;
8 | encoding: Encoding;
9 | quality: number;
10 | headers: Headers;
11 | uploadToken: string;
12 | serverEndpoint: string;
13 | filename: string;
14 | formField: string;
15 | dataType: 'blob' | 'base64';
16 | };
17 |
18 | export type RequestUploadToken = {
19 | url: string;
20 | encoding: Encoding;
21 | quality: number;
22 | headers: Headers;
23 | correlationId: string;
24 | };
25 |
--------------------------------------------------------------------------------
/game/client/utils.ts:
--------------------------------------------------------------------------------
1 | export const uuidv4 = (): string => {
2 | let uuid = '';
3 | for (let ii = 0; ii < 32; ii += 1) {
4 | switch (ii) {
5 | case 8:
6 | case 20:
7 | uuid += '-';
8 | uuid += ((Math.random() * 16) | 0).toString(16);
9 | break;
10 | case 12:
11 | uuid += '-';
12 | uuid += '4';
13 | break;
14 | case 16:
15 | uuid += '-';
16 | uuid += ((Math.random() * 4) | 8).toString(16);
17 | break;
18 | default:
19 | uuid += ((Math.random() * 16) | 0).toString(16);
20 | }
21 | }
22 | return uuid;
23 | };
--------------------------------------------------------------------------------
/game/nui/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/game/nui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ScreenCapture
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/game/nui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@screencapture/nui",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "typescript": "^5.5.3",
13 | "vite": "^5.4.1"
14 | },
15 | "dependencies": {
16 | "@screencapture/gameview": "workspace:*"
17 | }
18 | }
--------------------------------------------------------------------------------
/game/nui/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/game/nui/src/capture-stream.ts:
--------------------------------------------------------------------------------
1 | import { createGameView } from '@screencapture/gameview';
2 | import { CaptureStreamActions } from './types';
3 |
4 | type CaptureStreamRequest = {
5 | action: CaptureStreamActions;
6 | url: string;
7 | headers: Headers;
8 | uploadToken: string;
9 | serverEndpoint: string;
10 | formField: string;
11 | };
12 |
13 | export class CaptureStream {
14 | #gameView: any;
15 | #canvas: HTMLCanvasElement | null = null;
16 | #mediaStream: MediaStream | null = null;
17 | #recorder: MediaRecorder | null = null;
18 | #chunks: Blob[] = [];
19 |
20 | start() {
21 | window.addEventListener('message', (event) => {
22 | const data = event.data as CaptureStreamRequest;
23 |
24 | if (data.action === CaptureStreamActions.Start) {
25 | console.log('got message to start streaming');
26 | this.stream(data);
27 | }
28 |
29 | if (data.action === CaptureStreamActions.Stop) {
30 | this.stop();
31 | }
32 | });
33 |
34 | window.addEventListener('resize', () => {
35 | if (this.#gameView) {
36 | this.#gameView.resize(window.innerWidth, window.innerHeight);
37 | }
38 | });
39 | }
40 |
41 | stream(request: CaptureStreamRequest) {
42 | this.#canvas = document.createElement('canvas');
43 | this.#canvas.width = window.innerWidth;
44 | this.#canvas.height = window.innerHeight;
45 |
46 | this.#gameView = createGameView(this.#canvas);
47 |
48 | if (!this.#canvas) return console.error('Failed to find canvas');
49 |
50 | this.#mediaStream = this.#canvas.captureStream(30);
51 | this.#recorder = new MediaRecorder(this.#mediaStream, { mimeType: 'video/webm' });
52 |
53 | this.#recorder.ondataavailable = (ev) => {
54 | if (ev.data.size > 0) {
55 | console.log('data size', ev.data.size);
56 | this.#chunks.push(ev.data);
57 | // send chunk to http handler with corrID
58 | }
59 | };
60 |
61 | this.#recorder.onerror = (err) => {
62 | console.error('oops', err);
63 | };
64 |
65 | this.#recorder.onstop = async () => {
66 | console.log('rec stop');
67 | await this.uploadVideo(request);
68 | if (this.#canvas) return this.#canvas.remove();
69 | };
70 |
71 | this.#recorder.start(500);
72 | }
73 |
74 | stop() {
75 | if (this.#recorder && this.#recorder.state !== 'inactive') {
76 | this.#recorder.stop();
77 |
78 | if (this.#canvas) {
79 | this.#canvas?.remove();
80 | }
81 | }
82 | }
83 |
84 | async uploadVideo(request: CaptureStreamRequest) {
85 | console.log('chunk len', this.#chunks.length);
86 |
87 | const blob = new Blob(this.#chunks, { type: this.#recorder?.mimeType });
88 | console.log('blob size', blob.size);
89 |
90 | if (blob.size === 0) {
91 | console.error('Blob is empty, skipping upload');
92 | return;
93 | }
94 |
95 | const formData = new FormData();
96 | formData.append(request.formField || 'file', blob, 'capture.webm');
97 |
98 | console.log('request', request);
99 |
100 | try {
101 | // Fetch without setting 'Content-Type' manually
102 | const response = await fetch(request.serverEndpoint, {
103 | method: 'POST',
104 | headers: {
105 | 'X-ScreenCapture-Token': request.uploadToken, // Add custom headers
106 | },
107 | body: formData, // Browser handles Content-Type
108 | });
109 |
110 | if (!response.ok) {
111 | throw new Error(`Failed to upload video. Status: ${response.status}`);
112 | }
113 |
114 | console.log('Video uploaded successfully');
115 | } catch (err) {
116 | console.error('Error uploading video', err);
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/game/nui/src/capture.ts:
--------------------------------------------------------------------------------
1 | import { createGameView } from '@screencapture/gameview';
2 |
3 | type Encoding = 'webp' | 'jpg' | 'png';
4 |
5 | type CaptureRequest = {
6 | action: 'capture';
7 | url: string;
8 | encoding: Encoding;
9 | quality: number;
10 | headers: Headers;
11 | uploadToken: string;
12 | serverEndpoint: string;
13 | formField: string;
14 | dataType: 'blob' | 'base64';
15 | };
16 |
17 | export class Capture {
18 | #gameView: any;
19 | #canvas: HTMLCanvasElement | null = null;
20 |
21 | start() {
22 | window.addEventListener('message', async (event) => {
23 | const data = event.data as CaptureRequest;
24 |
25 | if (data.action === 'capture') {
26 | await this.captureScreen(data);
27 | }
28 | });
29 |
30 | window.addEventListener('resize', () => {
31 | if (this.#gameView) {
32 | this.#gameView.resize(window.innerWidth, window.innerHeight);
33 | }
34 | });
35 | }
36 |
37 | async captureScreen(request: CaptureRequest) {
38 | this.#canvas = document.createElement('canvas');
39 | this.#canvas.width = window.innerWidth;
40 | this.#canvas.height = window.innerHeight;
41 |
42 | this.#gameView = createGameView(this.#canvas);
43 |
44 | const enc = request.encoding ?? 'png';
45 | const qlty = request.quality ?? 0.5;
46 | let imageData: string | Blob;
47 | if (request.serverEndpoint || !request.formField) {
48 | // make sure we don't care about serverEndpoint, only the dataType
49 | imageData = await this.createBlob(this.#canvas, enc, qlty);
50 | } else {
51 | imageData = await this.createBlob(this.#canvas, enc, qlty);
52 | }
53 |
54 | if (!imageData) return console.error('No image available');
55 |
56 | await this.httpUploadImage(request, imageData);
57 | this.#canvas.remove();
58 | }
59 |
60 | async httpUploadImage(request: CaptureRequest, imageData: string | Blob) {
61 | const reqBody = this.createRequestBody(request, imageData);
62 |
63 | if (request.serverEndpoint) {
64 | try {
65 | await fetch(request.serverEndpoint, {
66 | method: 'POST',
67 | headers: {
68 | 'X-ScreenCapture-Token': request.uploadToken,
69 | },
70 | body: reqBody,
71 | });
72 | } catch (err) {
73 | console.error(err);
74 | }
75 | }
76 | }
77 |
78 | createRequestBody(request: CaptureRequest, imageData: string | Blob): BodyInit {
79 | if (imageData instanceof Blob) {
80 | const formData = new FormData();
81 | formData.append(request.formField ?? 'file', imageData);
82 |
83 | return formData;
84 | }
85 |
86 | // dataType is just here in order to know what to do with the data when we get it back
87 | return JSON.stringify({ imageData: imageData, dataType: request.dataType });
88 | }
89 |
90 | createDataURL(canvas: HTMLCanvasElement): Promise {
91 | return new Promise((resolve, reject) => {
92 | const url = canvas.toDataURL('image/webp', 0.7);
93 | if (!url) {
94 | reject('No data URL available');
95 | }
96 |
97 | resolve(url);
98 | });
99 | }
100 |
101 | createBlob(canvas: HTMLCanvasElement, enc: Encoding, quality = 0.7): Promise {
102 | return new Promise((resolve, reject) => {
103 | canvas.toBlob(
104 | (blob) => {
105 | if (blob) {
106 | resolve(blob);
107 | } else {
108 | reject('No blob available');
109 | }
110 | },
111 | `image/${enc}`,
112 | quality,
113 | );
114 | });
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/game/nui/src/main.ts:
--------------------------------------------------------------------------------
1 | import { Capture } from "./capture";
2 | import "./style.css";
3 |
4 | const capture = new Capture();
5 | capture.start();
6 |
7 | /* const stream = new CaptureStream();
8 | stream.start(); */
--------------------------------------------------------------------------------
/game/nui/src/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | background: transparent;
3 | background-color: transparent;
4 | }
5 |
6 | body {
7 | margin: 0; /* Remove default margin */
8 | overflow: hidden; /* Prevent scrollbars */
9 | }
--------------------------------------------------------------------------------
/game/nui/src/types.ts:
--------------------------------------------------------------------------------
1 | export enum CaptureStreamActions {
2 | Start = "capture-stream-start",
3 | Stop = "capture-stream-stop"
4 | }
--------------------------------------------------------------------------------
/game/nui/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/game/nui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 |
16 | /* Linting */
17 | "strict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "noFallthroughCasesInSwitch": true
21 | },
22 | "include": ["src"]
23 | }
24 |
--------------------------------------------------------------------------------
/game/nui/vite.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('vite').UserConfig} */
2 | export default {
3 | base: "./",
4 | };
5 |
--------------------------------------------------------------------------------
/game/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@screencapture/game",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "node scripts/esbuild.config.js",
9 | "build:client": "esbuild client/client.ts --bundle --platform=neutral --outfile=dist/client.js",
10 | "build:server": "esbuild server/server.ts --bundle --platform=node --outfile=dist/server.js"
11 | },
12 | "dependencies": {
13 | "@citizenfx/http-wrapper": "^0.2.2",
14 | "@koa/router": "^13.1.0",
15 | "form-data": "^4.0.1",
16 | "koa": "^2.15.4",
17 | "koa-body": "^6.0.1",
18 | "koa-router": "^13.0.1",
19 | "multer": "1.4.5-lts.1",
20 | "nanoid": "^5.0.8",
21 | "node-fetch": "^3.3.2"
22 | },
23 | "devDependencies": {
24 | "@citizenfx/client": "2.0.10822-1",
25 | "@citizenfx/server": "2.0.7290-1",
26 | "@screencapture/typescript-config": "workspace:*",
27 | "@types/formidable": "^3.4.5",
28 | "@types/koa": "^2.15.0",
29 | "@types/koa-router": "^7.4.8",
30 | "@types/koa__router": "^12.0.4",
31 | "@types/multer": "^1.4.12",
32 | "@types/node": "^22.8.6",
33 | "colorette": "^2.0.20",
34 | "esbuild": "^0.24.0",
35 | "rcon": "^1.1.0",
36 | "tsup": "^8.3.0"
37 | },
38 | "keywords": [],
39 | "author": "",
40 | "license": "MIT"
41 | }
--------------------------------------------------------------------------------
/game/scripts/esbuild.config.js:
--------------------------------------------------------------------------------
1 | const { context } = require("esbuild");
2 | const nodePaths = require("./node-paths");
3 |
4 |
5 | const isWatchEnabled = process.argv.findIndex((arg) => arg === '--watch') !== -1;
6 |
7 | const shouldRestart = process.argv.findIndex((arg) => arg === '--restart') !== -1;
8 |
9 | const buildConfig = {
10 | server: {
11 | platform: 'node',
12 | target: ['node21'],
13 | format: 'cjs'
14 | },
15 | client: {
16 | platform: 'browser',
17 | target: ['es2021'],
18 | format: 'iife',
19 | },
20 | };
21 |
22 | async function build() {
23 | for (const [targetProject, projectConfig] of Object.entries(buildConfig)) {
24 | const ctx = await context({
25 | bundle: true,
26 | entryPoints: [`${targetProject}/bootstrap.ts`],
27 | outfile: `dist/${targetProject}.js`,
28 | minify: targetProject === 'client',
29 | plugins: [nodePaths],
30 | ...projectConfig,
31 | });
32 |
33 | if (isWatchEnabled) {
34 | await ctx.watch();
35 | } else {
36 | await ctx.rebuild();
37 | await ctx.dispose();
38 | }
39 | }
40 | }
41 |
42 | build();
43 |
--------------------------------------------------------------------------------
/game/scripts/handle-build.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const {
4 | blueBright,
5 | cyanBright,
6 | greenBright,
7 | red,
8 | yellowBright,
9 | } = require("colorette");
10 | const RCon = require("rcon");
11 |
12 | let isAuthing = false;
13 | const rcon = new RCon("127.0.0.1", 30120, "dev", {
14 | tcp: false,
15 | challenge: false,
16 | });
17 |
18 | function log(level, log, domain, logData) {
19 | console.log(
20 | `[${yellowBright(
21 | new Date().toLocaleString().replace(",", "")
22 | )}] [${cyanBright(domain.toUpperCase())}] [${
23 | level === "INFO" ? blueBright("INFO") : red("ERROR")
24 | }] - ${log}`,
25 | logData ?? ""
26 | );
27 | }
28 |
29 | function handleYarnLock() {
30 | const resourcePath = path.resolve(__dirname, "../");
31 | const packageJson = path.resolve(resourcePath, "package.json");
32 | const yarnLock = path.resolve(resourcePath, ".yarn.installed");
33 |
34 | if (!fs.existsSync(packageJson)) {
35 | log(
36 | "ERROR",
37 | "Root directory is missing a package.json file. How is this possible?",
38 | "node"
39 | );
40 | return;
41 | }
42 |
43 | if (!fs.existsSync(yarnLock)) {
44 | log(
45 | "INFO",
46 | "Root directory is missing a .yarn.installed file. Creating it now...",
47 | "node"
48 | );
49 | fs.closeSync(fs.openSync(yarnLock, "w"));
50 | return;
51 | }
52 |
53 | const packageStat = fs.statSync(packageJson);
54 | const yarnStat = fs.statSync(yarnLock);
55 |
56 | if (packageStat.mtimeMs > yarnStat.mtimeMs) {
57 | log(
58 | "INFO",
59 | "Root directory package.json change detected. Overwriting the .yarn.installed file now...",
60 | "node"
61 | );
62 | fs.closeSync(fs.openSync(yarnLock, "w"));
63 | return;
64 | }
65 | }
66 |
67 | function debounce(func, delay) {
68 | let timeoutId;
69 |
70 | return (...args) => {
71 | clearTimeout(timeoutId);
72 |
73 | timeoutId = setTimeout(() => {
74 | timeoutId = null;
75 | func(...args);
76 | }, delay);
77 | };
78 | }
79 |
80 | const restartResource = debounce(async () => {
81 | log("INFO", "Attempting to restart resource", "node");
82 | rcon.send("ensure sdk");
83 | }, 500);
84 |
85 | /**
86 | * @type {import('esbuild').Plugin}
87 | */
88 | function handleBuild(domain, shouldRestart) {
89 | return {
90 | name: "handle-build",
91 | setup(build) {
92 | if (shouldRestart && !isAuthing) {
93 | isAuthing = true;
94 | rcon.connect();
95 | }
96 |
97 | let buildCount = 0;
98 | let buildStart = 0;
99 |
100 | build.onStart(() => {
101 | buildStart = performance.now();
102 | });
103 |
104 | build.onEnd((res) => {
105 | const firstBuild = buildCount++ === 0;
106 |
107 | if (res.errors.length > 0) {
108 | log(
109 | "ERROR",
110 | "An error occurred during the build process.",
111 | domain,
112 | res.errors
113 | );
114 | return;
115 | }
116 |
117 | log(
118 | "INFO",
119 | `Build completed ${
120 | res.warnings.length > 0
121 | ? yellowBright("with warnings")
122 | : greenBright("successfully")
123 | } in ${(performance.now() - buildStart).toFixed(0)}ms`,
124 | domain,
125 | res.warnings.length > 0 ? res.warnings : undefined
126 | );
127 |
128 | handleYarnLock();
129 |
130 | if (!firstBuild && shouldRestart) {
131 | restartResource();
132 | }
133 | });
134 | },
135 | };
136 | }
137 |
138 | module.exports = handleBuild;
--------------------------------------------------------------------------------
/game/scripts/node-paths.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | /**
4 | * @type {import('esbuild').Plugin}
5 | */
6 | module.exports = {
7 | name: "node-paths",
8 | setup(build) {
9 | build.onLoad({ filter: /\.(js|ts)$/ }, async (args) => {
10 | const source = await require("fs/promises").readFile(args.path, "utf8");
11 |
12 | const dirname = `const __dirname = ${JSON.stringify(
13 | path.dirname(args.path)
14 | )};`;
15 |
16 | const filename = `const __filename = ${JSON.stringify(args.path)};`;
17 |
18 | return {
19 | contents: `${dirname}\n${filename}\n${source}`,
20 | loader: args.path.endsWith(".ts") ? "ts" : "js",
21 | };
22 | });
23 | },
24 | };
--------------------------------------------------------------------------------
/game/server/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { createServer } from './koa-router';
2 | import './export';
3 | import { eventController } from './event';
4 | import { RequestUploadToken } from './types';
5 | import { UploadStore } from './upload-store';
6 |
7 | export const uploadStore = new UploadStore();
8 |
9 | async function boot() {
10 | createServer(uploadStore);
11 | }
12 |
13 | boot();
14 |
15 | eventController(
16 | 'screencapture:INTERNAL_requestUploadToken',
17 | async ({ ctx, body, send }) => {
18 | function uploadCallback(
19 | response: unknown,
20 | playerSource: number | undefined,
21 | correlationId: string | undefined,
22 | ): void {
23 | emitNet('screencapture:INTERNAL_uploadComplete', playerSource, JSON.stringify(response), correlationId);
24 | }
25 |
26 | const token = uploadStore.addUpload({
27 | callback: uploadCallback,
28 | isRemote: true,
29 | remoteConfig: {
30 | filename: body ? body.filename : undefined,
31 | encoding: body.encoding,
32 | headers: body.headers,
33 | formField: 'file',
34 | },
35 | url: body.url,
36 | dataType: 'blob',
37 | playerSource: ctx.source,
38 | correlationId: body.correlationId,
39 | });
40 |
41 | return send(token);
42 | },
43 | );
44 |
--------------------------------------------------------------------------------
/game/server/context.ts:
--------------------------------------------------------------------------------
1 | export type Context = {
2 | source: number;
3 | };
4 |
5 | export function getEventContext(): Context {
6 | const _source = global.source;
7 | return {
8 | source: _source,
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/game/server/event.ts:
--------------------------------------------------------------------------------
1 | import { type Context, getEventContext } from './context';
2 |
3 | type Event = {
4 | body: T;
5 | ctx: Context;
6 | send: (data: R) => void;
7 | };
8 |
9 | export function eventController(
10 | event: string,
11 | callback: (req: Event) => Promise,
12 | ): void {
13 | onNet(event, async (responseEvent: string, data: TData) => {
14 | const ctx = getEventContext();
15 |
16 | function send(data: TResponse): void {
17 | return emitNet(responseEvent, ctx.source, data);
18 | }
19 |
20 | // TODO: Add status codes or something to the response
21 | await callback({
22 | body: data,
23 | ctx: ctx,
24 | send,
25 | });
26 | //return emitNet(responseEvent, ctx.source, response);
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/game/server/export.ts:
--------------------------------------------------------------------------------
1 | import { uploadStore } from './bootstrap';
2 | import { CallbackFn, CaptureOptions, DataType } from './types';
3 |
4 | /* global.exports("serverCaptureStream", (source: number) => {
5 | const token = router.addStream({
6 | callback: null,
7 | isRemote: false,
8 | remoteConfig: null,
9 | })
10 |
11 | emitNet("screencapture:captureStream", source, token, {})
12 | })
13 |
14 | // DO NOT USE
15 | global.exports("INTERNAL_stopServerCaptureStream", (source: number) => {
16 | emitNet("screencapture:INTERNAL:stopCaptureStream", source)
17 | }) */
18 |
19 | // upload the file from the server and return the raw response
20 | global.exports(
21 | 'remoteUpload',
22 | (source: number, url: string, options: CaptureOptions, callback: CallbackFn, dataType: DataType = 'base64') => {
23 | if (!source) return console.error('source is required for serverCapture');
24 |
25 | const token = uploadStore.addUpload({
26 | callback: callback,
27 | isRemote: true,
28 | remoteConfig: {
29 | ...options,
30 | encoding: options.encoding ?? 'webp',
31 | },
32 | url,
33 | dataType,
34 | });
35 |
36 | emitNet('screencapture:captureScreen', source, token, options, dataType);
37 | },
38 | );
39 |
40 | // dataType here doesn't matter for NUI, its just for the server to know how to handle the data
41 | // when calling this export, the client will always send it back as base64
42 | global.exports(
43 | 'serverCapture',
44 | (source: number, options: CaptureOptions, callback: CallbackFn, dataType: DataType = 'base64') => {
45 | if (!source) return console.error('source is required for serverCapture');
46 |
47 | const token = uploadStore.addUpload({
48 | callback,
49 | isRemote: false,
50 | remoteConfig: null,
51 | dataType,
52 | });
53 |
54 | const opts = {
55 | ...options,
56 | encoding: options.encoding ?? 'webp',
57 | };
58 |
59 | emitNet('screencapture:captureScreen', source, token, opts, dataType);
60 | },
61 | );
62 |
--------------------------------------------------------------------------------
/game/server/koa-router.ts:
--------------------------------------------------------------------------------
1 | import Koa from 'koa';
2 | import Router from '@koa/router';
3 | import { multer } from './multer'
4 |
5 | // @ts-ignore - no types
6 | import { setHttpCallback } from '@citizenfx/http-wrapper';
7 |
8 | import FormData from 'form-data';
9 | import fetch from 'node-fetch';
10 | import { Blob } from 'node:buffer';
11 | import { CaptureOptions, DataType } from './types';
12 | import { UploadStore } from './upload-store';
13 |
14 | export async function createServer(uploadStore: UploadStore) {
15 | const app = new Koa();
16 | const router = new Router();
17 | const upload = multer({
18 | storage: multer.memoryStorage()
19 | });
20 |
21 | router.post('/image', upload.single("file") as any, async (ctx) => {
22 | const token = ctx.request.headers['x-screencapture-token'] as string;
23 | if (!token) {
24 | ctx.status = 401;
25 | ctx.body = { status: 'error', message: 'No token provided' };
26 | return;
27 | }
28 |
29 | const { callback, dataType, isRemote, remoteConfig, url, playerSource, correlationId } =
30 | uploadStore.getUpload(token);
31 |
32 | const file = ctx.file;
33 | if (!file) {
34 | ctx.status = 400;
35 | ctx.body = { status: 'error', message: 'No file provided' };
36 | return;
37 | }
38 |
39 | try {
40 |
41 | const buf = await buffer(dataType, file.buffer);
42 |
43 | if (isRemote) {
44 | const response = await uploadFile(url, remoteConfig, buf, dataType);
45 |
46 | // this is only when we return data back to the client
47 | if (playerSource && correlationId) {
48 | callback(response, playerSource, correlationId);
49 | } else {
50 | callback(response);
51 | }
52 | } else {
53 | callback(buf);
54 | }
55 |
56 | ctx.status = 200;
57 | ctx.body = { status: 'success' };
58 | } catch (err) {
59 | if (err instanceof Error) {
60 | ctx.status = 500;
61 | ctx.body = { status: 'error', message: err.message };
62 | } else {
63 | ctx.status = 500;
64 | ctx.body = { status: 'error', message: 'An unknown error occurred' };
65 | }
66 | }
67 | });
68 |
69 | app.use(router.routes()).use(router.allowedMethods());
70 |
71 | setHttpCallback(app.callback());
72 | }
73 |
74 | async function uploadFile(
75 | url: string | undefined,
76 | config: CaptureOptions | null,
77 | buf: string | Buffer,
78 | dataType: DataType,
79 | ) {
80 | if (!url) throw new Error('No remote URL provided');
81 | if (!config) throw new Error('No remote config provided');
82 |
83 | try {
84 | const body = await createRequestBody(buf, dataType, config);
85 |
86 | let response;
87 | if (body instanceof FormData) {
88 | response = await fetch(url, {
89 | method: 'POST',
90 | headers: {
91 | ...body.getHeaders(),
92 | ...config.headers,
93 | },
94 | body: body.getBuffer(),
95 | });
96 | } else {
97 | response = await fetch(url, {
98 | method: 'POST',
99 | headers: config.headers || {},
100 | // as soon as we get a node upgrade, we'll use Node's http module
101 | // we might be able to do it now, but if so I'll test that later
102 | body: body as any,
103 | });
104 | }
105 |
106 | if (!response.ok) {
107 | const text = await response.text();
108 | throw new Error(`Failed to upload file to ${url}. Status: ${response.status}. Response: ${text}`);
109 | }
110 |
111 | const res = await response.json();
112 | return res;
113 | } catch (err) {
114 | if (err instanceof Error) {
115 | throw new Error(err.message);
116 | }
117 | }
118 | }
119 |
120 | function createRequestBody(
121 | buf: string | Buffer,
122 | dataType: DataType,
123 | config: CaptureOptions,
124 | ): Promise {
125 | return new Promise((resolve, reject) => {
126 | const { formField, filename } = config;
127 |
128 | const filenameExt = filename ? `${filename}.${config.encoding}` : `screenshot.${config.encoding}`;
129 |
130 | if (dataType === 'blob') {
131 | const formData = new FormData();
132 | formData.append(formField || 'file', buf, filenameExt);
133 | if (filename) {
134 | formData.append('filename', filename);
135 | }
136 |
137 | return resolve(formData);
138 | }
139 |
140 | if (typeof buf === 'string' && dataType === 'base64') {
141 | return resolve(buf);
142 | }
143 |
144 | return reject('Invalid body data');
145 | });
146 | }
147 |
148 | async function buffer(dataType: DataType, imageData: Buffer): Promise {
149 | return new Promise(async (resolve, reject) => {
150 | if (dataType === 'base64') {
151 | const blob = new Blob([imageData]);
152 | const dateURL = await blobToBase64(blob);
153 | resolve(dateURL);
154 | } else {
155 | resolve(imageData);
156 | }
157 | });
158 | }
159 |
160 | async function blobToBase64(blob: Blob): Promise {
161 | return new Promise(async (resolve, reject) => {
162 | try {
163 | const arrayBuffer = await blob.arrayBuffer();
164 | const base64 = Buffer.from(arrayBuffer).toString('base64');
165 | resolve(base64);
166 | } catch (err) {
167 | reject(err);
168 | }
169 | });
170 | }
171 |
--------------------------------------------------------------------------------
/game/server/multer.ts:
--------------------------------------------------------------------------------
1 | import originalMulter, { Options, Multer } from 'multer';
2 |
3 | export function multer(options: Options): Multer {
4 | const m = originalMulter(options);
5 |
6 | makePromise(m, 'any');
7 | makePromise(m, 'array');
8 | makePromise(m, 'fields');
9 | makePromise(m, 'none');
10 | makePromise(m, 'single');
11 |
12 | return m;
13 | }
14 |
15 | function makePromise(multer: any, name: any): any {
16 | if (!multer[name]) return;
17 |
18 | const fn = multer[name];
19 |
20 | multer[name] = function () {
21 | const middleware = Reflect.apply(fn, this, arguments);
22 |
23 | return async (ctx: any, next: any) => {
24 | await new Promise((resolve, reject) => {
25 | middleware(ctx.req, ctx.res, (err: any) => {
26 | if (err) return reject(err);
27 | if ('request' in ctx) {
28 | if (ctx.req.body) {
29 | ctx.request.body = ctx.req.body;
30 | delete ctx.req.body;
31 | }
32 |
33 | if (ctx.req.file) {
34 | ctx.request.file = ctx.req.file;
35 | ctx.file = ctx.req.file;
36 | delete ctx.req.file;
37 | }
38 |
39 | if (ctx.req.files) {
40 | ctx.request.files = ctx.req.files;
41 | ctx.files = ctx.req.files;
42 | delete ctx.req.files;
43 | }
44 | }
45 |
46 | resolve(ctx);
47 | });
48 | });
49 |
50 | return next();
51 | };
52 | };
53 | }
54 |
55 | multer.diskStorage = originalMulter.diskStorage;
56 | multer.memoryStorage = originalMulter.memoryStorage;
--------------------------------------------------------------------------------
/game/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@screencapture/typescript-config/base.json",
3 | "compilerOptions": {
4 | "types": ["@types/node", "@citizenfx/server"],
5 | "moduleResolution": "node",
6 | "module": "CommonJS"
7 | },
8 | "include": ["**/*.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/game/server/types.ts:
--------------------------------------------------------------------------------
1 | export type DataType = 'base64' | 'blob';
2 |
3 | type Encoding = 'webp' | 'jpg' | 'png';
4 |
5 | export interface UploadData {
6 | callback: CallbackFn;
7 | isRemote: boolean;
8 | remoteConfig: CaptureOptions | null;
9 | dataType: DataType;
10 | url?: string;
11 | playerSource?: number;
12 | correlationId?: string;
13 | }
14 |
15 | export interface StreamUploadData {
16 | callback: CallbackFn | null
17 | isRemote: boolean;
18 | remoteConfig: CaptureOptions | null;
19 | url?: string;
20 | }
21 |
22 | export interface RemoteConfig {
23 | url: string;
24 | headers?: HeadersInit;
25 | formField?: string;
26 | filename?: string;
27 | encoding?: string;
28 | }
29 |
30 | export interface CaptureOptions {
31 | headers?: HeadersInit;
32 | formField?: string;
33 | filename?: string;
34 | encoding?: string;
35 | }
36 |
37 | export type CallbackFn = (data: unknown, _playerSource?: number, correlationId?: string) => void;
38 |
39 | export interface CallbackData {
40 | imageData: string | Buffer;
41 | dataType: string;
42 | }
43 |
44 | export interface RequestBody {
45 | imageData: string;
46 | dataType: DataType;
47 | }
48 |
49 | export type RequestUploadToken = {
50 | url: string;
51 | encoding: Encoding;
52 | quality: number;
53 | headers: Headers;
54 | correlationId: string;
55 | filename: string;
56 | };
57 |
--------------------------------------------------------------------------------
/game/server/upload-store.ts:
--------------------------------------------------------------------------------
1 | import { nanoid } from 'nanoid';
2 | import { UploadData } from './types';
3 |
4 | export class UploadStore {
5 | #uploadMap: Map;
6 | //#streamUploadMap: Map;
7 |
8 | constructor() {
9 | this.#uploadMap = new Map();
10 | //this.#streamUploadMap = new Map();
11 | }
12 |
13 | addUpload(params: UploadData): string {
14 | const uploadToken = nanoid(24);
15 |
16 | this.#uploadMap.set(uploadToken, params);
17 |
18 | return uploadToken;
19 | }
20 |
21 | getUpload(uploadToken: string): UploadData {
22 | const exists = this.#uploadMap.has(uploadToken);
23 | if (!exists) {
24 | throw new Error('Upload data does not exist. Cancelling screen capture.');
25 | }
26 |
27 | const data = this.#uploadMap.get(uploadToken);
28 | if (!data) throw new Error('Could not find upload data');
29 |
30 | return data;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "screencapture",
3 | "version": "0.0.0",
4 | "description": "",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "build:gameview": "pnpm --filter @screencapture/gameview build",
8 | "build:game": "pnpm --filter @screencapture/game build",
9 | "build:nui": "pnpm --filter @screencapture/nui build",
10 | "build": "pnpm turbo build"
11 | },
12 | "keywords": [],
13 | "author": "itschip",
14 | "license": "MIT",
15 | "devDependencies": {
16 | "prettier": "^3.3.3",
17 | "turbo": "^2.1.2",
18 | "typescript": "^5.5.3"
19 | },
20 | "packageManager": "pnpm@9.11.0"
21 | }
--------------------------------------------------------------------------------
/packages/gameview/index.ts:
--------------------------------------------------------------------------------
1 | export { createGameView } from './webgl';
--------------------------------------------------------------------------------
/packages/gameview/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@screencapture/gameview",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "module": "dist/index.mjs",
7 | "types": "dist/index.d.ts",
8 | "scripts": {
9 | "test": "echo \"Error: no test specified\" && exit 1",
10 | "build": "tsup index.ts --format esm,cjs --minify --dts"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "tsup": "^8.3.0",
17 | "@screencapture/typescript-config": "workspace:*"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/gameview/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@screencapture/typescript-config/base.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["**/*.ts"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/gameview/webgl.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/citizenfx/fivem/blob/538f9cc8310391417fd025febae6d1efb9558bc5/ext/cfx-ui/src/app/app.component.ts#L317
2 | const vertexShaderSrc = `
3 | attribute vec2 a_position;
4 | attribute vec2 a_texcoord;
5 | uniform mat3 u_matrix;
6 | varying vec2 textureCoordinate;
7 | void main() {
8 | gl_Position = vec4(a_position, 0.0, 1.0);
9 | textureCoordinate = a_texcoord;
10 | }
11 | `;
12 |
13 | const fragmentShaderSrc = `
14 | varying highp vec2 textureCoordinate;
15 | uniform sampler2D external_texture;
16 | void main()
17 | {
18 | gl_FragColor = texture2D(external_texture, textureCoordinate);
19 | }
20 | `;
21 |
22 | function makeShader(gl: WebGLRenderingContext, type: number, src: string) {
23 | const shader = gl.createShader(type);
24 | if (!shader) {
25 | throw new Error('Failed to create shader');
26 | }
27 |
28 | gl.shaderSource(shader, src);
29 | gl.compileShader(shader);
30 |
31 | const infoLog = gl.getShaderInfoLog(shader);
32 | if (infoLog) {
33 | console.error(infoLog);
34 | }
35 |
36 | return shader;
37 | }
38 |
39 | function createTexture(gl: WebGLRenderingContext) {
40 | const tex = gl.createTexture();
41 |
42 | const texPixels = new Uint8Array([0, 0, 255, 255]);
43 |
44 | gl.bindTexture(gl.TEXTURE_2D, tex);
45 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, texPixels);
46 |
47 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
48 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
49 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
50 |
51 | // Magic hook sequence
52 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
53 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
54 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
55 |
56 | // Reset
57 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
58 |
59 | return tex;
60 | }
61 |
62 | function createBuffers(gl: WebGLRenderingContext) {
63 | const vertexBuff = gl.createBuffer();
64 | gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuff);
65 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
66 | -1, -1,
67 | 1, -1,
68 | -1, 1,
69 | 1, 1,
70 | ]), gl.STATIC_DRAW);
71 |
72 | const texBuff = gl.createBuffer();
73 | gl.bindBuffer(gl.ARRAY_BUFFER, texBuff);
74 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
75 | 0, 0,
76 | 1, 0,
77 | 0, 1,
78 | 1, 1,
79 | ]), gl.STATIC_DRAW);
80 |
81 | return { vertexBuff, texBuff };
82 | }
83 |
84 | function createProgram(gl: WebGLRenderingContext) {
85 | const vertexShader = makeShader(gl, gl.VERTEX_SHADER, vertexShaderSrc);
86 | const fragmentShader = makeShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSrc);
87 |
88 | const program = gl.createProgram();
89 | if (!program) {
90 | throw new Error('Failed to create program');
91 | }
92 |
93 | gl.attachShader(program, vertexShader);
94 | gl.attachShader(program, fragmentShader);
95 | gl.linkProgram(program);
96 | gl.useProgram(program);
97 |
98 | const vloc = gl.getAttribLocation(program, 'a_position');
99 | const tloc = gl.getAttribLocation(program, 'a_texcoord');
100 |
101 | return { program, vloc, tloc };
102 | }
103 |
104 | export function createGameView(canvas: HTMLCanvasElement) {
105 | const gl = canvas.getContext('webgl', {
106 | antialias: false,
107 | depth: false,
108 | stencil: false,
109 | alpha: false,
110 | desynchronized: true,
111 | failIfMajorPerformanceCaveat: false
112 | }) as WebGLRenderingContext;
113 |
114 | let render = () => { };
115 |
116 | function createStuff() {
117 | const tex = createTexture(gl);
118 | const { program, vloc, tloc } = createProgram(gl);
119 | const { vertexBuff, texBuff } = createBuffers(gl);
120 |
121 | gl.useProgram(program);
122 |
123 | gl.bindTexture(gl.TEXTURE_2D, tex);
124 |
125 | gl.uniform1i(gl.getUniformLocation(program, 'external_texture'), 0);
126 |
127 | gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuff);
128 | gl.vertexAttribPointer(vloc, 2, gl.FLOAT, false, 0, 0);
129 | gl.enableVertexAttribArray(vloc);
130 |
131 | gl.bindBuffer(gl.ARRAY_BUFFER, texBuff);
132 | gl.vertexAttribPointer(tloc, 2, gl.FLOAT, false, 0, 0);
133 | gl.enableVertexAttribArray(tloc);
134 |
135 | gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
136 |
137 | render();
138 | }
139 |
140 | const gameView = {
141 | canvas,
142 | gl,
143 | animationFrame: void 0,
144 | resize: (width: number, height: number) => {
145 | gl.viewport(0, 0, width, height);
146 | gl.canvas.width = width;
147 | gl.canvas.height = height;
148 | },
149 | };
150 |
151 | render = () => {
152 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
153 | gl.finish();
154 |
155 | // @ts-ignore
156 | gameView.animationFrame = requestAnimationFrame(render);
157 | };
158 |
159 | createStuff();
160 |
161 | return gameView;
162 | }
163 |
--------------------------------------------------------------------------------
/packages/react/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itschip/screencapture/091b63b59705af61bd6c09d667639af8796f14a2/packages/react/index.ts
--------------------------------------------------------------------------------
/packages/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@screencapture/react",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": ["react", "fivem", "screenshot-basic", "screenshot", "webgl"],
10 | "author": "",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "tsup": "^8.3.0",
14 | "@screencapture/typescript-config": "workspace:*",
15 | "@screencapture/gameview": "workspace:*"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@screencapture/typescript-config/react.json",
3 | "compilerOptions": {
4 | "outDir": "dist",
5 | "jsx": "react-jsx"
6 | },
7 | "include": ["**/*.ts", "**/*.tsx"],
8 | "exclude": ["node_modules", "dist"]
9 | }
10 |
--------------------------------------------------------------------------------
/packages/react/useCaptureScreen.ts:
--------------------------------------------------------------------------------
1 | import { createGameView } from '@screencapture/gameview';
2 | import { createBlob } from './utils';
3 |
4 | export const useCaptureScreen = () => {
5 | const capture = async (canvas: HTMLCanvasElement) => {
6 | let localCanvas = false;
7 | if (!canvas) {
8 | localCanvas = true;
9 | canvas = document.createElement('canvas');
10 | canvas.width = window.innerWidth;
11 | canvas.height = window.innerHeight;
12 | }
13 |
14 | const gameView = createGameView(canvas);
15 |
16 | // TODO: Use innerWidth and innerHeight from the game view unless the user has specified a custom size
17 | gameView.resize(window.innerWidth, window.innerHeight);
18 |
19 | // TODO: Option to choose between base64 and blob
20 | // TODO: Option for quality and encoding type
21 | const blob = await createBlob(canvas);
22 |
23 | if (!blob) {
24 | console.error('No blob available');
25 | return;
26 | }
27 |
28 | if (localCanvas) {
29 | canvas.remove();
30 | }
31 |
32 | return blob;
33 | };
34 |
35 | return { capture };
36 | };
--------------------------------------------------------------------------------
/packages/react/utils.ts:
--------------------------------------------------------------------------------
1 | export async function createBlob(canvas: HTMLCanvasElement): Promise {
2 | return new Promise((resolve, reject) => {
3 | canvas.toBlob(
4 | (blob) => {
5 | if (blob) {
6 | resolve(blob);
7 | } else {
8 | reject("No blob available");
9 | }
10 | },
11 | "image/webp",
12 | 0.5
13 | );
14 | });
15 | }
--------------------------------------------------------------------------------
/packages/typescript-config/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "declaration": true,
6 | "declarationMap": true,
7 | "esModuleInterop": true,
8 | "incremental": false,
9 | "isolatedModules": true,
10 | "lib": ["es2022", "DOM", "DOM.Iterable"],
11 | "module": "NodeNext",
12 | "moduleDetection": "force",
13 | "moduleResolution": "NodeNext",
14 | "noUncheckedIndexedAccess": true,
15 | "resolveJsonModule": true,
16 | "skipLibCheck": true,
17 | "strict": true,
18 | "target": "ES2022"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/typescript-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@screencapture/typescript-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "publishConfig": {
6 | "access": "public"
7 | },
8 | "author": "itschip",
9 | "license": "MIT"
10 | }
--------------------------------------------------------------------------------
/packages/typescript-config/react.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "React Library",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "jsx": "react-jsx"
7 | }
8 | }
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | devDependencies:
11 | prettier:
12 | specifier: ^3.3.3
13 | version: 3.3.3
14 | turbo:
15 | specifier: ^2.1.2
16 | version: 2.1.2
17 | typescript:
18 | specifier: ^5.5.3
19 | version: 5.6.2
20 |
21 | game:
22 | dependencies:
23 | '@citizenfx/http-wrapper':
24 | specifier: ^0.2.2
25 | version: 0.2.2
26 | '@koa/router':
27 | specifier: ^13.1.0
28 | version: 13.1.0
29 | form-data:
30 | specifier: ^4.0.1
31 | version: 4.0.1
32 | koa:
33 | specifier: ^2.15.4
34 | version: 2.15.4
35 | koa-body:
36 | specifier: ^6.0.1
37 | version: 6.0.1
38 | koa-router:
39 | specifier: ^13.0.1
40 | version: 13.0.1
41 | multer:
42 | specifier: 1.4.5-lts.1
43 | version: 1.4.5-lts.1
44 | nanoid:
45 | specifier: ^5.0.8
46 | version: 5.0.8
47 | node-fetch:
48 | specifier: ^3.3.2
49 | version: 3.3.2
50 | devDependencies:
51 | '@citizenfx/client':
52 | specifier: 2.0.10822-1
53 | version: 2.0.10822-1
54 | '@citizenfx/server':
55 | specifier: 2.0.7290-1
56 | version: 2.0.7290-1
57 | '@screencapture/typescript-config':
58 | specifier: workspace:*
59 | version: link:../packages/typescript-config
60 | '@types/formidable':
61 | specifier: ^3.4.5
62 | version: 3.4.5
63 | '@types/koa':
64 | specifier: ^2.15.0
65 | version: 2.15.0
66 | '@types/koa-router':
67 | specifier: ^7.4.8
68 | version: 7.4.8
69 | '@types/koa__router':
70 | specifier: ^12.0.4
71 | version: 12.0.4
72 | '@types/multer':
73 | specifier: ^1.4.12
74 | version: 1.4.12
75 | '@types/node':
76 | specifier: ^22.8.6
77 | version: 22.8.6
78 | colorette:
79 | specifier: ^2.0.20
80 | version: 2.0.20
81 | esbuild:
82 | specifier: ^0.24.0
83 | version: 0.24.0
84 | rcon:
85 | specifier: ^1.1.0
86 | version: 1.1.0
87 | tsup:
88 | specifier: ^8.3.0
89 | version: 8.3.0(postcss@8.4.47)(typescript@5.6.2)
90 |
91 | game/nui:
92 | dependencies:
93 | '@screencapture/gameview':
94 | specifier: workspace:*
95 | version: link:../../packages/gameview
96 | devDependencies:
97 | typescript:
98 | specifier: ^5.5.3
99 | version: 5.6.2
100 | vite:
101 | specifier: ^5.4.1
102 | version: 5.4.6(@types/node@22.8.6)
103 |
104 | packages/gameview:
105 | devDependencies:
106 | '@screencapture/typescript-config':
107 | specifier: workspace:*
108 | version: link:../typescript-config
109 | tsup:
110 | specifier: ^8.3.0
111 | version: 8.3.0(postcss@8.4.47)(typescript@5.6.2)
112 |
113 | packages/react:
114 | devDependencies:
115 | '@screencapture/gameview':
116 | specifier: workspace:*
117 | version: link:../gameview
118 | '@screencapture/typescript-config':
119 | specifier: workspace:*
120 | version: link:../typescript-config
121 | tsup:
122 | specifier: ^8.3.0
123 | version: 8.3.0(postcss@8.4.47)(typescript@5.6.2)
124 |
125 | packages/typescript-config: {}
126 |
127 | packages:
128 |
129 | '@citizenfx/client@2.0.10822-1':
130 | resolution: {integrity: sha512-9z8qf000oOsPw1lEn+KA2yxANGifcEn841YogOpQ2tjuwMRNy3jqqbIRg0kgnF3kTqNm2y45m+qM5i0CmHOCWw==}
131 |
132 | '@citizenfx/http-wrapper@0.2.2':
133 | resolution: {integrity: sha512-hFyrWN2U30KFRgYteyqs7PZ+9aXyiH3tsgOQL/vcOp9dGAZAyRSHDotJYZivTEpjRN4dMbgbZ2h9TgoDFRKi9w==}
134 |
135 | '@citizenfx/server@2.0.7290-1':
136 | resolution: {integrity: sha512-ZWuREJ7APkrUh2XOuREdVrZBPH7VNvOdz4DWlj1NVslwNi0atCk9cxiRtQ5yJpBTY9mZDQ5XwNeelQBlW64Yjg==}
137 |
138 | '@esbuild/aix-ppc64@0.21.5':
139 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
140 | engines: {node: '>=12'}
141 | cpu: [ppc64]
142 | os: [aix]
143 |
144 | '@esbuild/aix-ppc64@0.23.1':
145 | resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
146 | engines: {node: '>=18'}
147 | cpu: [ppc64]
148 | os: [aix]
149 |
150 | '@esbuild/aix-ppc64@0.24.0':
151 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
152 | engines: {node: '>=18'}
153 | cpu: [ppc64]
154 | os: [aix]
155 |
156 | '@esbuild/android-arm64@0.21.5':
157 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
158 | engines: {node: '>=12'}
159 | cpu: [arm64]
160 | os: [android]
161 |
162 | '@esbuild/android-arm64@0.23.1':
163 | resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
164 | engines: {node: '>=18'}
165 | cpu: [arm64]
166 | os: [android]
167 |
168 | '@esbuild/android-arm64@0.24.0':
169 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
170 | engines: {node: '>=18'}
171 | cpu: [arm64]
172 | os: [android]
173 |
174 | '@esbuild/android-arm@0.21.5':
175 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
176 | engines: {node: '>=12'}
177 | cpu: [arm]
178 | os: [android]
179 |
180 | '@esbuild/android-arm@0.23.1':
181 | resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
182 | engines: {node: '>=18'}
183 | cpu: [arm]
184 | os: [android]
185 |
186 | '@esbuild/android-arm@0.24.0':
187 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
188 | engines: {node: '>=18'}
189 | cpu: [arm]
190 | os: [android]
191 |
192 | '@esbuild/android-x64@0.21.5':
193 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
194 | engines: {node: '>=12'}
195 | cpu: [x64]
196 | os: [android]
197 |
198 | '@esbuild/android-x64@0.23.1':
199 | resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
200 | engines: {node: '>=18'}
201 | cpu: [x64]
202 | os: [android]
203 |
204 | '@esbuild/android-x64@0.24.0':
205 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
206 | engines: {node: '>=18'}
207 | cpu: [x64]
208 | os: [android]
209 |
210 | '@esbuild/darwin-arm64@0.21.5':
211 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
212 | engines: {node: '>=12'}
213 | cpu: [arm64]
214 | os: [darwin]
215 |
216 | '@esbuild/darwin-arm64@0.23.1':
217 | resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
218 | engines: {node: '>=18'}
219 | cpu: [arm64]
220 | os: [darwin]
221 |
222 | '@esbuild/darwin-arm64@0.24.0':
223 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
224 | engines: {node: '>=18'}
225 | cpu: [arm64]
226 | os: [darwin]
227 |
228 | '@esbuild/darwin-x64@0.21.5':
229 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
230 | engines: {node: '>=12'}
231 | cpu: [x64]
232 | os: [darwin]
233 |
234 | '@esbuild/darwin-x64@0.23.1':
235 | resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
236 | engines: {node: '>=18'}
237 | cpu: [x64]
238 | os: [darwin]
239 |
240 | '@esbuild/darwin-x64@0.24.0':
241 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
242 | engines: {node: '>=18'}
243 | cpu: [x64]
244 | os: [darwin]
245 |
246 | '@esbuild/freebsd-arm64@0.21.5':
247 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
248 | engines: {node: '>=12'}
249 | cpu: [arm64]
250 | os: [freebsd]
251 |
252 | '@esbuild/freebsd-arm64@0.23.1':
253 | resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
254 | engines: {node: '>=18'}
255 | cpu: [arm64]
256 | os: [freebsd]
257 |
258 | '@esbuild/freebsd-arm64@0.24.0':
259 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
260 | engines: {node: '>=18'}
261 | cpu: [arm64]
262 | os: [freebsd]
263 |
264 | '@esbuild/freebsd-x64@0.21.5':
265 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
266 | engines: {node: '>=12'}
267 | cpu: [x64]
268 | os: [freebsd]
269 |
270 | '@esbuild/freebsd-x64@0.23.1':
271 | resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
272 | engines: {node: '>=18'}
273 | cpu: [x64]
274 | os: [freebsd]
275 |
276 | '@esbuild/freebsd-x64@0.24.0':
277 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
278 | engines: {node: '>=18'}
279 | cpu: [x64]
280 | os: [freebsd]
281 |
282 | '@esbuild/linux-arm64@0.21.5':
283 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
284 | engines: {node: '>=12'}
285 | cpu: [arm64]
286 | os: [linux]
287 |
288 | '@esbuild/linux-arm64@0.23.1':
289 | resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
290 | engines: {node: '>=18'}
291 | cpu: [arm64]
292 | os: [linux]
293 |
294 | '@esbuild/linux-arm64@0.24.0':
295 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
296 | engines: {node: '>=18'}
297 | cpu: [arm64]
298 | os: [linux]
299 |
300 | '@esbuild/linux-arm@0.21.5':
301 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
302 | engines: {node: '>=12'}
303 | cpu: [arm]
304 | os: [linux]
305 |
306 | '@esbuild/linux-arm@0.23.1':
307 | resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
308 | engines: {node: '>=18'}
309 | cpu: [arm]
310 | os: [linux]
311 |
312 | '@esbuild/linux-arm@0.24.0':
313 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
314 | engines: {node: '>=18'}
315 | cpu: [arm]
316 | os: [linux]
317 |
318 | '@esbuild/linux-ia32@0.21.5':
319 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
320 | engines: {node: '>=12'}
321 | cpu: [ia32]
322 | os: [linux]
323 |
324 | '@esbuild/linux-ia32@0.23.1':
325 | resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
326 | engines: {node: '>=18'}
327 | cpu: [ia32]
328 | os: [linux]
329 |
330 | '@esbuild/linux-ia32@0.24.0':
331 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
332 | engines: {node: '>=18'}
333 | cpu: [ia32]
334 | os: [linux]
335 |
336 | '@esbuild/linux-loong64@0.21.5':
337 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
338 | engines: {node: '>=12'}
339 | cpu: [loong64]
340 | os: [linux]
341 |
342 | '@esbuild/linux-loong64@0.23.1':
343 | resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
344 | engines: {node: '>=18'}
345 | cpu: [loong64]
346 | os: [linux]
347 |
348 | '@esbuild/linux-loong64@0.24.0':
349 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
350 | engines: {node: '>=18'}
351 | cpu: [loong64]
352 | os: [linux]
353 |
354 | '@esbuild/linux-mips64el@0.21.5':
355 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
356 | engines: {node: '>=12'}
357 | cpu: [mips64el]
358 | os: [linux]
359 |
360 | '@esbuild/linux-mips64el@0.23.1':
361 | resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
362 | engines: {node: '>=18'}
363 | cpu: [mips64el]
364 | os: [linux]
365 |
366 | '@esbuild/linux-mips64el@0.24.0':
367 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
368 | engines: {node: '>=18'}
369 | cpu: [mips64el]
370 | os: [linux]
371 |
372 | '@esbuild/linux-ppc64@0.21.5':
373 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
374 | engines: {node: '>=12'}
375 | cpu: [ppc64]
376 | os: [linux]
377 |
378 | '@esbuild/linux-ppc64@0.23.1':
379 | resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
380 | engines: {node: '>=18'}
381 | cpu: [ppc64]
382 | os: [linux]
383 |
384 | '@esbuild/linux-ppc64@0.24.0':
385 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
386 | engines: {node: '>=18'}
387 | cpu: [ppc64]
388 | os: [linux]
389 |
390 | '@esbuild/linux-riscv64@0.21.5':
391 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
392 | engines: {node: '>=12'}
393 | cpu: [riscv64]
394 | os: [linux]
395 |
396 | '@esbuild/linux-riscv64@0.23.1':
397 | resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
398 | engines: {node: '>=18'}
399 | cpu: [riscv64]
400 | os: [linux]
401 |
402 | '@esbuild/linux-riscv64@0.24.0':
403 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
404 | engines: {node: '>=18'}
405 | cpu: [riscv64]
406 | os: [linux]
407 |
408 | '@esbuild/linux-s390x@0.21.5':
409 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
410 | engines: {node: '>=12'}
411 | cpu: [s390x]
412 | os: [linux]
413 |
414 | '@esbuild/linux-s390x@0.23.1':
415 | resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
416 | engines: {node: '>=18'}
417 | cpu: [s390x]
418 | os: [linux]
419 |
420 | '@esbuild/linux-s390x@0.24.0':
421 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
422 | engines: {node: '>=18'}
423 | cpu: [s390x]
424 | os: [linux]
425 |
426 | '@esbuild/linux-x64@0.21.5':
427 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
428 | engines: {node: '>=12'}
429 | cpu: [x64]
430 | os: [linux]
431 |
432 | '@esbuild/linux-x64@0.23.1':
433 | resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
434 | engines: {node: '>=18'}
435 | cpu: [x64]
436 | os: [linux]
437 |
438 | '@esbuild/linux-x64@0.24.0':
439 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
440 | engines: {node: '>=18'}
441 | cpu: [x64]
442 | os: [linux]
443 |
444 | '@esbuild/netbsd-x64@0.21.5':
445 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
446 | engines: {node: '>=12'}
447 | cpu: [x64]
448 | os: [netbsd]
449 |
450 | '@esbuild/netbsd-x64@0.23.1':
451 | resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
452 | engines: {node: '>=18'}
453 | cpu: [x64]
454 | os: [netbsd]
455 |
456 | '@esbuild/netbsd-x64@0.24.0':
457 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
458 | engines: {node: '>=18'}
459 | cpu: [x64]
460 | os: [netbsd]
461 |
462 | '@esbuild/openbsd-arm64@0.23.1':
463 | resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
464 | engines: {node: '>=18'}
465 | cpu: [arm64]
466 | os: [openbsd]
467 |
468 | '@esbuild/openbsd-arm64@0.24.0':
469 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
470 | engines: {node: '>=18'}
471 | cpu: [arm64]
472 | os: [openbsd]
473 |
474 | '@esbuild/openbsd-x64@0.21.5':
475 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
476 | engines: {node: '>=12'}
477 | cpu: [x64]
478 | os: [openbsd]
479 |
480 | '@esbuild/openbsd-x64@0.23.1':
481 | resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
482 | engines: {node: '>=18'}
483 | cpu: [x64]
484 | os: [openbsd]
485 |
486 | '@esbuild/openbsd-x64@0.24.0':
487 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
488 | engines: {node: '>=18'}
489 | cpu: [x64]
490 | os: [openbsd]
491 |
492 | '@esbuild/sunos-x64@0.21.5':
493 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
494 | engines: {node: '>=12'}
495 | cpu: [x64]
496 | os: [sunos]
497 |
498 | '@esbuild/sunos-x64@0.23.1':
499 | resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
500 | engines: {node: '>=18'}
501 | cpu: [x64]
502 | os: [sunos]
503 |
504 | '@esbuild/sunos-x64@0.24.0':
505 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
506 | engines: {node: '>=18'}
507 | cpu: [x64]
508 | os: [sunos]
509 |
510 | '@esbuild/win32-arm64@0.21.5':
511 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
512 | engines: {node: '>=12'}
513 | cpu: [arm64]
514 | os: [win32]
515 |
516 | '@esbuild/win32-arm64@0.23.1':
517 | resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
518 | engines: {node: '>=18'}
519 | cpu: [arm64]
520 | os: [win32]
521 |
522 | '@esbuild/win32-arm64@0.24.0':
523 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
524 | engines: {node: '>=18'}
525 | cpu: [arm64]
526 | os: [win32]
527 |
528 | '@esbuild/win32-ia32@0.21.5':
529 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
530 | engines: {node: '>=12'}
531 | cpu: [ia32]
532 | os: [win32]
533 |
534 | '@esbuild/win32-ia32@0.23.1':
535 | resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
536 | engines: {node: '>=18'}
537 | cpu: [ia32]
538 | os: [win32]
539 |
540 | '@esbuild/win32-ia32@0.24.0':
541 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
542 | engines: {node: '>=18'}
543 | cpu: [ia32]
544 | os: [win32]
545 |
546 | '@esbuild/win32-x64@0.21.5':
547 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
548 | engines: {node: '>=12'}
549 | cpu: [x64]
550 | os: [win32]
551 |
552 | '@esbuild/win32-x64@0.23.1':
553 | resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
554 | engines: {node: '>=18'}
555 | cpu: [x64]
556 | os: [win32]
557 |
558 | '@esbuild/win32-x64@0.24.0':
559 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
560 | engines: {node: '>=18'}
561 | cpu: [x64]
562 | os: [win32]
563 |
564 | '@hapi/bourne@3.0.0':
565 | resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
566 |
567 | '@isaacs/cliui@8.0.2':
568 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
569 | engines: {node: '>=12'}
570 |
571 | '@jridgewell/gen-mapping@0.3.5':
572 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
573 | engines: {node: '>=6.0.0'}
574 |
575 | '@jridgewell/resolve-uri@3.1.2':
576 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
577 | engines: {node: '>=6.0.0'}
578 |
579 | '@jridgewell/set-array@1.2.1':
580 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
581 | engines: {node: '>=6.0.0'}
582 |
583 | '@jridgewell/sourcemap-codec@1.5.0':
584 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
585 |
586 | '@jridgewell/trace-mapping@0.3.25':
587 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
588 |
589 | '@koa/router@13.1.0':
590 | resolution: {integrity: sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw==}
591 | engines: {node: '>= 18'}
592 |
593 | '@pkgjs/parseargs@0.11.0':
594 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
595 | engines: {node: '>=14'}
596 |
597 | '@rollup/rollup-android-arm-eabi@4.22.0':
598 | resolution: {integrity: sha512-/IZQvg6ZR0tAkEi4tdXOraQoWeJy9gbQ/cx4I7k9dJaCk9qrXEcdouxRVz5kZXt5C2bQ9pILoAA+KB4C/d3pfw==}
599 | cpu: [arm]
600 | os: [android]
601 |
602 | '@rollup/rollup-android-arm64@4.22.0':
603 | resolution: {integrity: sha512-ETHi4bxrYnvOtXeM7d4V4kZWixib2jddFacJjsOjwbgYSRsyXYtZHC4ht134OsslPIcnkqT+TKV4eU8rNBKyyQ==}
604 | cpu: [arm64]
605 | os: [android]
606 |
607 | '@rollup/rollup-darwin-arm64@4.22.0':
608 | resolution: {integrity: sha512-ZWgARzhSKE+gVUX7QWaECoRQsPwaD8ZR0Oxb3aUpzdErTvlEadfQpORPXkKSdKbFci9v8MJfkTtoEHnnW9Ulng==}
609 | cpu: [arm64]
610 | os: [darwin]
611 |
612 | '@rollup/rollup-darwin-x64@4.22.0':
613 | resolution: {integrity: sha512-h0ZAtOfHyio8Az6cwIGS+nHUfRMWBDO5jXB8PQCARVF6Na/G6XS2SFxDl8Oem+S5ZsHQgtsI7RT4JQnI1qrlaw==}
614 | cpu: [x64]
615 | os: [darwin]
616 |
617 | '@rollup/rollup-linux-arm-gnueabihf@4.22.0':
618 | resolution: {integrity: sha512-9pxQJSPwFsVi0ttOmqLY4JJ9pg9t1gKhK0JDbV1yUEETSx55fdyCjt39eBQ54OQCzAF0nVGO6LfEH1KnCPvelA==}
619 | cpu: [arm]
620 | os: [linux]
621 |
622 | '@rollup/rollup-linux-arm-musleabihf@4.22.0':
623 | resolution: {integrity: sha512-YJ5Ku5BmNJZb58A4qSEo3JlIG4d3G2lWyBi13ABlXzO41SsdnUKi3HQHe83VpwBVG4jHFTW65jOQb8qyoR+qzg==}
624 | cpu: [arm]
625 | os: [linux]
626 |
627 | '@rollup/rollup-linux-arm64-gnu@4.22.0':
628 | resolution: {integrity: sha512-U4G4u7f+QCqHlVg1Nlx+qapZy+QoG+NV6ux+upo/T7arNGwKvKP2kmGM4W5QTbdewWFgudQxi3kDNST9GT1/mg==}
629 | cpu: [arm64]
630 | os: [linux]
631 |
632 | '@rollup/rollup-linux-arm64-musl@4.22.0':
633 | resolution: {integrity: sha512-aQpNlKmx3amwkA3a5J6nlXSahE1ijl0L9KuIjVOUhfOh7uw2S4piR3mtpxpRtbnK809SBtyPsM9q15CPTsY7HQ==}
634 | cpu: [arm64]
635 | os: [linux]
636 |
637 | '@rollup/rollup-linux-powerpc64le-gnu@4.22.0':
638 | resolution: {integrity: sha512-9fx6Zj/7vve/Fp4iexUFRKb5+RjLCff6YTRQl4CoDhdMfDoobWmhAxQWV3NfShMzQk1Q/iCnageFyGfqnsmeqQ==}
639 | cpu: [ppc64]
640 | os: [linux]
641 |
642 | '@rollup/rollup-linux-riscv64-gnu@4.22.0':
643 | resolution: {integrity: sha512-VWQiCcN7zBgZYLjndIEh5tamtnKg5TGxyZPWcN9zBtXBwfcGSZ5cHSdQZfQH/GB4uRxk0D3VYbOEe/chJhPGLQ==}
644 | cpu: [riscv64]
645 | os: [linux]
646 |
647 | '@rollup/rollup-linux-s390x-gnu@4.22.0':
648 | resolution: {integrity: sha512-EHmPnPWvyYqncObwqrosb/CpH3GOjE76vWVs0g4hWsDRUVhg61hBmlVg5TPXqF+g+PvIbqkC7i3h8wbn4Gp2Fg==}
649 | cpu: [s390x]
650 | os: [linux]
651 |
652 | '@rollup/rollup-linux-x64-gnu@4.22.0':
653 | resolution: {integrity: sha512-tsSWy3YQzmpjDKnQ1Vcpy3p9Z+kMFbSIesCdMNgLizDWFhrLZIoN21JSq01g+MZMDFF+Y1+4zxgrlqPjid5ohg==}
654 | cpu: [x64]
655 | os: [linux]
656 |
657 | '@rollup/rollup-linux-x64-musl@4.22.0':
658 | resolution: {integrity: sha512-anr1Y11uPOQrpuU8XOikY5lH4Qu94oS6j0xrulHk3NkLDq19MlX8Ng/pVipjxBJ9a2l3+F39REZYyWQFkZ4/fw==}
659 | cpu: [x64]
660 | os: [linux]
661 |
662 | '@rollup/rollup-win32-arm64-msvc@4.22.0':
663 | resolution: {integrity: sha512-7LB+Bh+Ut7cfmO0m244/asvtIGQr5pG5Rvjz/l1Rnz1kDzM02pSX9jPaS0p+90H5I1x4d1FkCew+B7MOnoatNw==}
664 | cpu: [arm64]
665 | os: [win32]
666 |
667 | '@rollup/rollup-win32-ia32-msvc@4.22.0':
668 | resolution: {integrity: sha512-+3qZ4rer7t/QsC5JwMpcvCVPRcJt1cJrYS/TMJZzXIJbxWFQEVhrIc26IhB+5Z9fT9umfVc+Es2mOZgl+7jdJQ==}
669 | cpu: [ia32]
670 | os: [win32]
671 |
672 | '@rollup/rollup-win32-x64-msvc@4.22.0':
673 | resolution: {integrity: sha512-YdicNOSJONVx/vuPkgPTyRoAPx3GbknBZRCOUkK84FJ/YTfs/F0vl/YsMscrB6Y177d+yDRcj+JWMPMCgshwrA==}
674 | cpu: [x64]
675 | os: [win32]
676 |
677 | '@types/accepts@1.3.7':
678 | resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
679 |
680 | '@types/body-parser@1.19.5':
681 | resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
682 |
683 | '@types/co-body@6.1.3':
684 | resolution: {integrity: sha512-UhuhrQ5hclX6UJctv5m4Rfp52AfG9o9+d9/HwjxhVB5NjXxr5t9oKgJxN8xRHgr35oo8meUEHUPFWiKg6y71aA==}
685 |
686 | '@types/connect@3.4.38':
687 | resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
688 |
689 | '@types/content-disposition@0.5.8':
690 | resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==}
691 |
692 | '@types/cookies@0.9.0':
693 | resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==}
694 |
695 | '@types/estree@1.0.5':
696 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
697 |
698 | '@types/express-serve-static-core@5.0.6':
699 | resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==}
700 |
701 | '@types/express@5.0.0':
702 | resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==}
703 |
704 | '@types/formidable@2.0.6':
705 | resolution: {integrity: sha512-L4HcrA05IgQyNYJj6kItuIkXrInJvsXTPC5B1i64FggWKKqSL+4hgt7asiSNva75AoLQjq29oPxFfU4GAQ6Z2w==}
706 |
707 | '@types/formidable@3.4.5':
708 | resolution: {integrity: sha512-s7YPsNVfnsng5L8sKnG/Gbb2tiwwJTY1conOkJzTMRvJAlLFW1nEua+ADsJQu8N1c0oTHx9+d5nqg10WuT9gHQ==}
709 |
710 | '@types/http-assert@1.5.6':
711 | resolution: {integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==}
712 |
713 | '@types/http-errors@2.0.4':
714 | resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
715 |
716 | '@types/keygrip@1.0.6':
717 | resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==}
718 |
719 | '@types/koa-compose@3.2.8':
720 | resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==}
721 |
722 | '@types/koa-router@7.4.8':
723 | resolution: {integrity: sha512-SkWlv4F9f+l3WqYNQHnWjYnyTxYthqt8W9az2RTdQW7Ay8bc00iRZcrb8MC75iEfPqnGcg2csEl8tTG1NQPD4A==}
724 |
725 | '@types/koa@2.15.0':
726 | resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==}
727 |
728 | '@types/koa__router@12.0.4':
729 | resolution: {integrity: sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==}
730 |
731 | '@types/mime@1.3.5':
732 | resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
733 |
734 | '@types/multer@1.4.12':
735 | resolution: {integrity: sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==}
736 |
737 | '@types/node@22.8.6':
738 | resolution: {integrity: sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==}
739 |
740 | '@types/qs@6.9.18':
741 | resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==}
742 |
743 | '@types/range-parser@1.2.7':
744 | resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
745 |
746 | '@types/send@0.17.4':
747 | resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
748 |
749 | '@types/serve-static@1.15.7':
750 | resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
751 |
752 | accepts@1.3.8:
753 | resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
754 | engines: {node: '>= 0.6'}
755 |
756 | ansi-regex@5.0.1:
757 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
758 | engines: {node: '>=8'}
759 |
760 | ansi-regex@6.1.0:
761 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
762 | engines: {node: '>=12'}
763 |
764 | ansi-styles@4.3.0:
765 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
766 | engines: {node: '>=8'}
767 |
768 | ansi-styles@6.2.1:
769 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
770 | engines: {node: '>=12'}
771 |
772 | any-promise@1.3.0:
773 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
774 |
775 | anymatch@3.1.3:
776 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
777 | engines: {node: '>= 8'}
778 |
779 | append-field@1.0.0:
780 | resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==}
781 |
782 | asap@2.0.6:
783 | resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
784 |
785 | asynckit@0.4.0:
786 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
787 |
788 | balanced-match@1.0.2:
789 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
790 |
791 | binary-extensions@2.3.0:
792 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
793 | engines: {node: '>=8'}
794 |
795 | brace-expansion@2.0.1:
796 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
797 |
798 | braces@3.0.3:
799 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
800 | engines: {node: '>=8'}
801 |
802 | buffer-from@1.1.2:
803 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
804 |
805 | bundle-require@5.0.0:
806 | resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
807 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
808 | peerDependencies:
809 | esbuild: '>=0.18'
810 |
811 | busboy@1.6.0:
812 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
813 | engines: {node: '>=10.16.0'}
814 |
815 | bytes@3.1.2:
816 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
817 | engines: {node: '>= 0.8'}
818 |
819 | cac@6.7.14:
820 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
821 | engines: {node: '>=8'}
822 |
823 | cache-content-type@1.0.1:
824 | resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==}
825 | engines: {node: '>= 6.0.0'}
826 |
827 | call-bind-apply-helpers@1.0.2:
828 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
829 | engines: {node: '>= 0.4'}
830 |
831 | call-bound@1.0.3:
832 | resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
833 | engines: {node: '>= 0.4'}
834 |
835 | chokidar@3.6.0:
836 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
837 | engines: {node: '>= 8.10.0'}
838 |
839 | co-body@6.2.0:
840 | resolution: {integrity: sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA==}
841 | engines: {node: '>=8.0.0'}
842 |
843 | co@4.6.0:
844 | resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
845 | engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
846 |
847 | color-convert@2.0.1:
848 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
849 | engines: {node: '>=7.0.0'}
850 |
851 | color-name@1.1.4:
852 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
853 |
854 | colorette@2.0.20:
855 | resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
856 |
857 | combined-stream@1.0.8:
858 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
859 | engines: {node: '>= 0.8'}
860 |
861 | commander@4.1.1:
862 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
863 | engines: {node: '>= 6'}
864 |
865 | concat-stream@1.6.2:
866 | resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==}
867 | engines: {'0': node >= 0.8}
868 |
869 | consola@3.2.3:
870 | resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
871 | engines: {node: ^14.18.0 || >=16.10.0}
872 |
873 | content-disposition@0.5.4:
874 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
875 | engines: {node: '>= 0.6'}
876 |
877 | content-type@1.0.5:
878 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
879 | engines: {node: '>= 0.6'}
880 |
881 | cookies@0.9.1:
882 | resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==}
883 | engines: {node: '>= 0.8'}
884 |
885 | core-util-is@1.0.3:
886 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
887 |
888 | cross-spawn@7.0.3:
889 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
890 | engines: {node: '>= 8'}
891 |
892 | data-uri-to-buffer@4.0.1:
893 | resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
894 | engines: {node: '>= 12'}
895 |
896 | debug@4.3.7:
897 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
898 | engines: {node: '>=6.0'}
899 | peerDependencies:
900 | supports-color: '*'
901 | peerDependenciesMeta:
902 | supports-color:
903 | optional: true
904 |
905 | deep-equal@1.0.1:
906 | resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==}
907 |
908 | delayed-stream@1.0.0:
909 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
910 | engines: {node: '>=0.4.0'}
911 |
912 | delegates@1.0.0:
913 | resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
914 |
915 | depd@1.1.2:
916 | resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
917 | engines: {node: '>= 0.6'}
918 |
919 | depd@2.0.0:
920 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
921 | engines: {node: '>= 0.8'}
922 |
923 | destroy@1.2.0:
924 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
925 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
926 |
927 | dezalgo@1.0.4:
928 | resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==}
929 |
930 | dunder-proto@1.0.1:
931 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
932 | engines: {node: '>= 0.4'}
933 |
934 | eastasianwidth@0.2.0:
935 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
936 |
937 | ee-first@1.1.1:
938 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
939 |
940 | emoji-regex@8.0.0:
941 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
942 |
943 | emoji-regex@9.2.2:
944 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
945 |
946 | encodeurl@1.0.2:
947 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
948 | engines: {node: '>= 0.8'}
949 |
950 | es-define-property@1.0.1:
951 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
952 | engines: {node: '>= 0.4'}
953 |
954 | es-errors@1.3.0:
955 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
956 | engines: {node: '>= 0.4'}
957 |
958 | es-object-atoms@1.1.1:
959 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
960 | engines: {node: '>= 0.4'}
961 |
962 | esbuild@0.21.5:
963 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
964 | engines: {node: '>=12'}
965 | hasBin: true
966 |
967 | esbuild@0.23.1:
968 | resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
969 | engines: {node: '>=18'}
970 | hasBin: true
971 |
972 | esbuild@0.24.0:
973 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
974 | engines: {node: '>=18'}
975 | hasBin: true
976 |
977 | escape-html@1.0.3:
978 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
979 |
980 | execa@5.1.1:
981 | resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
982 | engines: {node: '>=10'}
983 |
984 | fdir@6.3.0:
985 | resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==}
986 | peerDependencies:
987 | picomatch: ^3 || ^4
988 | peerDependenciesMeta:
989 | picomatch:
990 | optional: true
991 |
992 | fetch-blob@3.2.0:
993 | resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
994 | engines: {node: ^12.20 || >= 14.13}
995 |
996 | fill-range@7.1.1:
997 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
998 | engines: {node: '>=8'}
999 |
1000 | foreground-child@3.3.0:
1001 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
1002 | engines: {node: '>=14'}
1003 |
1004 | form-data@4.0.1:
1005 | resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
1006 | engines: {node: '>= 6'}
1007 |
1008 | formdata-polyfill@4.0.10:
1009 | resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
1010 | engines: {node: '>=12.20.0'}
1011 |
1012 | formidable@2.1.2:
1013 | resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==}
1014 |
1015 | fresh@0.5.2:
1016 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
1017 | engines: {node: '>= 0.6'}
1018 |
1019 | fsevents@2.3.3:
1020 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
1021 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
1022 | os: [darwin]
1023 |
1024 | function-bind@1.1.2:
1025 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
1026 |
1027 | get-intrinsic@1.2.7:
1028 | resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
1029 | engines: {node: '>= 0.4'}
1030 |
1031 | get-proto@1.0.1:
1032 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
1033 | engines: {node: '>= 0.4'}
1034 |
1035 | get-stream@6.0.1:
1036 | resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
1037 | engines: {node: '>=10'}
1038 |
1039 | glob-parent@5.1.2:
1040 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
1041 | engines: {node: '>= 6'}
1042 |
1043 | glob@10.4.5:
1044 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
1045 | hasBin: true
1046 |
1047 | gopd@1.2.0:
1048 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
1049 | engines: {node: '>= 0.4'}
1050 |
1051 | has-symbols@1.1.0:
1052 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
1053 | engines: {node: '>= 0.4'}
1054 |
1055 | has-tostringtag@1.0.2:
1056 | resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
1057 | engines: {node: '>= 0.4'}
1058 |
1059 | hasown@2.0.2:
1060 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
1061 | engines: {node: '>= 0.4'}
1062 |
1063 | hexoid@1.0.0:
1064 | resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==}
1065 | engines: {node: '>=8'}
1066 |
1067 | http-assert@1.5.0:
1068 | resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==}
1069 | engines: {node: '>= 0.8'}
1070 |
1071 | http-errors@1.8.1:
1072 | resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==}
1073 | engines: {node: '>= 0.6'}
1074 |
1075 | http-errors@2.0.0:
1076 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
1077 | engines: {node: '>= 0.8'}
1078 |
1079 | human-signals@2.1.0:
1080 | resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
1081 | engines: {node: '>=10.17.0'}
1082 |
1083 | iconv-lite@0.4.24:
1084 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
1085 | engines: {node: '>=0.10.0'}
1086 |
1087 | inflation@2.1.0:
1088 | resolution: {integrity: sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==}
1089 | engines: {node: '>= 0.8.0'}
1090 |
1091 | inherits@2.0.4:
1092 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
1093 |
1094 | is-binary-path@2.1.0:
1095 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
1096 | engines: {node: '>=8'}
1097 |
1098 | is-extglob@2.1.1:
1099 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
1100 | engines: {node: '>=0.10.0'}
1101 |
1102 | is-fullwidth-code-point@3.0.0:
1103 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
1104 | engines: {node: '>=8'}
1105 |
1106 | is-generator-function@1.1.0:
1107 | resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
1108 | engines: {node: '>= 0.4'}
1109 |
1110 | is-glob@4.0.3:
1111 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
1112 | engines: {node: '>=0.10.0'}
1113 |
1114 | is-number@7.0.0:
1115 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
1116 | engines: {node: '>=0.12.0'}
1117 |
1118 | is-regex@1.2.1:
1119 | resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
1120 | engines: {node: '>= 0.4'}
1121 |
1122 | is-stream@2.0.1:
1123 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
1124 | engines: {node: '>=8'}
1125 |
1126 | isarray@1.0.0:
1127 | resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
1128 |
1129 | isexe@2.0.0:
1130 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
1131 |
1132 | jackspeak@3.4.3:
1133 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
1134 |
1135 | joycon@3.1.1:
1136 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
1137 | engines: {node: '>=10'}
1138 |
1139 | keygrip@1.1.0:
1140 | resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==}
1141 | engines: {node: '>= 0.6'}
1142 |
1143 | koa-body@6.0.1:
1144 | resolution: {integrity: sha512-M8ZvMD8r+kPHy28aWP9VxL7kY8oPWA+C7ZgCljrCMeaU7uX6wsIQgDHskyrAr9sw+jqnIXyv4Mlxri5R4InIJg==}
1145 |
1146 | koa-compose@4.1.0:
1147 | resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==}
1148 |
1149 | koa-convert@2.0.0:
1150 | resolution: {integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==}
1151 | engines: {node: '>= 10'}
1152 |
1153 | koa-router@13.0.1:
1154 | resolution: {integrity: sha512-4/sijXdSxocIe2wv7RFFSxvo2ic1pDzPSmy11yCGztng1hx408qfw1wVmN3aqhQaU7U6nJ039JKC8ObE73Ohgw==}
1155 | engines: {node: '>= 18'}
1156 |
1157 | koa@2.15.4:
1158 | resolution: {integrity: sha512-7fNBIdrU2PEgLljXoPWoyY4r1e+ToWCmzS/wwMPbUNs7X+5MMET1ObhJBlUkF5uZG9B6QhM2zS1TsH6adegkiQ==}
1159 | engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4}
1160 |
1161 | lilconfig@3.1.2:
1162 | resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
1163 | engines: {node: '>=14'}
1164 |
1165 | lines-and-columns@1.2.4:
1166 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
1167 |
1168 | load-tsconfig@0.2.5:
1169 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
1170 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1171 |
1172 | lodash.sortby@4.7.0:
1173 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
1174 |
1175 | lru-cache@10.4.3:
1176 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
1177 |
1178 | math-intrinsics@1.1.0:
1179 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
1180 | engines: {node: '>= 0.4'}
1181 |
1182 | media-typer@0.3.0:
1183 | resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
1184 | engines: {node: '>= 0.6'}
1185 |
1186 | merge-stream@2.0.0:
1187 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
1188 |
1189 | mime-db@1.52.0:
1190 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
1191 | engines: {node: '>= 0.6'}
1192 |
1193 | mime-types@2.1.35:
1194 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
1195 | engines: {node: '>= 0.6'}
1196 |
1197 | mimic-fn@2.1.0:
1198 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
1199 | engines: {node: '>=6'}
1200 |
1201 | minimatch@9.0.5:
1202 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
1203 | engines: {node: '>=16 || 14 >=14.17'}
1204 |
1205 | minimist@1.2.8:
1206 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
1207 |
1208 | minipass@7.1.2:
1209 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
1210 | engines: {node: '>=16 || 14 >=14.17'}
1211 |
1212 | mkdirp@0.5.6:
1213 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
1214 | hasBin: true
1215 |
1216 | ms@2.1.3:
1217 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1218 |
1219 | multer@1.4.5-lts.1:
1220 | resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==}
1221 | engines: {node: '>= 6.0.0'}
1222 |
1223 | mz@2.7.0:
1224 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
1225 |
1226 | nanoid@3.3.7:
1227 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
1228 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
1229 | hasBin: true
1230 |
1231 | nanoid@5.0.8:
1232 | resolution: {integrity: sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==}
1233 | engines: {node: ^18 || >=20}
1234 | hasBin: true
1235 |
1236 | negotiator@0.6.3:
1237 | resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
1238 | engines: {node: '>= 0.6'}
1239 |
1240 | node-domexception@1.0.0:
1241 | resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
1242 | engines: {node: '>=10.5.0'}
1243 |
1244 | node-fetch@3.3.2:
1245 | resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
1246 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1247 |
1248 | normalize-path@3.0.0:
1249 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
1250 | engines: {node: '>=0.10.0'}
1251 |
1252 | npm-run-path@4.0.1:
1253 | resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
1254 | engines: {node: '>=8'}
1255 |
1256 | object-assign@4.1.1:
1257 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
1258 | engines: {node: '>=0.10.0'}
1259 |
1260 | object-inspect@1.13.4:
1261 | resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
1262 | engines: {node: '>= 0.4'}
1263 |
1264 | on-finished@2.4.1:
1265 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
1266 | engines: {node: '>= 0.8'}
1267 |
1268 | once@1.4.0:
1269 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
1270 |
1271 | onetime@5.1.2:
1272 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
1273 | engines: {node: '>=6'}
1274 |
1275 | only@0.0.2:
1276 | resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==}
1277 |
1278 | package-json-from-dist@1.0.0:
1279 | resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==}
1280 |
1281 | parseurl@1.3.3:
1282 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
1283 | engines: {node: '>= 0.8'}
1284 |
1285 | path-key@3.1.1:
1286 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
1287 | engines: {node: '>=8'}
1288 |
1289 | path-scurry@1.11.1:
1290 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
1291 | engines: {node: '>=16 || 14 >=14.18'}
1292 |
1293 | path-to-regexp@6.3.0:
1294 | resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
1295 |
1296 | path-to-regexp@8.2.0:
1297 | resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
1298 | engines: {node: '>=16'}
1299 |
1300 | picocolors@1.1.0:
1301 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
1302 |
1303 | picomatch@2.3.1:
1304 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
1305 | engines: {node: '>=8.6'}
1306 |
1307 | picomatch@4.0.2:
1308 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
1309 | engines: {node: '>=12'}
1310 |
1311 | pirates@4.0.6:
1312 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
1313 | engines: {node: '>= 6'}
1314 |
1315 | postcss-load-config@6.0.1:
1316 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
1317 | engines: {node: '>= 18'}
1318 | peerDependencies:
1319 | jiti: '>=1.21.0'
1320 | postcss: '>=8.0.9'
1321 | tsx: ^4.8.1
1322 | yaml: ^2.4.2
1323 | peerDependenciesMeta:
1324 | jiti:
1325 | optional: true
1326 | postcss:
1327 | optional: true
1328 | tsx:
1329 | optional: true
1330 | yaml:
1331 | optional: true
1332 |
1333 | postcss@8.4.47:
1334 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
1335 | engines: {node: ^10 || ^12 || >=14}
1336 |
1337 | prettier@3.3.3:
1338 | resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
1339 | engines: {node: '>=14'}
1340 | hasBin: true
1341 |
1342 | process-nextick-args@2.0.1:
1343 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
1344 |
1345 | punycode@2.3.1:
1346 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1347 | engines: {node: '>=6'}
1348 |
1349 | qs@6.14.0:
1350 | resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
1351 | engines: {node: '>=0.6'}
1352 |
1353 | raw-body@2.5.2:
1354 | resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
1355 | engines: {node: '>= 0.8'}
1356 |
1357 | rcon@1.1.0:
1358 | resolution: {integrity: sha512-eotwcApOBjfadTjqQlrZVR4jzlwGCMNxmHhnFZx+g4kouwwRstRHkk1ON7DzkqrHNIjADSh0cU3gThSsDolUpg==}
1359 |
1360 | readable-stream@2.3.8:
1361 | resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
1362 |
1363 | readdirp@3.6.0:
1364 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
1365 | engines: {node: '>=8.10.0'}
1366 |
1367 | resolve-from@5.0.0:
1368 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
1369 | engines: {node: '>=8'}
1370 |
1371 | rollup@4.22.0:
1372 | resolution: {integrity: sha512-W21MUIFPZ4+O2Je/EU+GP3iz7PH4pVPUXSbEZdatQnxo29+3rsUjgrJmzuAZU24z7yRAnFN6ukxeAhZh/c7hzg==}
1373 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
1374 | hasBin: true
1375 |
1376 | safe-buffer@5.1.2:
1377 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
1378 |
1379 | safe-buffer@5.2.1:
1380 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
1381 |
1382 | safe-regex-test@1.1.0:
1383 | resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
1384 | engines: {node: '>= 0.4'}
1385 |
1386 | safer-buffer@2.1.2:
1387 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
1388 |
1389 | setprototypeof@1.2.0:
1390 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
1391 |
1392 | shebang-command@2.0.0:
1393 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
1394 | engines: {node: '>=8'}
1395 |
1396 | shebang-regex@3.0.0:
1397 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
1398 | engines: {node: '>=8'}
1399 |
1400 | side-channel-list@1.0.0:
1401 | resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
1402 | engines: {node: '>= 0.4'}
1403 |
1404 | side-channel-map@1.0.1:
1405 | resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
1406 | engines: {node: '>= 0.4'}
1407 |
1408 | side-channel-weakmap@1.0.2:
1409 | resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
1410 | engines: {node: '>= 0.4'}
1411 |
1412 | side-channel@1.1.0:
1413 | resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
1414 | engines: {node: '>= 0.4'}
1415 |
1416 | signal-exit@3.0.7:
1417 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
1418 |
1419 | signal-exit@4.1.0:
1420 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
1421 | engines: {node: '>=14'}
1422 |
1423 | source-map-js@1.2.1:
1424 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
1425 | engines: {node: '>=0.10.0'}
1426 |
1427 | source-map@0.8.0-beta.0:
1428 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
1429 | engines: {node: '>= 8'}
1430 |
1431 | statuses@1.5.0:
1432 | resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
1433 | engines: {node: '>= 0.6'}
1434 |
1435 | statuses@2.0.1:
1436 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
1437 | engines: {node: '>= 0.8'}
1438 |
1439 | streamsearch@1.1.0:
1440 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
1441 | engines: {node: '>=10.0.0'}
1442 |
1443 | string-width@4.2.3:
1444 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
1445 | engines: {node: '>=8'}
1446 |
1447 | string-width@5.1.2:
1448 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
1449 | engines: {node: '>=12'}
1450 |
1451 | string_decoder@1.1.1:
1452 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
1453 |
1454 | strip-ansi@6.0.1:
1455 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1456 | engines: {node: '>=8'}
1457 |
1458 | strip-ansi@7.1.0:
1459 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
1460 | engines: {node: '>=12'}
1461 |
1462 | strip-final-newline@2.0.0:
1463 | resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
1464 | engines: {node: '>=6'}
1465 |
1466 | sucrase@3.35.0:
1467 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
1468 | engines: {node: '>=16 || 14 >=14.17'}
1469 | hasBin: true
1470 |
1471 | thenify-all@1.6.0:
1472 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
1473 | engines: {node: '>=0.8'}
1474 |
1475 | thenify@3.3.1:
1476 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
1477 |
1478 | tinyglobby@0.2.6:
1479 | resolution: {integrity: sha512-NbBoFBpqfcgd1tCiO8Lkfdk+xrA7mlLR9zgvZcZWQQwU63XAfUePyd6wZBaU93Hqw347lHnwFzttAkemHzzz4g==}
1480 | engines: {node: '>=12.0.0'}
1481 |
1482 | to-regex-range@5.0.1:
1483 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
1484 | engines: {node: '>=8.0'}
1485 |
1486 | toidentifier@1.0.1:
1487 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
1488 | engines: {node: '>=0.6'}
1489 |
1490 | tr46@1.0.1:
1491 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
1492 |
1493 | tree-kill@1.2.2:
1494 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
1495 | hasBin: true
1496 |
1497 | ts-interface-checker@0.1.13:
1498 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
1499 |
1500 | tsscmp@1.0.6:
1501 | resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==}
1502 | engines: {node: '>=0.6.x'}
1503 |
1504 | tsup@8.3.0:
1505 | resolution: {integrity: sha512-ALscEeyS03IomcuNdFdc0YWGVIkwH1Ws7nfTbAPuoILvEV2hpGQAY72LIOjglGo4ShWpZfpBqP/jpQVCzqYQag==}
1506 | engines: {node: '>=18'}
1507 | hasBin: true
1508 | peerDependencies:
1509 | '@microsoft/api-extractor': ^7.36.0
1510 | '@swc/core': ^1
1511 | postcss: ^8.4.12
1512 | typescript: '>=4.5.0'
1513 | peerDependenciesMeta:
1514 | '@microsoft/api-extractor':
1515 | optional: true
1516 | '@swc/core':
1517 | optional: true
1518 | postcss:
1519 | optional: true
1520 | typescript:
1521 | optional: true
1522 |
1523 | turbo-darwin-64@2.1.2:
1524 | resolution: {integrity: sha512-3TEBxHWh99h2yIzkuIigMEOXt/ItYQp0aPiJjPd1xN4oDcsKK5AxiFKPH9pdtfIBzYsY59kQhZiFj0ELnSP7Bw==}
1525 | cpu: [x64]
1526 | os: [darwin]
1527 |
1528 | turbo-darwin-arm64@2.1.2:
1529 | resolution: {integrity: sha512-he0miWNq2WxJzsH82jS2Z4MXpnkzn9SH8a79iPXiJkq25QREImucscM4RPasXm8wARp91pyysJMq6aasD45CeA==}
1530 | cpu: [arm64]
1531 | os: [darwin]
1532 |
1533 | turbo-linux-64@2.1.2:
1534 | resolution: {integrity: sha512-fKUBcc0rK8Vdqv5a/E3CSpMBLG1bzwv+Q0Q83F8fG2ZfNCNKGbcEYABdonNZkkx141Rj03cZQFCgxu3MVEGU+A==}
1535 | cpu: [x64]
1536 | os: [linux]
1537 |
1538 | turbo-linux-arm64@2.1.2:
1539 | resolution: {integrity: sha512-sV8Bpmm0WiuxgbhxymcC7wSsuxfBBieI98GegSwbr/bs1ANAgzCg93urIrdKdQ3/b31zZxQwcaP4FBF1wx1Qdg==}
1540 | cpu: [arm64]
1541 | os: [linux]
1542 |
1543 | turbo-windows-64@2.1.2:
1544 | resolution: {integrity: sha512-wcmIJZI9ORT9ykHGliFE6kWRQrlH930QGSjSgWC8uFChFFuOyUlvC7ttcxuSvU9VqC7NF4C+GVAcFJQ8lTjN7g==}
1545 | cpu: [x64]
1546 | os: [win32]
1547 |
1548 | turbo-windows-arm64@2.1.2:
1549 | resolution: {integrity: sha512-zdnXjrhk7YO6CP+Q5wPueEvOCLH4lDa6C4rrwiakcWcPgcQGbVozJlo4uaQ6awo8HLWQEvOwu84RkWTdLAc/Hw==}
1550 | cpu: [arm64]
1551 | os: [win32]
1552 |
1553 | turbo@2.1.2:
1554 | resolution: {integrity: sha512-Jb0rbU4iHEVQ18An/YfakdIv9rKnd3zUfSE117EngrfWXFHo3RndVH96US3GsT8VHpwTncPePDBT2t06PaFLrw==}
1555 | hasBin: true
1556 |
1557 | type-is@1.6.18:
1558 | resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
1559 | engines: {node: '>= 0.6'}
1560 |
1561 | typedarray@0.0.6:
1562 | resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
1563 |
1564 | typescript@5.6.2:
1565 | resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==}
1566 | engines: {node: '>=14.17'}
1567 | hasBin: true
1568 |
1569 | undici-types@6.19.8:
1570 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
1571 |
1572 | unpipe@1.0.0:
1573 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
1574 | engines: {node: '>= 0.8'}
1575 |
1576 | util-deprecate@1.0.2:
1577 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
1578 |
1579 | vary@1.1.2:
1580 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
1581 | engines: {node: '>= 0.8'}
1582 |
1583 | vite@5.4.6:
1584 | resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==}
1585 | engines: {node: ^18.0.0 || >=20.0.0}
1586 | hasBin: true
1587 | peerDependencies:
1588 | '@types/node': ^18.0.0 || >=20.0.0
1589 | less: '*'
1590 | lightningcss: ^1.21.0
1591 | sass: '*'
1592 | sass-embedded: '*'
1593 | stylus: '*'
1594 | sugarss: '*'
1595 | terser: ^5.4.0
1596 | peerDependenciesMeta:
1597 | '@types/node':
1598 | optional: true
1599 | less:
1600 | optional: true
1601 | lightningcss:
1602 | optional: true
1603 | sass:
1604 | optional: true
1605 | sass-embedded:
1606 | optional: true
1607 | stylus:
1608 | optional: true
1609 | sugarss:
1610 | optional: true
1611 | terser:
1612 | optional: true
1613 |
1614 | web-streams-polyfill@3.3.3:
1615 | resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
1616 | engines: {node: '>= 8'}
1617 |
1618 | webidl-conversions@4.0.2:
1619 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
1620 |
1621 | whatwg-url@7.1.0:
1622 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
1623 |
1624 | which@2.0.2:
1625 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1626 | engines: {node: '>= 8'}
1627 | hasBin: true
1628 |
1629 | wrap-ansi@7.0.0:
1630 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1631 | engines: {node: '>=10'}
1632 |
1633 | wrap-ansi@8.1.0:
1634 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
1635 | engines: {node: '>=12'}
1636 |
1637 | wrappy@1.0.2:
1638 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
1639 |
1640 | xtend@4.0.2:
1641 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
1642 | engines: {node: '>=0.4'}
1643 |
1644 | ylru@1.4.0:
1645 | resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==}
1646 | engines: {node: '>= 4.0.0'}
1647 |
1648 | zod@3.24.2:
1649 | resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==}
1650 |
1651 | snapshots:
1652 |
1653 | '@citizenfx/client@2.0.10822-1': {}
1654 |
1655 | '@citizenfx/http-wrapper@0.2.2': {}
1656 |
1657 | '@citizenfx/server@2.0.7290-1': {}
1658 |
1659 | '@esbuild/aix-ppc64@0.21.5':
1660 | optional: true
1661 |
1662 | '@esbuild/aix-ppc64@0.23.1':
1663 | optional: true
1664 |
1665 | '@esbuild/aix-ppc64@0.24.0':
1666 | optional: true
1667 |
1668 | '@esbuild/android-arm64@0.21.5':
1669 | optional: true
1670 |
1671 | '@esbuild/android-arm64@0.23.1':
1672 | optional: true
1673 |
1674 | '@esbuild/android-arm64@0.24.0':
1675 | optional: true
1676 |
1677 | '@esbuild/android-arm@0.21.5':
1678 | optional: true
1679 |
1680 | '@esbuild/android-arm@0.23.1':
1681 | optional: true
1682 |
1683 | '@esbuild/android-arm@0.24.0':
1684 | optional: true
1685 |
1686 | '@esbuild/android-x64@0.21.5':
1687 | optional: true
1688 |
1689 | '@esbuild/android-x64@0.23.1':
1690 | optional: true
1691 |
1692 | '@esbuild/android-x64@0.24.0':
1693 | optional: true
1694 |
1695 | '@esbuild/darwin-arm64@0.21.5':
1696 | optional: true
1697 |
1698 | '@esbuild/darwin-arm64@0.23.1':
1699 | optional: true
1700 |
1701 | '@esbuild/darwin-arm64@0.24.0':
1702 | optional: true
1703 |
1704 | '@esbuild/darwin-x64@0.21.5':
1705 | optional: true
1706 |
1707 | '@esbuild/darwin-x64@0.23.1':
1708 | optional: true
1709 |
1710 | '@esbuild/darwin-x64@0.24.0':
1711 | optional: true
1712 |
1713 | '@esbuild/freebsd-arm64@0.21.5':
1714 | optional: true
1715 |
1716 | '@esbuild/freebsd-arm64@0.23.1':
1717 | optional: true
1718 |
1719 | '@esbuild/freebsd-arm64@0.24.0':
1720 | optional: true
1721 |
1722 | '@esbuild/freebsd-x64@0.21.5':
1723 | optional: true
1724 |
1725 | '@esbuild/freebsd-x64@0.23.1':
1726 | optional: true
1727 |
1728 | '@esbuild/freebsd-x64@0.24.0':
1729 | optional: true
1730 |
1731 | '@esbuild/linux-arm64@0.21.5':
1732 | optional: true
1733 |
1734 | '@esbuild/linux-arm64@0.23.1':
1735 | optional: true
1736 |
1737 | '@esbuild/linux-arm64@0.24.0':
1738 | optional: true
1739 |
1740 | '@esbuild/linux-arm@0.21.5':
1741 | optional: true
1742 |
1743 | '@esbuild/linux-arm@0.23.1':
1744 | optional: true
1745 |
1746 | '@esbuild/linux-arm@0.24.0':
1747 | optional: true
1748 |
1749 | '@esbuild/linux-ia32@0.21.5':
1750 | optional: true
1751 |
1752 | '@esbuild/linux-ia32@0.23.1':
1753 | optional: true
1754 |
1755 | '@esbuild/linux-ia32@0.24.0':
1756 | optional: true
1757 |
1758 | '@esbuild/linux-loong64@0.21.5':
1759 | optional: true
1760 |
1761 | '@esbuild/linux-loong64@0.23.1':
1762 | optional: true
1763 |
1764 | '@esbuild/linux-loong64@0.24.0':
1765 | optional: true
1766 |
1767 | '@esbuild/linux-mips64el@0.21.5':
1768 | optional: true
1769 |
1770 | '@esbuild/linux-mips64el@0.23.1':
1771 | optional: true
1772 |
1773 | '@esbuild/linux-mips64el@0.24.0':
1774 | optional: true
1775 |
1776 | '@esbuild/linux-ppc64@0.21.5':
1777 | optional: true
1778 |
1779 | '@esbuild/linux-ppc64@0.23.1':
1780 | optional: true
1781 |
1782 | '@esbuild/linux-ppc64@0.24.0':
1783 | optional: true
1784 |
1785 | '@esbuild/linux-riscv64@0.21.5':
1786 | optional: true
1787 |
1788 | '@esbuild/linux-riscv64@0.23.1':
1789 | optional: true
1790 |
1791 | '@esbuild/linux-riscv64@0.24.0':
1792 | optional: true
1793 |
1794 | '@esbuild/linux-s390x@0.21.5':
1795 | optional: true
1796 |
1797 | '@esbuild/linux-s390x@0.23.1':
1798 | optional: true
1799 |
1800 | '@esbuild/linux-s390x@0.24.0':
1801 | optional: true
1802 |
1803 | '@esbuild/linux-x64@0.21.5':
1804 | optional: true
1805 |
1806 | '@esbuild/linux-x64@0.23.1':
1807 | optional: true
1808 |
1809 | '@esbuild/linux-x64@0.24.0':
1810 | optional: true
1811 |
1812 | '@esbuild/netbsd-x64@0.21.5':
1813 | optional: true
1814 |
1815 | '@esbuild/netbsd-x64@0.23.1':
1816 | optional: true
1817 |
1818 | '@esbuild/netbsd-x64@0.24.0':
1819 | optional: true
1820 |
1821 | '@esbuild/openbsd-arm64@0.23.1':
1822 | optional: true
1823 |
1824 | '@esbuild/openbsd-arm64@0.24.0':
1825 | optional: true
1826 |
1827 | '@esbuild/openbsd-x64@0.21.5':
1828 | optional: true
1829 |
1830 | '@esbuild/openbsd-x64@0.23.1':
1831 | optional: true
1832 |
1833 | '@esbuild/openbsd-x64@0.24.0':
1834 | optional: true
1835 |
1836 | '@esbuild/sunos-x64@0.21.5':
1837 | optional: true
1838 |
1839 | '@esbuild/sunos-x64@0.23.1':
1840 | optional: true
1841 |
1842 | '@esbuild/sunos-x64@0.24.0':
1843 | optional: true
1844 |
1845 | '@esbuild/win32-arm64@0.21.5':
1846 | optional: true
1847 |
1848 | '@esbuild/win32-arm64@0.23.1':
1849 | optional: true
1850 |
1851 | '@esbuild/win32-arm64@0.24.0':
1852 | optional: true
1853 |
1854 | '@esbuild/win32-ia32@0.21.5':
1855 | optional: true
1856 |
1857 | '@esbuild/win32-ia32@0.23.1':
1858 | optional: true
1859 |
1860 | '@esbuild/win32-ia32@0.24.0':
1861 | optional: true
1862 |
1863 | '@esbuild/win32-x64@0.21.5':
1864 | optional: true
1865 |
1866 | '@esbuild/win32-x64@0.23.1':
1867 | optional: true
1868 |
1869 | '@esbuild/win32-x64@0.24.0':
1870 | optional: true
1871 |
1872 | '@hapi/bourne@3.0.0': {}
1873 |
1874 | '@isaacs/cliui@8.0.2':
1875 | dependencies:
1876 | string-width: 5.1.2
1877 | string-width-cjs: string-width@4.2.3
1878 | strip-ansi: 7.1.0
1879 | strip-ansi-cjs: strip-ansi@6.0.1
1880 | wrap-ansi: 8.1.0
1881 | wrap-ansi-cjs: wrap-ansi@7.0.0
1882 |
1883 | '@jridgewell/gen-mapping@0.3.5':
1884 | dependencies:
1885 | '@jridgewell/set-array': 1.2.1
1886 | '@jridgewell/sourcemap-codec': 1.5.0
1887 | '@jridgewell/trace-mapping': 0.3.25
1888 |
1889 | '@jridgewell/resolve-uri@3.1.2': {}
1890 |
1891 | '@jridgewell/set-array@1.2.1': {}
1892 |
1893 | '@jridgewell/sourcemap-codec@1.5.0': {}
1894 |
1895 | '@jridgewell/trace-mapping@0.3.25':
1896 | dependencies:
1897 | '@jridgewell/resolve-uri': 3.1.2
1898 | '@jridgewell/sourcemap-codec': 1.5.0
1899 |
1900 | '@koa/router@13.1.0':
1901 | dependencies:
1902 | http-errors: 2.0.0
1903 | koa-compose: 4.1.0
1904 | path-to-regexp: 6.3.0
1905 |
1906 | '@pkgjs/parseargs@0.11.0':
1907 | optional: true
1908 |
1909 | '@rollup/rollup-android-arm-eabi@4.22.0':
1910 | optional: true
1911 |
1912 | '@rollup/rollup-android-arm64@4.22.0':
1913 | optional: true
1914 |
1915 | '@rollup/rollup-darwin-arm64@4.22.0':
1916 | optional: true
1917 |
1918 | '@rollup/rollup-darwin-x64@4.22.0':
1919 | optional: true
1920 |
1921 | '@rollup/rollup-linux-arm-gnueabihf@4.22.0':
1922 | optional: true
1923 |
1924 | '@rollup/rollup-linux-arm-musleabihf@4.22.0':
1925 | optional: true
1926 |
1927 | '@rollup/rollup-linux-arm64-gnu@4.22.0':
1928 | optional: true
1929 |
1930 | '@rollup/rollup-linux-arm64-musl@4.22.0':
1931 | optional: true
1932 |
1933 | '@rollup/rollup-linux-powerpc64le-gnu@4.22.0':
1934 | optional: true
1935 |
1936 | '@rollup/rollup-linux-riscv64-gnu@4.22.0':
1937 | optional: true
1938 |
1939 | '@rollup/rollup-linux-s390x-gnu@4.22.0':
1940 | optional: true
1941 |
1942 | '@rollup/rollup-linux-x64-gnu@4.22.0':
1943 | optional: true
1944 |
1945 | '@rollup/rollup-linux-x64-musl@4.22.0':
1946 | optional: true
1947 |
1948 | '@rollup/rollup-win32-arm64-msvc@4.22.0':
1949 | optional: true
1950 |
1951 | '@rollup/rollup-win32-ia32-msvc@4.22.0':
1952 | optional: true
1953 |
1954 | '@rollup/rollup-win32-x64-msvc@4.22.0':
1955 | optional: true
1956 |
1957 | '@types/accepts@1.3.7':
1958 | dependencies:
1959 | '@types/node': 22.8.6
1960 |
1961 | '@types/body-parser@1.19.5':
1962 | dependencies:
1963 | '@types/connect': 3.4.38
1964 | '@types/node': 22.8.6
1965 |
1966 | '@types/co-body@6.1.3':
1967 | dependencies:
1968 | '@types/node': 22.8.6
1969 | '@types/qs': 6.9.18
1970 |
1971 | '@types/connect@3.4.38':
1972 | dependencies:
1973 | '@types/node': 22.8.6
1974 |
1975 | '@types/content-disposition@0.5.8': {}
1976 |
1977 | '@types/cookies@0.9.0':
1978 | dependencies:
1979 | '@types/connect': 3.4.38
1980 | '@types/express': 5.0.0
1981 | '@types/keygrip': 1.0.6
1982 | '@types/node': 22.8.6
1983 |
1984 | '@types/estree@1.0.5': {}
1985 |
1986 | '@types/express-serve-static-core@5.0.6':
1987 | dependencies:
1988 | '@types/node': 22.8.6
1989 | '@types/qs': 6.9.18
1990 | '@types/range-parser': 1.2.7
1991 | '@types/send': 0.17.4
1992 |
1993 | '@types/express@5.0.0':
1994 | dependencies:
1995 | '@types/body-parser': 1.19.5
1996 | '@types/express-serve-static-core': 5.0.6
1997 | '@types/qs': 6.9.18
1998 | '@types/serve-static': 1.15.7
1999 |
2000 | '@types/formidable@2.0.6':
2001 | dependencies:
2002 | '@types/node': 22.8.6
2003 |
2004 | '@types/formidable@3.4.5':
2005 | dependencies:
2006 | '@types/node': 22.8.6
2007 |
2008 | '@types/http-assert@1.5.6': {}
2009 |
2010 | '@types/http-errors@2.0.4': {}
2011 |
2012 | '@types/keygrip@1.0.6': {}
2013 |
2014 | '@types/koa-compose@3.2.8':
2015 | dependencies:
2016 | '@types/koa': 2.15.0
2017 |
2018 | '@types/koa-router@7.4.8':
2019 | dependencies:
2020 | '@types/koa': 2.15.0
2021 |
2022 | '@types/koa@2.15.0':
2023 | dependencies:
2024 | '@types/accepts': 1.3.7
2025 | '@types/content-disposition': 0.5.8
2026 | '@types/cookies': 0.9.0
2027 | '@types/http-assert': 1.5.6
2028 | '@types/http-errors': 2.0.4
2029 | '@types/keygrip': 1.0.6
2030 | '@types/koa-compose': 3.2.8
2031 | '@types/node': 22.8.6
2032 |
2033 | '@types/koa__router@12.0.4':
2034 | dependencies:
2035 | '@types/koa': 2.15.0
2036 |
2037 | '@types/mime@1.3.5': {}
2038 |
2039 | '@types/multer@1.4.12':
2040 | dependencies:
2041 | '@types/express': 5.0.0
2042 |
2043 | '@types/node@22.8.6':
2044 | dependencies:
2045 | undici-types: 6.19.8
2046 |
2047 | '@types/qs@6.9.18': {}
2048 |
2049 | '@types/range-parser@1.2.7': {}
2050 |
2051 | '@types/send@0.17.4':
2052 | dependencies:
2053 | '@types/mime': 1.3.5
2054 | '@types/node': 22.8.6
2055 |
2056 | '@types/serve-static@1.15.7':
2057 | dependencies:
2058 | '@types/http-errors': 2.0.4
2059 | '@types/node': 22.8.6
2060 | '@types/send': 0.17.4
2061 |
2062 | accepts@1.3.8:
2063 | dependencies:
2064 | mime-types: 2.1.35
2065 | negotiator: 0.6.3
2066 |
2067 | ansi-regex@5.0.1: {}
2068 |
2069 | ansi-regex@6.1.0: {}
2070 |
2071 | ansi-styles@4.3.0:
2072 | dependencies:
2073 | color-convert: 2.0.1
2074 |
2075 | ansi-styles@6.2.1: {}
2076 |
2077 | any-promise@1.3.0: {}
2078 |
2079 | anymatch@3.1.3:
2080 | dependencies:
2081 | normalize-path: 3.0.0
2082 | picomatch: 2.3.1
2083 |
2084 | append-field@1.0.0: {}
2085 |
2086 | asap@2.0.6: {}
2087 |
2088 | asynckit@0.4.0: {}
2089 |
2090 | balanced-match@1.0.2: {}
2091 |
2092 | binary-extensions@2.3.0: {}
2093 |
2094 | brace-expansion@2.0.1:
2095 | dependencies:
2096 | balanced-match: 1.0.2
2097 |
2098 | braces@3.0.3:
2099 | dependencies:
2100 | fill-range: 7.1.1
2101 |
2102 | buffer-from@1.1.2: {}
2103 |
2104 | bundle-require@5.0.0(esbuild@0.23.1):
2105 | dependencies:
2106 | esbuild: 0.23.1
2107 | load-tsconfig: 0.2.5
2108 |
2109 | busboy@1.6.0:
2110 | dependencies:
2111 | streamsearch: 1.1.0
2112 |
2113 | bytes@3.1.2: {}
2114 |
2115 | cac@6.7.14: {}
2116 |
2117 | cache-content-type@1.0.1:
2118 | dependencies:
2119 | mime-types: 2.1.35
2120 | ylru: 1.4.0
2121 |
2122 | call-bind-apply-helpers@1.0.2:
2123 | dependencies:
2124 | es-errors: 1.3.0
2125 | function-bind: 1.1.2
2126 |
2127 | call-bound@1.0.3:
2128 | dependencies:
2129 | call-bind-apply-helpers: 1.0.2
2130 | get-intrinsic: 1.2.7
2131 |
2132 | chokidar@3.6.0:
2133 | dependencies:
2134 | anymatch: 3.1.3
2135 | braces: 3.0.3
2136 | glob-parent: 5.1.2
2137 | is-binary-path: 2.1.0
2138 | is-glob: 4.0.3
2139 | normalize-path: 3.0.0
2140 | readdirp: 3.6.0
2141 | optionalDependencies:
2142 | fsevents: 2.3.3
2143 |
2144 | co-body@6.2.0:
2145 | dependencies:
2146 | '@hapi/bourne': 3.0.0
2147 | inflation: 2.1.0
2148 | qs: 6.14.0
2149 | raw-body: 2.5.2
2150 | type-is: 1.6.18
2151 |
2152 | co@4.6.0: {}
2153 |
2154 | color-convert@2.0.1:
2155 | dependencies:
2156 | color-name: 1.1.4
2157 |
2158 | color-name@1.1.4: {}
2159 |
2160 | colorette@2.0.20: {}
2161 |
2162 | combined-stream@1.0.8:
2163 | dependencies:
2164 | delayed-stream: 1.0.0
2165 |
2166 | commander@4.1.1: {}
2167 |
2168 | concat-stream@1.6.2:
2169 | dependencies:
2170 | buffer-from: 1.1.2
2171 | inherits: 2.0.4
2172 | readable-stream: 2.3.8
2173 | typedarray: 0.0.6
2174 |
2175 | consola@3.2.3: {}
2176 |
2177 | content-disposition@0.5.4:
2178 | dependencies:
2179 | safe-buffer: 5.2.1
2180 |
2181 | content-type@1.0.5: {}
2182 |
2183 | cookies@0.9.1:
2184 | dependencies:
2185 | depd: 2.0.0
2186 | keygrip: 1.1.0
2187 |
2188 | core-util-is@1.0.3: {}
2189 |
2190 | cross-spawn@7.0.3:
2191 | dependencies:
2192 | path-key: 3.1.1
2193 | shebang-command: 2.0.0
2194 | which: 2.0.2
2195 |
2196 | data-uri-to-buffer@4.0.1: {}
2197 |
2198 | debug@4.3.7:
2199 | dependencies:
2200 | ms: 2.1.3
2201 |
2202 | deep-equal@1.0.1: {}
2203 |
2204 | delayed-stream@1.0.0: {}
2205 |
2206 | delegates@1.0.0: {}
2207 |
2208 | depd@1.1.2: {}
2209 |
2210 | depd@2.0.0: {}
2211 |
2212 | destroy@1.2.0: {}
2213 |
2214 | dezalgo@1.0.4:
2215 | dependencies:
2216 | asap: 2.0.6
2217 | wrappy: 1.0.2
2218 |
2219 | dunder-proto@1.0.1:
2220 | dependencies:
2221 | call-bind-apply-helpers: 1.0.2
2222 | es-errors: 1.3.0
2223 | gopd: 1.2.0
2224 |
2225 | eastasianwidth@0.2.0: {}
2226 |
2227 | ee-first@1.1.1: {}
2228 |
2229 | emoji-regex@8.0.0: {}
2230 |
2231 | emoji-regex@9.2.2: {}
2232 |
2233 | encodeurl@1.0.2: {}
2234 |
2235 | es-define-property@1.0.1: {}
2236 |
2237 | es-errors@1.3.0: {}
2238 |
2239 | es-object-atoms@1.1.1:
2240 | dependencies:
2241 | es-errors: 1.3.0
2242 |
2243 | esbuild@0.21.5:
2244 | optionalDependencies:
2245 | '@esbuild/aix-ppc64': 0.21.5
2246 | '@esbuild/android-arm': 0.21.5
2247 | '@esbuild/android-arm64': 0.21.5
2248 | '@esbuild/android-x64': 0.21.5
2249 | '@esbuild/darwin-arm64': 0.21.5
2250 | '@esbuild/darwin-x64': 0.21.5
2251 | '@esbuild/freebsd-arm64': 0.21.5
2252 | '@esbuild/freebsd-x64': 0.21.5
2253 | '@esbuild/linux-arm': 0.21.5
2254 | '@esbuild/linux-arm64': 0.21.5
2255 | '@esbuild/linux-ia32': 0.21.5
2256 | '@esbuild/linux-loong64': 0.21.5
2257 | '@esbuild/linux-mips64el': 0.21.5
2258 | '@esbuild/linux-ppc64': 0.21.5
2259 | '@esbuild/linux-riscv64': 0.21.5
2260 | '@esbuild/linux-s390x': 0.21.5
2261 | '@esbuild/linux-x64': 0.21.5
2262 | '@esbuild/netbsd-x64': 0.21.5
2263 | '@esbuild/openbsd-x64': 0.21.5
2264 | '@esbuild/sunos-x64': 0.21.5
2265 | '@esbuild/win32-arm64': 0.21.5
2266 | '@esbuild/win32-ia32': 0.21.5
2267 | '@esbuild/win32-x64': 0.21.5
2268 |
2269 | esbuild@0.23.1:
2270 | optionalDependencies:
2271 | '@esbuild/aix-ppc64': 0.23.1
2272 | '@esbuild/android-arm': 0.23.1
2273 | '@esbuild/android-arm64': 0.23.1
2274 | '@esbuild/android-x64': 0.23.1
2275 | '@esbuild/darwin-arm64': 0.23.1
2276 | '@esbuild/darwin-x64': 0.23.1
2277 | '@esbuild/freebsd-arm64': 0.23.1
2278 | '@esbuild/freebsd-x64': 0.23.1
2279 | '@esbuild/linux-arm': 0.23.1
2280 | '@esbuild/linux-arm64': 0.23.1
2281 | '@esbuild/linux-ia32': 0.23.1
2282 | '@esbuild/linux-loong64': 0.23.1
2283 | '@esbuild/linux-mips64el': 0.23.1
2284 | '@esbuild/linux-ppc64': 0.23.1
2285 | '@esbuild/linux-riscv64': 0.23.1
2286 | '@esbuild/linux-s390x': 0.23.1
2287 | '@esbuild/linux-x64': 0.23.1
2288 | '@esbuild/netbsd-x64': 0.23.1
2289 | '@esbuild/openbsd-arm64': 0.23.1
2290 | '@esbuild/openbsd-x64': 0.23.1
2291 | '@esbuild/sunos-x64': 0.23.1
2292 | '@esbuild/win32-arm64': 0.23.1
2293 | '@esbuild/win32-ia32': 0.23.1
2294 | '@esbuild/win32-x64': 0.23.1
2295 |
2296 | esbuild@0.24.0:
2297 | optionalDependencies:
2298 | '@esbuild/aix-ppc64': 0.24.0
2299 | '@esbuild/android-arm': 0.24.0
2300 | '@esbuild/android-arm64': 0.24.0
2301 | '@esbuild/android-x64': 0.24.0
2302 | '@esbuild/darwin-arm64': 0.24.0
2303 | '@esbuild/darwin-x64': 0.24.0
2304 | '@esbuild/freebsd-arm64': 0.24.0
2305 | '@esbuild/freebsd-x64': 0.24.0
2306 | '@esbuild/linux-arm': 0.24.0
2307 | '@esbuild/linux-arm64': 0.24.0
2308 | '@esbuild/linux-ia32': 0.24.0
2309 | '@esbuild/linux-loong64': 0.24.0
2310 | '@esbuild/linux-mips64el': 0.24.0
2311 | '@esbuild/linux-ppc64': 0.24.0
2312 | '@esbuild/linux-riscv64': 0.24.0
2313 | '@esbuild/linux-s390x': 0.24.0
2314 | '@esbuild/linux-x64': 0.24.0
2315 | '@esbuild/netbsd-x64': 0.24.0
2316 | '@esbuild/openbsd-arm64': 0.24.0
2317 | '@esbuild/openbsd-x64': 0.24.0
2318 | '@esbuild/sunos-x64': 0.24.0
2319 | '@esbuild/win32-arm64': 0.24.0
2320 | '@esbuild/win32-ia32': 0.24.0
2321 | '@esbuild/win32-x64': 0.24.0
2322 |
2323 | escape-html@1.0.3: {}
2324 |
2325 | execa@5.1.1:
2326 | dependencies:
2327 | cross-spawn: 7.0.3
2328 | get-stream: 6.0.1
2329 | human-signals: 2.1.0
2330 | is-stream: 2.0.1
2331 | merge-stream: 2.0.0
2332 | npm-run-path: 4.0.1
2333 | onetime: 5.1.2
2334 | signal-exit: 3.0.7
2335 | strip-final-newline: 2.0.0
2336 |
2337 | fdir@6.3.0(picomatch@4.0.2):
2338 | optionalDependencies:
2339 | picomatch: 4.0.2
2340 |
2341 | fetch-blob@3.2.0:
2342 | dependencies:
2343 | node-domexception: 1.0.0
2344 | web-streams-polyfill: 3.3.3
2345 |
2346 | fill-range@7.1.1:
2347 | dependencies:
2348 | to-regex-range: 5.0.1
2349 |
2350 | foreground-child@3.3.0:
2351 | dependencies:
2352 | cross-spawn: 7.0.3
2353 | signal-exit: 4.1.0
2354 |
2355 | form-data@4.0.1:
2356 | dependencies:
2357 | asynckit: 0.4.0
2358 | combined-stream: 1.0.8
2359 | mime-types: 2.1.35
2360 |
2361 | formdata-polyfill@4.0.10:
2362 | dependencies:
2363 | fetch-blob: 3.2.0
2364 |
2365 | formidable@2.1.2:
2366 | dependencies:
2367 | dezalgo: 1.0.4
2368 | hexoid: 1.0.0
2369 | once: 1.4.0
2370 | qs: 6.14.0
2371 |
2372 | fresh@0.5.2: {}
2373 |
2374 | fsevents@2.3.3:
2375 | optional: true
2376 |
2377 | function-bind@1.1.2: {}
2378 |
2379 | get-intrinsic@1.2.7:
2380 | dependencies:
2381 | call-bind-apply-helpers: 1.0.2
2382 | es-define-property: 1.0.1
2383 | es-errors: 1.3.0
2384 | es-object-atoms: 1.1.1
2385 | function-bind: 1.1.2
2386 | get-proto: 1.0.1
2387 | gopd: 1.2.0
2388 | has-symbols: 1.1.0
2389 | hasown: 2.0.2
2390 | math-intrinsics: 1.1.0
2391 |
2392 | get-proto@1.0.1:
2393 | dependencies:
2394 | dunder-proto: 1.0.1
2395 | es-object-atoms: 1.1.1
2396 |
2397 | get-stream@6.0.1: {}
2398 |
2399 | glob-parent@5.1.2:
2400 | dependencies:
2401 | is-glob: 4.0.3
2402 |
2403 | glob@10.4.5:
2404 | dependencies:
2405 | foreground-child: 3.3.0
2406 | jackspeak: 3.4.3
2407 | minimatch: 9.0.5
2408 | minipass: 7.1.2
2409 | package-json-from-dist: 1.0.0
2410 | path-scurry: 1.11.1
2411 |
2412 | gopd@1.2.0: {}
2413 |
2414 | has-symbols@1.1.0: {}
2415 |
2416 | has-tostringtag@1.0.2:
2417 | dependencies:
2418 | has-symbols: 1.1.0
2419 |
2420 | hasown@2.0.2:
2421 | dependencies:
2422 | function-bind: 1.1.2
2423 |
2424 | hexoid@1.0.0: {}
2425 |
2426 | http-assert@1.5.0:
2427 | dependencies:
2428 | deep-equal: 1.0.1
2429 | http-errors: 1.8.1
2430 |
2431 | http-errors@1.8.1:
2432 | dependencies:
2433 | depd: 1.1.2
2434 | inherits: 2.0.4
2435 | setprototypeof: 1.2.0
2436 | statuses: 1.5.0
2437 | toidentifier: 1.0.1
2438 |
2439 | http-errors@2.0.0:
2440 | dependencies:
2441 | depd: 2.0.0
2442 | inherits: 2.0.4
2443 | setprototypeof: 1.2.0
2444 | statuses: 2.0.1
2445 | toidentifier: 1.0.1
2446 |
2447 | human-signals@2.1.0: {}
2448 |
2449 | iconv-lite@0.4.24:
2450 | dependencies:
2451 | safer-buffer: 2.1.2
2452 |
2453 | inflation@2.1.0: {}
2454 |
2455 | inherits@2.0.4: {}
2456 |
2457 | is-binary-path@2.1.0:
2458 | dependencies:
2459 | binary-extensions: 2.3.0
2460 |
2461 | is-extglob@2.1.1: {}
2462 |
2463 | is-fullwidth-code-point@3.0.0: {}
2464 |
2465 | is-generator-function@1.1.0:
2466 | dependencies:
2467 | call-bound: 1.0.3
2468 | get-proto: 1.0.1
2469 | has-tostringtag: 1.0.2
2470 | safe-regex-test: 1.1.0
2471 |
2472 | is-glob@4.0.3:
2473 | dependencies:
2474 | is-extglob: 2.1.1
2475 |
2476 | is-number@7.0.0: {}
2477 |
2478 | is-regex@1.2.1:
2479 | dependencies:
2480 | call-bound: 1.0.3
2481 | gopd: 1.2.0
2482 | has-tostringtag: 1.0.2
2483 | hasown: 2.0.2
2484 |
2485 | is-stream@2.0.1: {}
2486 |
2487 | isarray@1.0.0: {}
2488 |
2489 | isexe@2.0.0: {}
2490 |
2491 | jackspeak@3.4.3:
2492 | dependencies:
2493 | '@isaacs/cliui': 8.0.2
2494 | optionalDependencies:
2495 | '@pkgjs/parseargs': 0.11.0
2496 |
2497 | joycon@3.1.1: {}
2498 |
2499 | keygrip@1.1.0:
2500 | dependencies:
2501 | tsscmp: 1.0.6
2502 |
2503 | koa-body@6.0.1:
2504 | dependencies:
2505 | '@types/co-body': 6.1.3
2506 | '@types/formidable': 2.0.6
2507 | '@types/koa': 2.15.0
2508 | co-body: 6.2.0
2509 | formidable: 2.1.2
2510 | zod: 3.24.2
2511 |
2512 | koa-compose@4.1.0: {}
2513 |
2514 | koa-convert@2.0.0:
2515 | dependencies:
2516 | co: 4.6.0
2517 | koa-compose: 4.1.0
2518 |
2519 | koa-router@13.0.1:
2520 | dependencies:
2521 | http-errors: 2.0.0
2522 | koa-compose: 4.1.0
2523 | path-to-regexp: 8.2.0
2524 |
2525 | koa@2.15.4:
2526 | dependencies:
2527 | accepts: 1.3.8
2528 | cache-content-type: 1.0.1
2529 | content-disposition: 0.5.4
2530 | content-type: 1.0.5
2531 | cookies: 0.9.1
2532 | debug: 4.3.7
2533 | delegates: 1.0.0
2534 | depd: 2.0.0
2535 | destroy: 1.2.0
2536 | encodeurl: 1.0.2
2537 | escape-html: 1.0.3
2538 | fresh: 0.5.2
2539 | http-assert: 1.5.0
2540 | http-errors: 1.8.1
2541 | is-generator-function: 1.1.0
2542 | koa-compose: 4.1.0
2543 | koa-convert: 2.0.0
2544 | on-finished: 2.4.1
2545 | only: 0.0.2
2546 | parseurl: 1.3.3
2547 | statuses: 1.5.0
2548 | type-is: 1.6.18
2549 | vary: 1.1.2
2550 | transitivePeerDependencies:
2551 | - supports-color
2552 |
2553 | lilconfig@3.1.2: {}
2554 |
2555 | lines-and-columns@1.2.4: {}
2556 |
2557 | load-tsconfig@0.2.5: {}
2558 |
2559 | lodash.sortby@4.7.0: {}
2560 |
2561 | lru-cache@10.4.3: {}
2562 |
2563 | math-intrinsics@1.1.0: {}
2564 |
2565 | media-typer@0.3.0: {}
2566 |
2567 | merge-stream@2.0.0: {}
2568 |
2569 | mime-db@1.52.0: {}
2570 |
2571 | mime-types@2.1.35:
2572 | dependencies:
2573 | mime-db: 1.52.0
2574 |
2575 | mimic-fn@2.1.0: {}
2576 |
2577 | minimatch@9.0.5:
2578 | dependencies:
2579 | brace-expansion: 2.0.1
2580 |
2581 | minimist@1.2.8: {}
2582 |
2583 | minipass@7.1.2: {}
2584 |
2585 | mkdirp@0.5.6:
2586 | dependencies:
2587 | minimist: 1.2.8
2588 |
2589 | ms@2.1.3: {}
2590 |
2591 | multer@1.4.5-lts.1:
2592 | dependencies:
2593 | append-field: 1.0.0
2594 | busboy: 1.6.0
2595 | concat-stream: 1.6.2
2596 | mkdirp: 0.5.6
2597 | object-assign: 4.1.1
2598 | type-is: 1.6.18
2599 | xtend: 4.0.2
2600 |
2601 | mz@2.7.0:
2602 | dependencies:
2603 | any-promise: 1.3.0
2604 | object-assign: 4.1.1
2605 | thenify-all: 1.6.0
2606 |
2607 | nanoid@3.3.7: {}
2608 |
2609 | nanoid@5.0.8: {}
2610 |
2611 | negotiator@0.6.3: {}
2612 |
2613 | node-domexception@1.0.0: {}
2614 |
2615 | node-fetch@3.3.2:
2616 | dependencies:
2617 | data-uri-to-buffer: 4.0.1
2618 | fetch-blob: 3.2.0
2619 | formdata-polyfill: 4.0.10
2620 |
2621 | normalize-path@3.0.0: {}
2622 |
2623 | npm-run-path@4.0.1:
2624 | dependencies:
2625 | path-key: 3.1.1
2626 |
2627 | object-assign@4.1.1: {}
2628 |
2629 | object-inspect@1.13.4: {}
2630 |
2631 | on-finished@2.4.1:
2632 | dependencies:
2633 | ee-first: 1.1.1
2634 |
2635 | once@1.4.0:
2636 | dependencies:
2637 | wrappy: 1.0.2
2638 |
2639 | onetime@5.1.2:
2640 | dependencies:
2641 | mimic-fn: 2.1.0
2642 |
2643 | only@0.0.2: {}
2644 |
2645 | package-json-from-dist@1.0.0: {}
2646 |
2647 | parseurl@1.3.3: {}
2648 |
2649 | path-key@3.1.1: {}
2650 |
2651 | path-scurry@1.11.1:
2652 | dependencies:
2653 | lru-cache: 10.4.3
2654 | minipass: 7.1.2
2655 |
2656 | path-to-regexp@6.3.0: {}
2657 |
2658 | path-to-regexp@8.2.0: {}
2659 |
2660 | picocolors@1.1.0: {}
2661 |
2662 | picomatch@2.3.1: {}
2663 |
2664 | picomatch@4.0.2: {}
2665 |
2666 | pirates@4.0.6: {}
2667 |
2668 | postcss-load-config@6.0.1(postcss@8.4.47):
2669 | dependencies:
2670 | lilconfig: 3.1.2
2671 | optionalDependencies:
2672 | postcss: 8.4.47
2673 |
2674 | postcss@8.4.47:
2675 | dependencies:
2676 | nanoid: 3.3.7
2677 | picocolors: 1.1.0
2678 | source-map-js: 1.2.1
2679 |
2680 | prettier@3.3.3: {}
2681 |
2682 | process-nextick-args@2.0.1: {}
2683 |
2684 | punycode@2.3.1: {}
2685 |
2686 | qs@6.14.0:
2687 | dependencies:
2688 | side-channel: 1.1.0
2689 |
2690 | raw-body@2.5.2:
2691 | dependencies:
2692 | bytes: 3.1.2
2693 | http-errors: 2.0.0
2694 | iconv-lite: 0.4.24
2695 | unpipe: 1.0.0
2696 |
2697 | rcon@1.1.0: {}
2698 |
2699 | readable-stream@2.3.8:
2700 | dependencies:
2701 | core-util-is: 1.0.3
2702 | inherits: 2.0.4
2703 | isarray: 1.0.0
2704 | process-nextick-args: 2.0.1
2705 | safe-buffer: 5.1.2
2706 | string_decoder: 1.1.1
2707 | util-deprecate: 1.0.2
2708 |
2709 | readdirp@3.6.0:
2710 | dependencies:
2711 | picomatch: 2.3.1
2712 |
2713 | resolve-from@5.0.0: {}
2714 |
2715 | rollup@4.22.0:
2716 | dependencies:
2717 | '@types/estree': 1.0.5
2718 | optionalDependencies:
2719 | '@rollup/rollup-android-arm-eabi': 4.22.0
2720 | '@rollup/rollup-android-arm64': 4.22.0
2721 | '@rollup/rollup-darwin-arm64': 4.22.0
2722 | '@rollup/rollup-darwin-x64': 4.22.0
2723 | '@rollup/rollup-linux-arm-gnueabihf': 4.22.0
2724 | '@rollup/rollup-linux-arm-musleabihf': 4.22.0
2725 | '@rollup/rollup-linux-arm64-gnu': 4.22.0
2726 | '@rollup/rollup-linux-arm64-musl': 4.22.0
2727 | '@rollup/rollup-linux-powerpc64le-gnu': 4.22.0
2728 | '@rollup/rollup-linux-riscv64-gnu': 4.22.0
2729 | '@rollup/rollup-linux-s390x-gnu': 4.22.0
2730 | '@rollup/rollup-linux-x64-gnu': 4.22.0
2731 | '@rollup/rollup-linux-x64-musl': 4.22.0
2732 | '@rollup/rollup-win32-arm64-msvc': 4.22.0
2733 | '@rollup/rollup-win32-ia32-msvc': 4.22.0
2734 | '@rollup/rollup-win32-x64-msvc': 4.22.0
2735 | fsevents: 2.3.3
2736 |
2737 | safe-buffer@5.1.2: {}
2738 |
2739 | safe-buffer@5.2.1: {}
2740 |
2741 | safe-regex-test@1.1.0:
2742 | dependencies:
2743 | call-bound: 1.0.3
2744 | es-errors: 1.3.0
2745 | is-regex: 1.2.1
2746 |
2747 | safer-buffer@2.1.2: {}
2748 |
2749 | setprototypeof@1.2.0: {}
2750 |
2751 | shebang-command@2.0.0:
2752 | dependencies:
2753 | shebang-regex: 3.0.0
2754 |
2755 | shebang-regex@3.0.0: {}
2756 |
2757 | side-channel-list@1.0.0:
2758 | dependencies:
2759 | es-errors: 1.3.0
2760 | object-inspect: 1.13.4
2761 |
2762 | side-channel-map@1.0.1:
2763 | dependencies:
2764 | call-bound: 1.0.3
2765 | es-errors: 1.3.0
2766 | get-intrinsic: 1.2.7
2767 | object-inspect: 1.13.4
2768 |
2769 | side-channel-weakmap@1.0.2:
2770 | dependencies:
2771 | call-bound: 1.0.3
2772 | es-errors: 1.3.0
2773 | get-intrinsic: 1.2.7
2774 | object-inspect: 1.13.4
2775 | side-channel-map: 1.0.1
2776 |
2777 | side-channel@1.1.0:
2778 | dependencies:
2779 | es-errors: 1.3.0
2780 | object-inspect: 1.13.4
2781 | side-channel-list: 1.0.0
2782 | side-channel-map: 1.0.1
2783 | side-channel-weakmap: 1.0.2
2784 |
2785 | signal-exit@3.0.7: {}
2786 |
2787 | signal-exit@4.1.0: {}
2788 |
2789 | source-map-js@1.2.1: {}
2790 |
2791 | source-map@0.8.0-beta.0:
2792 | dependencies:
2793 | whatwg-url: 7.1.0
2794 |
2795 | statuses@1.5.0: {}
2796 |
2797 | statuses@2.0.1: {}
2798 |
2799 | streamsearch@1.1.0: {}
2800 |
2801 | string-width@4.2.3:
2802 | dependencies:
2803 | emoji-regex: 8.0.0
2804 | is-fullwidth-code-point: 3.0.0
2805 | strip-ansi: 6.0.1
2806 |
2807 | string-width@5.1.2:
2808 | dependencies:
2809 | eastasianwidth: 0.2.0
2810 | emoji-regex: 9.2.2
2811 | strip-ansi: 7.1.0
2812 |
2813 | string_decoder@1.1.1:
2814 | dependencies:
2815 | safe-buffer: 5.1.2
2816 |
2817 | strip-ansi@6.0.1:
2818 | dependencies:
2819 | ansi-regex: 5.0.1
2820 |
2821 | strip-ansi@7.1.0:
2822 | dependencies:
2823 | ansi-regex: 6.1.0
2824 |
2825 | strip-final-newline@2.0.0: {}
2826 |
2827 | sucrase@3.35.0:
2828 | dependencies:
2829 | '@jridgewell/gen-mapping': 0.3.5
2830 | commander: 4.1.1
2831 | glob: 10.4.5
2832 | lines-and-columns: 1.2.4
2833 | mz: 2.7.0
2834 | pirates: 4.0.6
2835 | ts-interface-checker: 0.1.13
2836 |
2837 | thenify-all@1.6.0:
2838 | dependencies:
2839 | thenify: 3.3.1
2840 |
2841 | thenify@3.3.1:
2842 | dependencies:
2843 | any-promise: 1.3.0
2844 |
2845 | tinyglobby@0.2.6:
2846 | dependencies:
2847 | fdir: 6.3.0(picomatch@4.0.2)
2848 | picomatch: 4.0.2
2849 |
2850 | to-regex-range@5.0.1:
2851 | dependencies:
2852 | is-number: 7.0.0
2853 |
2854 | toidentifier@1.0.1: {}
2855 |
2856 | tr46@1.0.1:
2857 | dependencies:
2858 | punycode: 2.3.1
2859 |
2860 | tree-kill@1.2.2: {}
2861 |
2862 | ts-interface-checker@0.1.13: {}
2863 |
2864 | tsscmp@1.0.6: {}
2865 |
2866 | tsup@8.3.0(postcss@8.4.47)(typescript@5.6.2):
2867 | dependencies:
2868 | bundle-require: 5.0.0(esbuild@0.23.1)
2869 | cac: 6.7.14
2870 | chokidar: 3.6.0
2871 | consola: 3.2.3
2872 | debug: 4.3.7
2873 | esbuild: 0.23.1
2874 | execa: 5.1.1
2875 | joycon: 3.1.1
2876 | picocolors: 1.1.0
2877 | postcss-load-config: 6.0.1(postcss@8.4.47)
2878 | resolve-from: 5.0.0
2879 | rollup: 4.22.0
2880 | source-map: 0.8.0-beta.0
2881 | sucrase: 3.35.0
2882 | tinyglobby: 0.2.6
2883 | tree-kill: 1.2.2
2884 | optionalDependencies:
2885 | postcss: 8.4.47
2886 | typescript: 5.6.2
2887 | transitivePeerDependencies:
2888 | - jiti
2889 | - supports-color
2890 | - tsx
2891 | - yaml
2892 |
2893 | turbo-darwin-64@2.1.2:
2894 | optional: true
2895 |
2896 | turbo-darwin-arm64@2.1.2:
2897 | optional: true
2898 |
2899 | turbo-linux-64@2.1.2:
2900 | optional: true
2901 |
2902 | turbo-linux-arm64@2.1.2:
2903 | optional: true
2904 |
2905 | turbo-windows-64@2.1.2:
2906 | optional: true
2907 |
2908 | turbo-windows-arm64@2.1.2:
2909 | optional: true
2910 |
2911 | turbo@2.1.2:
2912 | optionalDependencies:
2913 | turbo-darwin-64: 2.1.2
2914 | turbo-darwin-arm64: 2.1.2
2915 | turbo-linux-64: 2.1.2
2916 | turbo-linux-arm64: 2.1.2
2917 | turbo-windows-64: 2.1.2
2918 | turbo-windows-arm64: 2.1.2
2919 |
2920 | type-is@1.6.18:
2921 | dependencies:
2922 | media-typer: 0.3.0
2923 | mime-types: 2.1.35
2924 |
2925 | typedarray@0.0.6: {}
2926 |
2927 | typescript@5.6.2: {}
2928 |
2929 | undici-types@6.19.8: {}
2930 |
2931 | unpipe@1.0.0: {}
2932 |
2933 | util-deprecate@1.0.2: {}
2934 |
2935 | vary@1.1.2: {}
2936 |
2937 | vite@5.4.6(@types/node@22.8.6):
2938 | dependencies:
2939 | esbuild: 0.21.5
2940 | postcss: 8.4.47
2941 | rollup: 4.22.0
2942 | optionalDependencies:
2943 | '@types/node': 22.8.6
2944 | fsevents: 2.3.3
2945 |
2946 | web-streams-polyfill@3.3.3: {}
2947 |
2948 | webidl-conversions@4.0.2: {}
2949 |
2950 | whatwg-url@7.1.0:
2951 | dependencies:
2952 | lodash.sortby: 4.7.0
2953 | tr46: 1.0.1
2954 | webidl-conversions: 4.0.2
2955 |
2956 | which@2.0.2:
2957 | dependencies:
2958 | isexe: 2.0.0
2959 |
2960 | wrap-ansi@7.0.0:
2961 | dependencies:
2962 | ansi-styles: 4.3.0
2963 | string-width: 4.2.3
2964 | strip-ansi: 6.0.1
2965 |
2966 | wrap-ansi@8.1.0:
2967 | dependencies:
2968 | ansi-styles: 6.2.1
2969 | string-width: 5.1.2
2970 | strip-ansi: 7.1.0
2971 |
2972 | wrappy@1.0.2: {}
2973 |
2974 | xtend@4.0.2: {}
2975 |
2976 | ylru@1.4.0: {}
2977 |
2978 | zod@3.24.2: {}
2979 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 | - 'game/**'
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "tasks": {
4 | "build": {
5 | "dependsOn": ["^build"]
6 | },
7 | "dev": {
8 | "persistent": true,
9 | "cache": false
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------