├── .eslintrc ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .luaurc ├── .prettierrc ├── LICENSE.md ├── README.md ├── default.project.json ├── dev.project.json ├── images └── logo.png ├── package.json ├── pnpm-lock.yaml ├── rokit.toml ├── scripts ├── check.sh └── install.sh ├── selene.toml ├── src ├── React.luau ├── Reflex.luau ├── components │ ├── ReflexContext.luau │ └── ReflexProvider.luau ├── hooks │ ├── useProducer.luau │ ├── useSelector.luau │ └── useSelectorCreator.luau ├── index.d.ts └── init.luau ├── tsconfig.json ├── wally.lock └── wally.toml /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "jsx": true, 5 | "useJSXTextNode": true, 6 | "ecmaVersion": 2018, 7 | "sourceType": "module", 8 | "project": "./tsconfig.json" 9 | }, 10 | "plugins": [ 11 | "@typescript-eslint", 12 | "roblox-ts", 13 | "prettier" 14 | ], 15 | "extends": [ 16 | "eslint:recommended", 17 | "plugin:@typescript-eslint/recommended", 18 | "plugin:roblox-ts/recommended", 19 | "plugin:prettier/recommended" 20 | ], 21 | "rules": { 22 | "prettier/prettier": "warn", 23 | "@typescript-eslint/no-explicit-any": "off", 24 | "@typescript-eslint/no-unsafe-declaration-merging": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | analyze: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: pnpm/action-setup@v3 18 | with: 19 | version: 8.15.1 20 | - uses: CompeyDev/setup-rokit@v0.1.2 21 | 22 | - name: Install dependencies 23 | run: | 24 | wally install 25 | rojo sourcemap dev.project.json --output sourcemap.json 26 | wally-package-types --sourcemap sourcemap.json Packages 27 | pnpm install 28 | 29 | - name: Download global Roblox types 30 | run: curl -o scripts/roblox.d.lua https://raw.githubusercontent.com/JohnnyMorganz/luau-lsp/main/scripts/globalTypes.d.lua 31 | 32 | - name: Analyze 33 | run: luau-lsp analyze --defs=scripts/roblox.d.lua --sourcemap=sourcemap.json --ignore="**/_Index/**" src 34 | 35 | - name: Check code quality 36 | run: | 37 | selene src 38 | stylua --check src 39 | pnpm eslint src 40 | 41 | - name: Build model 42 | run: rojo build -o react-reflex.rbxm 43 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [published] 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: CompeyDev/setup-rokit@v0.1.2 14 | 15 | - name: Install dependencies 16 | run: wally install 17 | 18 | - name: Build model 19 | run: rojo build -o react-reflex.rbxm 20 | 21 | - uses: AButler/upload-release-assets@v3.0 22 | with: 23 | files: "react-reflex.rbxm" 24 | repo-token: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /node_modules 3 | /Packages 4 | /sourcemap.json 5 | *.tsbuildinfo 6 | *.tgz 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.luaurc: -------------------------------------------------------------------------------- 1 | { 2 | "languageMode": "strict" 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 2, 4 | "trailingComma": "all", 5 | "useTabs": true 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2024 Littensy 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

3 | Logo 4 |

5 |

React Reflex

6 |

7 | An all-in-one state container. 8 |
9 | npm package → 10 |

11 |

12 | 13 |
14 | 15 | ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/littensy/react-reflex/ci.yml?style=for-the-badge&branch=master&logo=github) 16 | [![NPM Version](https://img.shields.io/npm/v/@rbxts/react-reflex.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@rbxts/react-reflex) 17 | [![GitHub License](https://img.shields.io/github/license/littensy/react-reflex?style=for-the-badge)](LICENSE.md) 18 | 19 |
20 | 21 | **Reflex** is a simple state container inspired by [Rodux](https://github.com/roblox/rodux) and [Silo](https://github.com/sleitnick/rbxts-silo), designed to be an all-in-one solution for managing and reacting to state in Roblox games. 22 | 23 | **React Reflex** provides React hooks and components for Reflex using either [`@rbxts/react`](https://github.com/littensy/rbxts-react) or [`jsdotlua/react`](https://github.com/jsdotlua/react-lua). 24 | 25 | See the [React Reflex documentation](https://littensy.github.io/reflex/docs/guides/roact-reflex/) for more information. 26 | 27 | ## 📦 Setup 28 | 29 | ### TypeScript 30 | 31 | Install the `@rbxts/react-reflex` package using your package manager of choice. 32 | 33 | ```sh 34 | npm install @rbxts/react-reflex 35 | yarn add @rbxts/react-reflex 36 | pnpm add @rbxts/react-reflex 37 | ``` 38 | 39 | ### Wally 40 | 41 | Add `littensy/react-reflex` to your `wally.toml` file. 42 | 43 | ```toml 44 | [dependencies] 45 | ReactReflex = "littensy/react-reflex@VERSION" 46 | ``` 47 | 48 | ## 🚀 Examples 49 | 50 | ### Mounting your app 51 | 52 | Use `` to enable Reflex hooks and components: 53 | 54 | ```tsx 55 | import React, { StrictMode } from "@rbxts/react"; 56 | import { createPortal, createRoot } from "@rbxts/react-roblox"; 57 | import { ReflexProvider } from "@rbxts/react-reflex"; 58 | 59 | const root = createRoot(new Instance("Folder")); 60 | 61 | root.render( 62 | 63 | 64 | {/* Your app */} 65 | {createPortal(, playerGui)} 66 | 67 | , 68 | ); 69 | ``` 70 | 71 | ### Typed hooks 72 | 73 | Custom hooks can be created to provide typed hooks for your state: 74 | 75 | ```tsx 76 | import { useProducer, useSelector, UseProducerHook, UseSelectorHook } from "@rbxts/react-reflex"; 77 | 78 | export const useRootProducer: UseProducerHook = useProducer; 79 | export const useRootSelector: UseSelectorHook = useSelector; 80 | ``` 81 | 82 | ### Counter 83 | 84 | ```tsx 85 | import React from "@rbxts/react"; 86 | import { useRootProducer, useRootSelector } from "./hooks"; 87 | 88 | export function Counter() { 89 | const producer = useRootProducer(); 90 | const count = useRootSelector((state) => state.count); 91 | 92 | return ( 93 | producer.increment(), 100 | MouseButton2Click: () => producer.decrement(), 101 | }} 102 | /> 103 | ); 104 | } 105 | ``` 106 | 107 | ## 📚 Resources 108 | 109 | - [Reflex Documentation](https://littensy.github.io/reflex/) - Learn about Reflex's core concepts and API 110 | - [Reflex Repository](https://github.com/littensy/reflex) - The official Reflex repository 111 | - [React Lua Documentation](https://jsdotlua.github.io/react-lua/) - A comprehensive guide for the differences between Roact and React 112 | 113 | ## 📝 License 114 | 115 | This project is licensed under the [MIT license](LICENSE). 116 | -------------------------------------------------------------------------------- /default.project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-reflex", 3 | "tree": { 4 | "$path": "src" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /dev.project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-reflex-dev", 3 | "tree": { 4 | "$className": "DataModel", 5 | "ReplicatedStorage": { 6 | "$className": "ReplicatedStorage", 7 | "Packages": { 8 | "$path": "Packages", 9 | "react": { "$path": "Packages/React.lua" }, 10 | "reflex": { 11 | "$className": "Folder", 12 | "_Index": { "$path": "Packages/_Index" }, 13 | "src": { "$path": "Packages/Reflex.lua" } 14 | }, 15 | "react-reflex": { "$path": "src" } 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littensy/react-reflex/4b3fd1a36f35d3ffcb5df3fe1fe4a7bb3f8114a4/images/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rbxts/react-reflex", 3 | "version": "0.3.7", 4 | "description": "React bindings for Reflex", 5 | "scripts": { 6 | "lint": "sh scripts/check.sh" 7 | }, 8 | "main": "src/init.lua", 9 | "types": "src/index.d.ts", 10 | "keywords": [ 11 | "roblox", 12 | "typescript", 13 | "roblox-ts", 14 | "redux" 15 | ], 16 | "author": "littensy", 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/littensy/react-reflex" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/littensy/react-reflex/issues" 24 | }, 25 | "homepage": "https://littensy.github.io/reflex", 26 | "files": [ 27 | "src", 28 | "default.project.json" 29 | ], 30 | "publishConfig": { 31 | "access": "public" 32 | }, 33 | "devDependencies": { 34 | "@rbxts/compiler-types": "2.3.0-types.0", 35 | "@rbxts/react": "^0.3.6", 36 | "@rbxts/reflex": "^4.3.1", 37 | "@rbxts/types": "^1.0.852", 38 | "@typescript-eslint/eslint-plugin": "^8.32.1", 39 | "@typescript-eslint/parser": "^8.32.1", 40 | "eslint": "^8.57.1", 41 | "eslint-config-prettier": "^9.1.0", 42 | "eslint-plugin-prettier": "^5.4.0", 43 | "eslint-plugin-roblox-ts": "^0.0.36", 44 | "prettier": "^3.5.3", 45 | "roblox-ts": "^3.0.0", 46 | "typescript": "^5.8.3" 47 | }, 48 | "peerDependencies": { 49 | "@rbxts/react": "*", 50 | "@rbxts/reflex": "*" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | '@rbxts/compiler-types': 12 | specifier: 2.3.0-types.0 13 | version: 2.3.0-types.0 14 | '@rbxts/react': 15 | specifier: ^0.3.6 16 | version: 0.3.6 17 | '@rbxts/reflex': 18 | specifier: ^4.3.1 19 | version: 4.3.1 20 | '@rbxts/types': 21 | specifier: ^1.0.852 22 | version: 1.0.852 23 | '@typescript-eslint/eslint-plugin': 24 | specifier: ^8.32.1 25 | version: 8.32.1(@typescript-eslint/parser@8.32.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) 26 | '@typescript-eslint/parser': 27 | specifier: ^8.32.1 28 | version: 8.32.1(eslint@8.57.1)(typescript@5.8.3) 29 | eslint: 30 | specifier: ^8.57.1 31 | version: 8.57.1 32 | eslint-config-prettier: 33 | specifier: ^9.1.0 34 | version: 9.1.0(eslint@8.57.1) 35 | eslint-plugin-prettier: 36 | specifier: ^5.4.0 37 | version: 5.4.0(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.5.3) 38 | eslint-plugin-roblox-ts: 39 | specifier: ^0.0.36 40 | version: 0.0.36(eslint@8.57.1) 41 | prettier: 42 | specifier: ^3.5.3 43 | version: 3.5.3 44 | roblox-ts: 45 | specifier: ^3.0.0 46 | version: 3.0.0 47 | typescript: 48 | specifier: ^5.8.3 49 | version: 5.8.3 50 | 51 | packages: 52 | 53 | '@eslint-community/eslint-utils@4.7.0': 54 | resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} 55 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 56 | peerDependencies: 57 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 58 | 59 | '@eslint-community/regexpp@4.12.1': 60 | resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 61 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 62 | 63 | '@eslint/eslintrc@2.1.4': 64 | resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} 65 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 66 | 67 | '@eslint/js@8.57.1': 68 | resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} 69 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 70 | 71 | '@humanwhocodes/config-array@0.13.0': 72 | resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} 73 | engines: {node: '>=10.10.0'} 74 | deprecated: Use @eslint/config-array instead 75 | 76 | '@humanwhocodes/module-importer@1.0.1': 77 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 78 | engines: {node: '>=12.22'} 79 | 80 | '@humanwhocodes/object-schema@2.0.3': 81 | resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} 82 | deprecated: Use @eslint/object-schema instead 83 | 84 | '@nodelib/fs.scandir@2.1.5': 85 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 86 | engines: {node: '>= 8'} 87 | 88 | '@nodelib/fs.stat@2.0.5': 89 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 90 | engines: {node: '>= 8'} 91 | 92 | '@nodelib/fs.walk@1.2.8': 93 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 94 | engines: {node: '>= 8'} 95 | 96 | '@pkgr/core@0.2.4': 97 | resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} 98 | engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} 99 | 100 | '@rbxts/compiler-types@2.3.0-types.0': 101 | resolution: {integrity: sha512-2kllUXLlK22OzSi3GmLT+/O70U9oB2iXp4rGFk5FLwc1pqf4W9EsInuJ0t7poLE2XnqnpW/ojff9CUNivI2+lw==} 102 | 103 | '@rbxts/react-vendor@0.3.6': 104 | resolution: {integrity: sha512-q3HilP6ZNHSgWW0lwka+Ft4Iq+fnPBppOeQhGua1XCtM2hEqhmUmME8DI1UlnaK/aGzdYW1bWC7YfHZhHGsIeA==} 105 | 106 | '@rbxts/react@0.3.6': 107 | resolution: {integrity: sha512-GeEqKjjyJT3zG85xEVCu3IMQdYRoXk4P9XCua4oriTIfuJaSTOWUukOmQ5ILpG/BpksLqXlpH8zqKKZcZaIs3g==} 108 | 109 | '@rbxts/reflex@4.3.1': 110 | resolution: {integrity: sha512-S5MbEpHKeRh9NWhwGJ789WbUsmlAlpQziWaNK4+kz1EpaaQ7uHQMZAuN1DYl4+QkqmOSuPlj04COwmArBGWH1Q==} 111 | 112 | '@rbxts/types@1.0.852': 113 | resolution: {integrity: sha512-OMbUGxZwuTMvagMbxCkCtHzSGiK06NWUJxi7OlwtL2f0scVbpzVFkclcHNYkP1TeXmlW1KSTVUa0AGYeIdStag==} 114 | 115 | '@roblox-ts/luau-ast@2.0.0': 116 | resolution: {integrity: sha512-cmMi093IdwBOLVxwuordhM8AmtbyTIyRpsTbB0D/JauidW4SXsQRQowSwWjHo4QP0DRJBXvOIlxtqEQi50uNzQ==} 117 | 118 | '@roblox-ts/path-translator@1.1.0': 119 | resolution: {integrity: sha512-D0akTmnNYqBw+ZIek5JxocT3BjmbgGOuOy0x1nIIxHBPNLGCpzseToY8jyYs/0mlvnN2xnSP/k8Tv+jvGOQSwQ==} 120 | 121 | '@roblox-ts/rojo-resolver@1.1.0': 122 | resolution: {integrity: sha512-QmvVryu1EeME+3QUoG5j/gHGJoJUaffCgZ92mhlG7cJSd1uyhgpY4CNWriZAwZJYkTlzd5Htkpn+18yDFbOFXA==} 123 | 124 | '@types/json-schema@7.0.15': 125 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 126 | 127 | '@types/node@20.17.46': 128 | resolution: {integrity: sha512-0PQHLhZPWOxGW4auogW0eOQAuNIlCYvibIpG67ja0TOJ6/sehu+1en7sfceUn+QQtx4Rk3GxbLNwPh0Cav7TWw==} 129 | 130 | '@types/semver@7.7.0': 131 | resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} 132 | 133 | '@typescript-eslint/eslint-plugin@8.32.1': 134 | resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==} 135 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 136 | peerDependencies: 137 | '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 138 | eslint: ^8.57.0 || ^9.0.0 139 | typescript: '>=4.8.4 <5.9.0' 140 | 141 | '@typescript-eslint/experimental-utils@5.62.0': 142 | resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} 143 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 144 | peerDependencies: 145 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 146 | 147 | '@typescript-eslint/parser@8.32.1': 148 | resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==} 149 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 150 | peerDependencies: 151 | eslint: ^8.57.0 || ^9.0.0 152 | typescript: '>=4.8.4 <5.9.0' 153 | 154 | '@typescript-eslint/scope-manager@5.62.0': 155 | resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} 156 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 157 | 158 | '@typescript-eslint/scope-manager@8.32.1': 159 | resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==} 160 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 161 | 162 | '@typescript-eslint/type-utils@8.32.1': 163 | resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==} 164 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 165 | peerDependencies: 166 | eslint: ^8.57.0 || ^9.0.0 167 | typescript: '>=4.8.4 <5.9.0' 168 | 169 | '@typescript-eslint/types@5.62.0': 170 | resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} 171 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 172 | 173 | '@typescript-eslint/types@8.32.1': 174 | resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==} 175 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 176 | 177 | '@typescript-eslint/typescript-estree@5.62.0': 178 | resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} 179 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 180 | peerDependencies: 181 | typescript: '*' 182 | peerDependenciesMeta: 183 | typescript: 184 | optional: true 185 | 186 | '@typescript-eslint/typescript-estree@8.32.1': 187 | resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==} 188 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 189 | peerDependencies: 190 | typescript: '>=4.8.4 <5.9.0' 191 | 192 | '@typescript-eslint/utils@5.62.0': 193 | resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} 194 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 195 | peerDependencies: 196 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 197 | 198 | '@typescript-eslint/utils@8.32.1': 199 | resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==} 200 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 201 | peerDependencies: 202 | eslint: ^8.57.0 || ^9.0.0 203 | typescript: '>=4.8.4 <5.9.0' 204 | 205 | '@typescript-eslint/visitor-keys@5.62.0': 206 | resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} 207 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 208 | 209 | '@typescript-eslint/visitor-keys@8.32.1': 210 | resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==} 211 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 212 | 213 | '@ungap/structured-clone@1.3.0': 214 | resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} 215 | 216 | acorn-jsx@5.3.2: 217 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 218 | peerDependencies: 219 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 220 | 221 | acorn@8.14.1: 222 | resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 223 | engines: {node: '>=0.4.0'} 224 | hasBin: true 225 | 226 | ajv@6.12.6: 227 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 228 | 229 | ajv@8.17.1: 230 | resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} 231 | 232 | ansi-regex@5.0.1: 233 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 234 | engines: {node: '>=8'} 235 | 236 | ansi-styles@4.3.0: 237 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 238 | engines: {node: '>=8'} 239 | 240 | anymatch@3.1.3: 241 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 242 | engines: {node: '>= 8'} 243 | 244 | argparse@2.0.1: 245 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 246 | 247 | array-union@2.1.0: 248 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 249 | engines: {node: '>=8'} 250 | 251 | balanced-match@1.0.2: 252 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 253 | 254 | binary-extensions@2.3.0: 255 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 256 | engines: {node: '>=8'} 257 | 258 | brace-expansion@1.1.11: 259 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 260 | 261 | brace-expansion@2.0.1: 262 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 263 | 264 | braces@3.0.3: 265 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 266 | engines: {node: '>=8'} 267 | 268 | callsites@3.1.0: 269 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 270 | engines: {node: '>=6'} 271 | 272 | chalk@4.1.2: 273 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 274 | engines: {node: '>=10'} 275 | 276 | chokidar@3.6.0: 277 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 278 | engines: {node: '>= 8.10.0'} 279 | 280 | cliui@8.0.1: 281 | resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} 282 | engines: {node: '>=12'} 283 | 284 | color-convert@2.0.1: 285 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 286 | engines: {node: '>=7.0.0'} 287 | 288 | color-name@1.1.4: 289 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 290 | 291 | concat-map@0.0.1: 292 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 293 | 294 | cross-spawn@7.0.6: 295 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 296 | engines: {node: '>= 8'} 297 | 298 | debug@4.4.1: 299 | resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 300 | engines: {node: '>=6.0'} 301 | peerDependencies: 302 | supports-color: '*' 303 | peerDependenciesMeta: 304 | supports-color: 305 | optional: true 306 | 307 | deep-is@0.1.4: 308 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 309 | 310 | dir-glob@3.0.1: 311 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 312 | engines: {node: '>=8'} 313 | 314 | doctrine@3.0.0: 315 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 316 | engines: {node: '>=6.0.0'} 317 | 318 | emoji-regex@8.0.0: 319 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 320 | 321 | escalade@3.2.0: 322 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 323 | engines: {node: '>=6'} 324 | 325 | escape-string-regexp@4.0.0: 326 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 327 | engines: {node: '>=10'} 328 | 329 | eslint-config-prettier@9.1.0: 330 | resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} 331 | hasBin: true 332 | peerDependencies: 333 | eslint: '>=7.0.0' 334 | 335 | eslint-plugin-prettier@5.4.0: 336 | resolution: {integrity: sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==} 337 | engines: {node: ^14.18.0 || >=16.0.0} 338 | peerDependencies: 339 | '@types/eslint': '>=8.0.0' 340 | eslint: '>=8.0.0' 341 | eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' 342 | prettier: '>=3.0.0' 343 | peerDependenciesMeta: 344 | '@types/eslint': 345 | optional: true 346 | eslint-config-prettier: 347 | optional: true 348 | 349 | eslint-plugin-roblox-ts@0.0.36: 350 | resolution: {integrity: sha512-vlbgfHY1heWSyDunVX3gIOamCy28KqrJlDkmuDOyYVBo8uLqdvbFkbWkdGxn59Vky1m6pFcvZGU6TObfmwm5Pg==} 351 | engines: {node: '>=0.10.0'} 352 | 353 | eslint-scope@5.1.1: 354 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 355 | engines: {node: '>=8.0.0'} 356 | 357 | eslint-scope@7.2.2: 358 | resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} 359 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 360 | 361 | eslint-visitor-keys@3.4.3: 362 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 363 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 364 | 365 | eslint-visitor-keys@4.2.0: 366 | resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 367 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 368 | 369 | eslint@8.57.1: 370 | resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} 371 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 372 | deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. 373 | hasBin: true 374 | 375 | espree@9.6.1: 376 | resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} 377 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 378 | 379 | esquery@1.6.0: 380 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 381 | engines: {node: '>=0.10'} 382 | 383 | esrecurse@4.3.0: 384 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 385 | engines: {node: '>=4.0'} 386 | 387 | estraverse@4.3.0: 388 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 389 | engines: {node: '>=4.0'} 390 | 391 | estraverse@5.3.0: 392 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 393 | engines: {node: '>=4.0'} 394 | 395 | esutils@2.0.3: 396 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 397 | engines: {node: '>=0.10.0'} 398 | 399 | fast-deep-equal@3.1.3: 400 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 401 | 402 | fast-diff@1.3.0: 403 | resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} 404 | 405 | fast-glob@3.3.3: 406 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 407 | engines: {node: '>=8.6.0'} 408 | 409 | fast-json-stable-stringify@2.1.0: 410 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 411 | 412 | fast-levenshtein@2.0.6: 413 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 414 | 415 | fast-uri@3.0.6: 416 | resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} 417 | 418 | fastq@1.19.1: 419 | resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 420 | 421 | file-entry-cache@6.0.1: 422 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 423 | engines: {node: ^10.12.0 || >=12.0.0} 424 | 425 | fill-range@7.1.1: 426 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 427 | engines: {node: '>=8'} 428 | 429 | find-up@5.0.0: 430 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 431 | engines: {node: '>=10'} 432 | 433 | flat-cache@3.2.0: 434 | resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} 435 | engines: {node: ^10.12.0 || >=12.0.0} 436 | 437 | flatted@3.3.3: 438 | resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 439 | 440 | fs-extra@11.3.0: 441 | resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} 442 | engines: {node: '>=14.14'} 443 | 444 | fs.realpath@1.0.0: 445 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 446 | 447 | fsevents@2.3.3: 448 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 449 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 450 | os: [darwin] 451 | 452 | function-bind@1.1.2: 453 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 454 | 455 | get-caller-file@2.0.5: 456 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 457 | engines: {node: 6.* || 8.* || >= 10.*} 458 | 459 | glob-parent@5.1.2: 460 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 461 | engines: {node: '>= 6'} 462 | 463 | glob-parent@6.0.2: 464 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 465 | engines: {node: '>=10.13.0'} 466 | 467 | glob@7.2.3: 468 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 469 | deprecated: Glob versions prior to v9 are no longer supported 470 | 471 | globals@13.24.0: 472 | resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} 473 | engines: {node: '>=8'} 474 | 475 | globby@11.1.0: 476 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 477 | engines: {node: '>=10'} 478 | 479 | graceful-fs@4.2.11: 480 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 481 | 482 | graphemer@1.4.0: 483 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 484 | 485 | has-flag@4.0.0: 486 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 487 | engines: {node: '>=8'} 488 | 489 | hasown@2.0.2: 490 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 491 | engines: {node: '>= 0.4'} 492 | 493 | ignore@5.3.2: 494 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 495 | engines: {node: '>= 4'} 496 | 497 | ignore@7.0.4: 498 | resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} 499 | engines: {node: '>= 4'} 500 | 501 | import-fresh@3.3.1: 502 | resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 503 | engines: {node: '>=6'} 504 | 505 | imurmurhash@0.1.4: 506 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 507 | engines: {node: '>=0.8.19'} 508 | 509 | inflight@1.0.6: 510 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 511 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 512 | 513 | inherits@2.0.4: 514 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 515 | 516 | is-binary-path@2.1.0: 517 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 518 | engines: {node: '>=8'} 519 | 520 | is-core-module@2.16.1: 521 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 522 | engines: {node: '>= 0.4'} 523 | 524 | is-extglob@2.1.1: 525 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 526 | engines: {node: '>=0.10.0'} 527 | 528 | is-fullwidth-code-point@3.0.0: 529 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 530 | engines: {node: '>=8'} 531 | 532 | is-glob@4.0.3: 533 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 534 | engines: {node: '>=0.10.0'} 535 | 536 | is-number@7.0.0: 537 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 538 | engines: {node: '>=0.12.0'} 539 | 540 | is-path-inside@3.0.3: 541 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 542 | engines: {node: '>=8'} 543 | 544 | isexe@2.0.0: 545 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 546 | 547 | js-yaml@4.1.0: 548 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 549 | hasBin: true 550 | 551 | json-buffer@3.0.1: 552 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 553 | 554 | json-schema-traverse@0.4.1: 555 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 556 | 557 | json-schema-traverse@1.0.0: 558 | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 559 | 560 | json-stable-stringify-without-jsonify@1.0.1: 561 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 562 | 563 | jsonfile@6.1.0: 564 | resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} 565 | 566 | keyv@4.5.4: 567 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 568 | 569 | kleur@4.1.5: 570 | resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} 571 | engines: {node: '>=6'} 572 | 573 | levn@0.4.1: 574 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 575 | engines: {node: '>= 0.8.0'} 576 | 577 | locate-path@6.0.0: 578 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 579 | engines: {node: '>=10'} 580 | 581 | lodash.merge@4.6.2: 582 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 583 | 584 | merge2@1.4.1: 585 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 586 | engines: {node: '>= 8'} 587 | 588 | micromatch@4.0.8: 589 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 590 | engines: {node: '>=8.6'} 591 | 592 | minimatch@3.1.2: 593 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 594 | 595 | minimatch@9.0.5: 596 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 597 | engines: {node: '>=16 || 14 >=14.17'} 598 | 599 | ms@2.1.3: 600 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 601 | 602 | natural-compare@1.4.0: 603 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 604 | 605 | normalize-path@3.0.0: 606 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 607 | engines: {node: '>=0.10.0'} 608 | 609 | once@1.4.0: 610 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 611 | 612 | optionator@0.9.4: 613 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 614 | engines: {node: '>= 0.8.0'} 615 | 616 | p-limit@3.1.0: 617 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 618 | engines: {node: '>=10'} 619 | 620 | p-locate@5.0.0: 621 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 622 | engines: {node: '>=10'} 623 | 624 | parent-module@1.0.1: 625 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 626 | engines: {node: '>=6'} 627 | 628 | path-exists@4.0.0: 629 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 630 | engines: {node: '>=8'} 631 | 632 | path-is-absolute@1.0.1: 633 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 634 | engines: {node: '>=0.10.0'} 635 | 636 | path-key@3.1.1: 637 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 638 | engines: {node: '>=8'} 639 | 640 | path-parse@1.0.7: 641 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 642 | 643 | path-type@4.0.0: 644 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 645 | engines: {node: '>=8'} 646 | 647 | picomatch@2.3.1: 648 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 649 | engines: {node: '>=8.6'} 650 | 651 | prelude-ls@1.2.1: 652 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 653 | engines: {node: '>= 0.8.0'} 654 | 655 | prettier-linter-helpers@1.0.0: 656 | resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} 657 | engines: {node: '>=6.0.0'} 658 | 659 | prettier@3.5.3: 660 | resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} 661 | engines: {node: '>=14'} 662 | hasBin: true 663 | 664 | punycode@2.3.1: 665 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 666 | engines: {node: '>=6'} 667 | 668 | queue-microtask@1.2.3: 669 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 670 | 671 | readdirp@3.6.0: 672 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 673 | engines: {node: '>=8.10.0'} 674 | 675 | require-directory@2.1.1: 676 | resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 677 | engines: {node: '>=0.10.0'} 678 | 679 | require-from-string@2.0.2: 680 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 681 | engines: {node: '>=0.10.0'} 682 | 683 | resolve-from@4.0.0: 684 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 685 | engines: {node: '>=4'} 686 | 687 | resolve@1.22.10: 688 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} 689 | engines: {node: '>= 0.4'} 690 | hasBin: true 691 | 692 | reusify@1.1.0: 693 | resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 694 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 695 | 696 | rimraf@3.0.2: 697 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 698 | deprecated: Rimraf versions prior to v4 are no longer supported 699 | hasBin: true 700 | 701 | roblox-ts@3.0.0: 702 | resolution: {integrity: sha512-hwAC2frIFlLJOtHd6F+5opMEhBgfAMK9z5l1mP+bykLBbMO5cn1q5lIwhhXbeh9Pq07rlhF8uGHlmeRLPd/3AA==} 703 | hasBin: true 704 | 705 | run-parallel@1.2.0: 706 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 707 | 708 | semver@7.7.2: 709 | resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 710 | engines: {node: '>=10'} 711 | hasBin: true 712 | 713 | shebang-command@2.0.0: 714 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 715 | engines: {node: '>=8'} 716 | 717 | shebang-regex@3.0.0: 718 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 719 | engines: {node: '>=8'} 720 | 721 | slash@3.0.0: 722 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 723 | engines: {node: '>=8'} 724 | 725 | string-width@4.2.3: 726 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 727 | engines: {node: '>=8'} 728 | 729 | strip-ansi@6.0.1: 730 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 731 | engines: {node: '>=8'} 732 | 733 | strip-json-comments@3.1.1: 734 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 735 | engines: {node: '>=8'} 736 | 737 | supports-color@7.2.0: 738 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 739 | engines: {node: '>=8'} 740 | 741 | supports-preserve-symlinks-flag@1.0.0: 742 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 743 | engines: {node: '>= 0.4'} 744 | 745 | synckit@0.11.4: 746 | resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==} 747 | engines: {node: ^14.18.0 || >=16.0.0} 748 | 749 | text-table@0.2.0: 750 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 751 | 752 | to-regex-range@5.0.1: 753 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 754 | engines: {node: '>=8.0'} 755 | 756 | ts-api-utils@2.1.0: 757 | resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 758 | engines: {node: '>=18.12'} 759 | peerDependencies: 760 | typescript: '>=4.8.4' 761 | 762 | tslib@1.14.1: 763 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 764 | 765 | tslib@2.8.1: 766 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 767 | 768 | tsutils@3.21.0: 769 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 770 | engines: {node: '>= 6'} 771 | peerDependencies: 772 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 773 | 774 | type-check@0.4.0: 775 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 776 | engines: {node: '>= 0.8.0'} 777 | 778 | type-fest@0.20.2: 779 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 780 | engines: {node: '>=10'} 781 | 782 | typescript@5.5.3: 783 | resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} 784 | engines: {node: '>=14.17'} 785 | hasBin: true 786 | 787 | typescript@5.8.3: 788 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 789 | engines: {node: '>=14.17'} 790 | hasBin: true 791 | 792 | undici-types@6.19.8: 793 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 794 | 795 | universalify@2.0.1: 796 | resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} 797 | engines: {node: '>= 10.0.0'} 798 | 799 | uri-js@4.4.1: 800 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 801 | 802 | which@2.0.2: 803 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 804 | engines: {node: '>= 8'} 805 | hasBin: true 806 | 807 | word-wrap@1.2.5: 808 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 809 | engines: {node: '>=0.10.0'} 810 | 811 | wrap-ansi@7.0.0: 812 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 813 | engines: {node: '>=10'} 814 | 815 | wrappy@1.0.2: 816 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 817 | 818 | y18n@5.0.8: 819 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 820 | engines: {node: '>=10'} 821 | 822 | yargs-parser@21.1.1: 823 | resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 824 | engines: {node: '>=12'} 825 | 826 | yargs@17.7.2: 827 | resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} 828 | engines: {node: '>=12'} 829 | 830 | yocto-queue@0.1.0: 831 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 832 | engines: {node: '>=10'} 833 | 834 | snapshots: 835 | 836 | '@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)': 837 | dependencies: 838 | eslint: 8.57.1 839 | eslint-visitor-keys: 3.4.3 840 | 841 | '@eslint-community/regexpp@4.12.1': {} 842 | 843 | '@eslint/eslintrc@2.1.4': 844 | dependencies: 845 | ajv: 6.12.6 846 | debug: 4.4.1 847 | espree: 9.6.1 848 | globals: 13.24.0 849 | ignore: 5.3.2 850 | import-fresh: 3.3.1 851 | js-yaml: 4.1.0 852 | minimatch: 3.1.2 853 | strip-json-comments: 3.1.1 854 | transitivePeerDependencies: 855 | - supports-color 856 | 857 | '@eslint/js@8.57.1': {} 858 | 859 | '@humanwhocodes/config-array@0.13.0': 860 | dependencies: 861 | '@humanwhocodes/object-schema': 2.0.3 862 | debug: 4.4.1 863 | minimatch: 3.1.2 864 | transitivePeerDependencies: 865 | - supports-color 866 | 867 | '@humanwhocodes/module-importer@1.0.1': {} 868 | 869 | '@humanwhocodes/object-schema@2.0.3': {} 870 | 871 | '@nodelib/fs.scandir@2.1.5': 872 | dependencies: 873 | '@nodelib/fs.stat': 2.0.5 874 | run-parallel: 1.2.0 875 | 876 | '@nodelib/fs.stat@2.0.5': {} 877 | 878 | '@nodelib/fs.walk@1.2.8': 879 | dependencies: 880 | '@nodelib/fs.scandir': 2.1.5 881 | fastq: 1.19.1 882 | 883 | '@pkgr/core@0.2.4': {} 884 | 885 | '@rbxts/compiler-types@2.3.0-types.0': {} 886 | 887 | '@rbxts/react-vendor@0.3.6': {} 888 | 889 | '@rbxts/react@0.3.6': 890 | dependencies: 891 | '@rbxts/react-vendor': 0.3.6 892 | 893 | '@rbxts/reflex@4.3.1': {} 894 | 895 | '@rbxts/types@1.0.852': {} 896 | 897 | '@roblox-ts/luau-ast@2.0.0': {} 898 | 899 | '@roblox-ts/path-translator@1.1.0': 900 | dependencies: 901 | ajv: 8.17.1 902 | fs-extra: 11.3.0 903 | 904 | '@roblox-ts/rojo-resolver@1.1.0': 905 | dependencies: 906 | ajv: 8.17.1 907 | fs-extra: 11.3.0 908 | 909 | '@types/json-schema@7.0.15': {} 910 | 911 | '@types/node@20.17.46': 912 | dependencies: 913 | undici-types: 6.19.8 914 | 915 | '@types/semver@7.7.0': {} 916 | 917 | '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)': 918 | dependencies: 919 | '@eslint-community/regexpp': 4.12.1 920 | '@typescript-eslint/parser': 8.32.1(eslint@8.57.1)(typescript@5.8.3) 921 | '@typescript-eslint/scope-manager': 8.32.1 922 | '@typescript-eslint/type-utils': 8.32.1(eslint@8.57.1)(typescript@5.8.3) 923 | '@typescript-eslint/utils': 8.32.1(eslint@8.57.1)(typescript@5.8.3) 924 | '@typescript-eslint/visitor-keys': 8.32.1 925 | eslint: 8.57.1 926 | graphemer: 1.4.0 927 | ignore: 7.0.4 928 | natural-compare: 1.4.0 929 | ts-api-utils: 2.1.0(typescript@5.8.3) 930 | typescript: 5.8.3 931 | transitivePeerDependencies: 932 | - supports-color 933 | 934 | '@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)': 935 | dependencies: 936 | '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) 937 | eslint: 8.57.1 938 | transitivePeerDependencies: 939 | - supports-color 940 | - typescript 941 | 942 | '@typescript-eslint/parser@8.32.1(eslint@8.57.1)(typescript@5.8.3)': 943 | dependencies: 944 | '@typescript-eslint/scope-manager': 8.32.1 945 | '@typescript-eslint/types': 8.32.1 946 | '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) 947 | '@typescript-eslint/visitor-keys': 8.32.1 948 | debug: 4.4.1 949 | eslint: 8.57.1 950 | typescript: 5.8.3 951 | transitivePeerDependencies: 952 | - supports-color 953 | 954 | '@typescript-eslint/scope-manager@5.62.0': 955 | dependencies: 956 | '@typescript-eslint/types': 5.62.0 957 | '@typescript-eslint/visitor-keys': 5.62.0 958 | 959 | '@typescript-eslint/scope-manager@8.32.1': 960 | dependencies: 961 | '@typescript-eslint/types': 8.32.1 962 | '@typescript-eslint/visitor-keys': 8.32.1 963 | 964 | '@typescript-eslint/type-utils@8.32.1(eslint@8.57.1)(typescript@5.8.3)': 965 | dependencies: 966 | '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) 967 | '@typescript-eslint/utils': 8.32.1(eslint@8.57.1)(typescript@5.8.3) 968 | debug: 4.4.1 969 | eslint: 8.57.1 970 | ts-api-utils: 2.1.0(typescript@5.8.3) 971 | typescript: 5.8.3 972 | transitivePeerDependencies: 973 | - supports-color 974 | 975 | '@typescript-eslint/types@5.62.0': {} 976 | 977 | '@typescript-eslint/types@8.32.1': {} 978 | 979 | '@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)': 980 | dependencies: 981 | '@typescript-eslint/types': 5.62.0 982 | '@typescript-eslint/visitor-keys': 5.62.0 983 | debug: 4.4.1 984 | globby: 11.1.0 985 | is-glob: 4.0.3 986 | semver: 7.7.2 987 | tsutils: 3.21.0(typescript@5.8.3) 988 | optionalDependencies: 989 | typescript: 5.8.3 990 | transitivePeerDependencies: 991 | - supports-color 992 | 993 | '@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)': 994 | dependencies: 995 | '@typescript-eslint/types': 8.32.1 996 | '@typescript-eslint/visitor-keys': 8.32.1 997 | debug: 4.4.1 998 | fast-glob: 3.3.3 999 | is-glob: 4.0.3 1000 | minimatch: 9.0.5 1001 | semver: 7.7.2 1002 | ts-api-utils: 2.1.0(typescript@5.8.3) 1003 | typescript: 5.8.3 1004 | transitivePeerDependencies: 1005 | - supports-color 1006 | 1007 | '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)': 1008 | dependencies: 1009 | '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) 1010 | '@types/json-schema': 7.0.15 1011 | '@types/semver': 7.7.0 1012 | '@typescript-eslint/scope-manager': 5.62.0 1013 | '@typescript-eslint/types': 5.62.0 1014 | '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) 1015 | eslint: 8.57.1 1016 | eslint-scope: 5.1.1 1017 | semver: 7.7.2 1018 | transitivePeerDependencies: 1019 | - supports-color 1020 | - typescript 1021 | 1022 | '@typescript-eslint/utils@8.32.1(eslint@8.57.1)(typescript@5.8.3)': 1023 | dependencies: 1024 | '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) 1025 | '@typescript-eslint/scope-manager': 8.32.1 1026 | '@typescript-eslint/types': 8.32.1 1027 | '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) 1028 | eslint: 8.57.1 1029 | typescript: 5.8.3 1030 | transitivePeerDependencies: 1031 | - supports-color 1032 | 1033 | '@typescript-eslint/visitor-keys@5.62.0': 1034 | dependencies: 1035 | '@typescript-eslint/types': 5.62.0 1036 | eslint-visitor-keys: 3.4.3 1037 | 1038 | '@typescript-eslint/visitor-keys@8.32.1': 1039 | dependencies: 1040 | '@typescript-eslint/types': 8.32.1 1041 | eslint-visitor-keys: 4.2.0 1042 | 1043 | '@ungap/structured-clone@1.3.0': {} 1044 | 1045 | acorn-jsx@5.3.2(acorn@8.14.1): 1046 | dependencies: 1047 | acorn: 8.14.1 1048 | 1049 | acorn@8.14.1: {} 1050 | 1051 | ajv@6.12.6: 1052 | dependencies: 1053 | fast-deep-equal: 3.1.3 1054 | fast-json-stable-stringify: 2.1.0 1055 | json-schema-traverse: 0.4.1 1056 | uri-js: 4.4.1 1057 | 1058 | ajv@8.17.1: 1059 | dependencies: 1060 | fast-deep-equal: 3.1.3 1061 | fast-uri: 3.0.6 1062 | json-schema-traverse: 1.0.0 1063 | require-from-string: 2.0.2 1064 | 1065 | ansi-regex@5.0.1: {} 1066 | 1067 | ansi-styles@4.3.0: 1068 | dependencies: 1069 | color-convert: 2.0.1 1070 | 1071 | anymatch@3.1.3: 1072 | dependencies: 1073 | normalize-path: 3.0.0 1074 | picomatch: 2.3.1 1075 | 1076 | argparse@2.0.1: {} 1077 | 1078 | array-union@2.1.0: {} 1079 | 1080 | balanced-match@1.0.2: {} 1081 | 1082 | binary-extensions@2.3.0: {} 1083 | 1084 | brace-expansion@1.1.11: 1085 | dependencies: 1086 | balanced-match: 1.0.2 1087 | concat-map: 0.0.1 1088 | 1089 | brace-expansion@2.0.1: 1090 | dependencies: 1091 | balanced-match: 1.0.2 1092 | 1093 | braces@3.0.3: 1094 | dependencies: 1095 | fill-range: 7.1.1 1096 | 1097 | callsites@3.1.0: {} 1098 | 1099 | chalk@4.1.2: 1100 | dependencies: 1101 | ansi-styles: 4.3.0 1102 | supports-color: 7.2.0 1103 | 1104 | chokidar@3.6.0: 1105 | dependencies: 1106 | anymatch: 3.1.3 1107 | braces: 3.0.3 1108 | glob-parent: 5.1.2 1109 | is-binary-path: 2.1.0 1110 | is-glob: 4.0.3 1111 | normalize-path: 3.0.0 1112 | readdirp: 3.6.0 1113 | optionalDependencies: 1114 | fsevents: 2.3.3 1115 | 1116 | cliui@8.0.1: 1117 | dependencies: 1118 | string-width: 4.2.3 1119 | strip-ansi: 6.0.1 1120 | wrap-ansi: 7.0.0 1121 | 1122 | color-convert@2.0.1: 1123 | dependencies: 1124 | color-name: 1.1.4 1125 | 1126 | color-name@1.1.4: {} 1127 | 1128 | concat-map@0.0.1: {} 1129 | 1130 | cross-spawn@7.0.6: 1131 | dependencies: 1132 | path-key: 3.1.1 1133 | shebang-command: 2.0.0 1134 | which: 2.0.2 1135 | 1136 | debug@4.4.1: 1137 | dependencies: 1138 | ms: 2.1.3 1139 | 1140 | deep-is@0.1.4: {} 1141 | 1142 | dir-glob@3.0.1: 1143 | dependencies: 1144 | path-type: 4.0.0 1145 | 1146 | doctrine@3.0.0: 1147 | dependencies: 1148 | esutils: 2.0.3 1149 | 1150 | emoji-regex@8.0.0: {} 1151 | 1152 | escalade@3.2.0: {} 1153 | 1154 | escape-string-regexp@4.0.0: {} 1155 | 1156 | eslint-config-prettier@9.1.0(eslint@8.57.1): 1157 | dependencies: 1158 | eslint: 8.57.1 1159 | 1160 | eslint-plugin-prettier@5.4.0(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.5.3): 1161 | dependencies: 1162 | eslint: 8.57.1 1163 | prettier: 3.5.3 1164 | prettier-linter-helpers: 1.0.0 1165 | synckit: 0.11.4 1166 | optionalDependencies: 1167 | eslint-config-prettier: 9.1.0(eslint@8.57.1) 1168 | 1169 | eslint-plugin-roblox-ts@0.0.36(eslint@8.57.1): 1170 | dependencies: 1171 | '@types/node': 20.17.46 1172 | '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) 1173 | typescript: 5.8.3 1174 | transitivePeerDependencies: 1175 | - eslint 1176 | - supports-color 1177 | 1178 | eslint-scope@5.1.1: 1179 | dependencies: 1180 | esrecurse: 4.3.0 1181 | estraverse: 4.3.0 1182 | 1183 | eslint-scope@7.2.2: 1184 | dependencies: 1185 | esrecurse: 4.3.0 1186 | estraverse: 5.3.0 1187 | 1188 | eslint-visitor-keys@3.4.3: {} 1189 | 1190 | eslint-visitor-keys@4.2.0: {} 1191 | 1192 | eslint@8.57.1: 1193 | dependencies: 1194 | '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) 1195 | '@eslint-community/regexpp': 4.12.1 1196 | '@eslint/eslintrc': 2.1.4 1197 | '@eslint/js': 8.57.1 1198 | '@humanwhocodes/config-array': 0.13.0 1199 | '@humanwhocodes/module-importer': 1.0.1 1200 | '@nodelib/fs.walk': 1.2.8 1201 | '@ungap/structured-clone': 1.3.0 1202 | ajv: 6.12.6 1203 | chalk: 4.1.2 1204 | cross-spawn: 7.0.6 1205 | debug: 4.4.1 1206 | doctrine: 3.0.0 1207 | escape-string-regexp: 4.0.0 1208 | eslint-scope: 7.2.2 1209 | eslint-visitor-keys: 3.4.3 1210 | espree: 9.6.1 1211 | esquery: 1.6.0 1212 | esutils: 2.0.3 1213 | fast-deep-equal: 3.1.3 1214 | file-entry-cache: 6.0.1 1215 | find-up: 5.0.0 1216 | glob-parent: 6.0.2 1217 | globals: 13.24.0 1218 | graphemer: 1.4.0 1219 | ignore: 5.3.2 1220 | imurmurhash: 0.1.4 1221 | is-glob: 4.0.3 1222 | is-path-inside: 3.0.3 1223 | js-yaml: 4.1.0 1224 | json-stable-stringify-without-jsonify: 1.0.1 1225 | levn: 0.4.1 1226 | lodash.merge: 4.6.2 1227 | minimatch: 3.1.2 1228 | natural-compare: 1.4.0 1229 | optionator: 0.9.4 1230 | strip-ansi: 6.0.1 1231 | text-table: 0.2.0 1232 | transitivePeerDependencies: 1233 | - supports-color 1234 | 1235 | espree@9.6.1: 1236 | dependencies: 1237 | acorn: 8.14.1 1238 | acorn-jsx: 5.3.2(acorn@8.14.1) 1239 | eslint-visitor-keys: 3.4.3 1240 | 1241 | esquery@1.6.0: 1242 | dependencies: 1243 | estraverse: 5.3.0 1244 | 1245 | esrecurse@4.3.0: 1246 | dependencies: 1247 | estraverse: 5.3.0 1248 | 1249 | estraverse@4.3.0: {} 1250 | 1251 | estraverse@5.3.0: {} 1252 | 1253 | esutils@2.0.3: {} 1254 | 1255 | fast-deep-equal@3.1.3: {} 1256 | 1257 | fast-diff@1.3.0: {} 1258 | 1259 | fast-glob@3.3.3: 1260 | dependencies: 1261 | '@nodelib/fs.stat': 2.0.5 1262 | '@nodelib/fs.walk': 1.2.8 1263 | glob-parent: 5.1.2 1264 | merge2: 1.4.1 1265 | micromatch: 4.0.8 1266 | 1267 | fast-json-stable-stringify@2.1.0: {} 1268 | 1269 | fast-levenshtein@2.0.6: {} 1270 | 1271 | fast-uri@3.0.6: {} 1272 | 1273 | fastq@1.19.1: 1274 | dependencies: 1275 | reusify: 1.1.0 1276 | 1277 | file-entry-cache@6.0.1: 1278 | dependencies: 1279 | flat-cache: 3.2.0 1280 | 1281 | fill-range@7.1.1: 1282 | dependencies: 1283 | to-regex-range: 5.0.1 1284 | 1285 | find-up@5.0.0: 1286 | dependencies: 1287 | locate-path: 6.0.0 1288 | path-exists: 4.0.0 1289 | 1290 | flat-cache@3.2.0: 1291 | dependencies: 1292 | flatted: 3.3.3 1293 | keyv: 4.5.4 1294 | rimraf: 3.0.2 1295 | 1296 | flatted@3.3.3: {} 1297 | 1298 | fs-extra@11.3.0: 1299 | dependencies: 1300 | graceful-fs: 4.2.11 1301 | jsonfile: 6.1.0 1302 | universalify: 2.0.1 1303 | 1304 | fs.realpath@1.0.0: {} 1305 | 1306 | fsevents@2.3.3: 1307 | optional: true 1308 | 1309 | function-bind@1.1.2: {} 1310 | 1311 | get-caller-file@2.0.5: {} 1312 | 1313 | glob-parent@5.1.2: 1314 | dependencies: 1315 | is-glob: 4.0.3 1316 | 1317 | glob-parent@6.0.2: 1318 | dependencies: 1319 | is-glob: 4.0.3 1320 | 1321 | glob@7.2.3: 1322 | dependencies: 1323 | fs.realpath: 1.0.0 1324 | inflight: 1.0.6 1325 | inherits: 2.0.4 1326 | minimatch: 3.1.2 1327 | once: 1.4.0 1328 | path-is-absolute: 1.0.1 1329 | 1330 | globals@13.24.0: 1331 | dependencies: 1332 | type-fest: 0.20.2 1333 | 1334 | globby@11.1.0: 1335 | dependencies: 1336 | array-union: 2.1.0 1337 | dir-glob: 3.0.1 1338 | fast-glob: 3.3.3 1339 | ignore: 5.3.2 1340 | merge2: 1.4.1 1341 | slash: 3.0.0 1342 | 1343 | graceful-fs@4.2.11: {} 1344 | 1345 | graphemer@1.4.0: {} 1346 | 1347 | has-flag@4.0.0: {} 1348 | 1349 | hasown@2.0.2: 1350 | dependencies: 1351 | function-bind: 1.1.2 1352 | 1353 | ignore@5.3.2: {} 1354 | 1355 | ignore@7.0.4: {} 1356 | 1357 | import-fresh@3.3.1: 1358 | dependencies: 1359 | parent-module: 1.0.1 1360 | resolve-from: 4.0.0 1361 | 1362 | imurmurhash@0.1.4: {} 1363 | 1364 | inflight@1.0.6: 1365 | dependencies: 1366 | once: 1.4.0 1367 | wrappy: 1.0.2 1368 | 1369 | inherits@2.0.4: {} 1370 | 1371 | is-binary-path@2.1.0: 1372 | dependencies: 1373 | binary-extensions: 2.3.0 1374 | 1375 | is-core-module@2.16.1: 1376 | dependencies: 1377 | hasown: 2.0.2 1378 | 1379 | is-extglob@2.1.1: {} 1380 | 1381 | is-fullwidth-code-point@3.0.0: {} 1382 | 1383 | is-glob@4.0.3: 1384 | dependencies: 1385 | is-extglob: 2.1.1 1386 | 1387 | is-number@7.0.0: {} 1388 | 1389 | is-path-inside@3.0.3: {} 1390 | 1391 | isexe@2.0.0: {} 1392 | 1393 | js-yaml@4.1.0: 1394 | dependencies: 1395 | argparse: 2.0.1 1396 | 1397 | json-buffer@3.0.1: {} 1398 | 1399 | json-schema-traverse@0.4.1: {} 1400 | 1401 | json-schema-traverse@1.0.0: {} 1402 | 1403 | json-stable-stringify-without-jsonify@1.0.1: {} 1404 | 1405 | jsonfile@6.1.0: 1406 | dependencies: 1407 | universalify: 2.0.1 1408 | optionalDependencies: 1409 | graceful-fs: 4.2.11 1410 | 1411 | keyv@4.5.4: 1412 | dependencies: 1413 | json-buffer: 3.0.1 1414 | 1415 | kleur@4.1.5: {} 1416 | 1417 | levn@0.4.1: 1418 | dependencies: 1419 | prelude-ls: 1.2.1 1420 | type-check: 0.4.0 1421 | 1422 | locate-path@6.0.0: 1423 | dependencies: 1424 | p-locate: 5.0.0 1425 | 1426 | lodash.merge@4.6.2: {} 1427 | 1428 | merge2@1.4.1: {} 1429 | 1430 | micromatch@4.0.8: 1431 | dependencies: 1432 | braces: 3.0.3 1433 | picomatch: 2.3.1 1434 | 1435 | minimatch@3.1.2: 1436 | dependencies: 1437 | brace-expansion: 1.1.11 1438 | 1439 | minimatch@9.0.5: 1440 | dependencies: 1441 | brace-expansion: 2.0.1 1442 | 1443 | ms@2.1.3: {} 1444 | 1445 | natural-compare@1.4.0: {} 1446 | 1447 | normalize-path@3.0.0: {} 1448 | 1449 | once@1.4.0: 1450 | dependencies: 1451 | wrappy: 1.0.2 1452 | 1453 | optionator@0.9.4: 1454 | dependencies: 1455 | deep-is: 0.1.4 1456 | fast-levenshtein: 2.0.6 1457 | levn: 0.4.1 1458 | prelude-ls: 1.2.1 1459 | type-check: 0.4.0 1460 | word-wrap: 1.2.5 1461 | 1462 | p-limit@3.1.0: 1463 | dependencies: 1464 | yocto-queue: 0.1.0 1465 | 1466 | p-locate@5.0.0: 1467 | dependencies: 1468 | p-limit: 3.1.0 1469 | 1470 | parent-module@1.0.1: 1471 | dependencies: 1472 | callsites: 3.1.0 1473 | 1474 | path-exists@4.0.0: {} 1475 | 1476 | path-is-absolute@1.0.1: {} 1477 | 1478 | path-key@3.1.1: {} 1479 | 1480 | path-parse@1.0.7: {} 1481 | 1482 | path-type@4.0.0: {} 1483 | 1484 | picomatch@2.3.1: {} 1485 | 1486 | prelude-ls@1.2.1: {} 1487 | 1488 | prettier-linter-helpers@1.0.0: 1489 | dependencies: 1490 | fast-diff: 1.3.0 1491 | 1492 | prettier@3.5.3: {} 1493 | 1494 | punycode@2.3.1: {} 1495 | 1496 | queue-microtask@1.2.3: {} 1497 | 1498 | readdirp@3.6.0: 1499 | dependencies: 1500 | picomatch: 2.3.1 1501 | 1502 | require-directory@2.1.1: {} 1503 | 1504 | require-from-string@2.0.2: {} 1505 | 1506 | resolve-from@4.0.0: {} 1507 | 1508 | resolve@1.22.10: 1509 | dependencies: 1510 | is-core-module: 2.16.1 1511 | path-parse: 1.0.7 1512 | supports-preserve-symlinks-flag: 1.0.0 1513 | 1514 | reusify@1.1.0: {} 1515 | 1516 | rimraf@3.0.2: 1517 | dependencies: 1518 | glob: 7.2.3 1519 | 1520 | roblox-ts@3.0.0: 1521 | dependencies: 1522 | '@roblox-ts/luau-ast': 2.0.0 1523 | '@roblox-ts/path-translator': 1.1.0 1524 | '@roblox-ts/rojo-resolver': 1.1.0 1525 | chokidar: 3.6.0 1526 | fs-extra: 11.3.0 1527 | kleur: 4.1.5 1528 | resolve: 1.22.10 1529 | typescript: 5.5.3 1530 | yargs: 17.7.2 1531 | 1532 | run-parallel@1.2.0: 1533 | dependencies: 1534 | queue-microtask: 1.2.3 1535 | 1536 | semver@7.7.2: {} 1537 | 1538 | shebang-command@2.0.0: 1539 | dependencies: 1540 | shebang-regex: 3.0.0 1541 | 1542 | shebang-regex@3.0.0: {} 1543 | 1544 | slash@3.0.0: {} 1545 | 1546 | string-width@4.2.3: 1547 | dependencies: 1548 | emoji-regex: 8.0.0 1549 | is-fullwidth-code-point: 3.0.0 1550 | strip-ansi: 6.0.1 1551 | 1552 | strip-ansi@6.0.1: 1553 | dependencies: 1554 | ansi-regex: 5.0.1 1555 | 1556 | strip-json-comments@3.1.1: {} 1557 | 1558 | supports-color@7.2.0: 1559 | dependencies: 1560 | has-flag: 4.0.0 1561 | 1562 | supports-preserve-symlinks-flag@1.0.0: {} 1563 | 1564 | synckit@0.11.4: 1565 | dependencies: 1566 | '@pkgr/core': 0.2.4 1567 | tslib: 2.8.1 1568 | 1569 | text-table@0.2.0: {} 1570 | 1571 | to-regex-range@5.0.1: 1572 | dependencies: 1573 | is-number: 7.0.0 1574 | 1575 | ts-api-utils@2.1.0(typescript@5.8.3): 1576 | dependencies: 1577 | typescript: 5.8.3 1578 | 1579 | tslib@1.14.1: {} 1580 | 1581 | tslib@2.8.1: {} 1582 | 1583 | tsutils@3.21.0(typescript@5.8.3): 1584 | dependencies: 1585 | tslib: 1.14.1 1586 | typescript: 5.8.3 1587 | 1588 | type-check@0.4.0: 1589 | dependencies: 1590 | prelude-ls: 1.2.1 1591 | 1592 | type-fest@0.20.2: {} 1593 | 1594 | typescript@5.5.3: {} 1595 | 1596 | typescript@5.8.3: {} 1597 | 1598 | undici-types@6.19.8: {} 1599 | 1600 | universalify@2.0.1: {} 1601 | 1602 | uri-js@4.4.1: 1603 | dependencies: 1604 | punycode: 2.3.1 1605 | 1606 | which@2.0.2: 1607 | dependencies: 1608 | isexe: 2.0.0 1609 | 1610 | word-wrap@1.2.5: {} 1611 | 1612 | wrap-ansi@7.0.0: 1613 | dependencies: 1614 | ansi-styles: 4.3.0 1615 | string-width: 4.2.3 1616 | strip-ansi: 6.0.1 1617 | 1618 | wrappy@1.0.2: {} 1619 | 1620 | y18n@5.0.8: {} 1621 | 1622 | yargs-parser@21.1.1: {} 1623 | 1624 | yargs@17.7.2: 1625 | dependencies: 1626 | cliui: 8.0.1 1627 | escalade: 3.2.0 1628 | get-caller-file: 2.0.5 1629 | require-directory: 2.1.1 1630 | string-width: 4.2.3 1631 | y18n: 5.0.8 1632 | yargs-parser: 21.1.1 1633 | 1634 | yocto-queue@0.1.0: {} 1635 | -------------------------------------------------------------------------------- /rokit.toml: -------------------------------------------------------------------------------- 1 | # This file lists tools managed by Rokit, a toolchain manager for Roblox projects. 2 | # For more information, see https://github.com/rojo-rbx/rokit 3 | 4 | # New tools can be added by running `rokit add ` in a terminal. 5 | 6 | [tools] 7 | wally = "UpliftGames/wally@0.3.2" 8 | rojo = "rojo-rbx/rojo@7.5.1" 9 | wally-package-types = "JohnnyMorganz/wally-package-types@1.4.2" 10 | stylua = "johnnymorganz/stylua@2.1.0" 11 | selene = "Kampfkarren/selene@0.28.0" 12 | luau-lsp = "johnnymorganz/luau-lsp@1.46.0" 13 | -------------------------------------------------------------------------------- /scripts/check.sh: -------------------------------------------------------------------------------- 1 | curl -o scripts/roblox.d.lua https://raw.githubusercontent.com/JohnnyMorganz/luau-lsp/main/scripts/globalTypes.d.lua 2 | 3 | rojo sourcemap dev.project.json -o sourcemap.json 4 | 5 | luau-lsp analyze --defs=scripts/roblox.d.lua --sourcemap=sourcemap.json --ignore="**/_Index/**" src 6 | selene src 7 | stylua --check src 8 | eslint src 9 | 10 | rm scripts/roblox.d.lua 11 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | wally install 2 | rojo sourcemap dev.project.json --output sourcemap.json 3 | wally-package-types --sourcemap sourcemap.json Packages 4 | -------------------------------------------------------------------------------- /selene.toml: -------------------------------------------------------------------------------- 1 | std = "roblox" 2 | -------------------------------------------------------------------------------- /src/React.luau: -------------------------------------------------------------------------------- 1 | --!nocheck 2 | 3 | return if script.Parent.Parent:FindFirstChild("react") 4 | then require(script.Parent.Parent.react) 5 | else require(script.Parent.Parent.React) 6 | -------------------------------------------------------------------------------- /src/Reflex.luau: -------------------------------------------------------------------------------- 1 | --!nocheck 2 | 3 | if script.Parent.Parent:FindFirstChild("reflex") then 4 | return require(script.Parent.Parent.reflex.src) 5 | end 6 | 7 | local Reflex = require(script.Parent.Parent.Reflex) 8 | 9 | export type Producer = Reflex.Producer 10 | 11 | return Reflex 12 | -------------------------------------------------------------------------------- /src/components/ReflexContext.luau: -------------------------------------------------------------------------------- 1 | local React = require(script.Parent.Parent.React) 2 | local Reflex = require(script.Parent.Parent.Reflex) 3 | 4 | local ReflexContext = React.createContext((nil :: any) :: Reflex.Producer) 5 | 6 | return ReflexContext 7 | -------------------------------------------------------------------------------- /src/components/ReflexProvider.luau: -------------------------------------------------------------------------------- 1 | local React = require(script.Parent.Parent.React) 2 | local Reflex = require(script.Parent.Parent.Reflex) 3 | local ReflexContext = require(script.Parent.ReflexContext) 4 | 5 | type Props = { 6 | --[=[ 7 | The root producer to provide to the context 8 | ]=] 9 | producer: Reflex.Producer, 10 | --[=[ 11 | An optional initial state snapshot to merge into the producer's state 12 | ]=] 13 | initialState: { [any]: any }?, 14 | children: any, 15 | } 16 | 17 | local function ReflexProvider(props: Props) 18 | React.useMemo(function() 19 | -- Run in useMemo to set the state before rendering children 20 | if props.initialState then 21 | local state = table.clone(props.producer:getState() :: {}) 22 | 23 | for key, value in props.initialState do 24 | state[key] = value 25 | end 26 | 27 | props.producer:setState(state) 28 | end 29 | end, {}) 30 | 31 | return React.createElement(ReflexContext.Provider, { value = props.producer }, props.children) 32 | end 33 | 34 | return ReflexProvider 35 | -------------------------------------------------------------------------------- /src/hooks/useProducer.luau: -------------------------------------------------------------------------------- 1 | local React = require(script.Parent.Parent.React) 2 | local ReflexContext = require(script.Parent.Parent.components.ReflexContext) 3 | 4 | --[=[ 5 | A hook that returns the producer passed to the ``. 6 | 7 | #### Example 8 | 9 | ```lua 10 | local useRootProducer = useProducer :: UseProducerHook 11 | ``` 12 | 13 | @return The root producer 14 | ]=] 15 | export type UseProducerHook = () -> RootProducer 16 | 17 | --[=[ 18 | Returns the producer passed to the ``. 19 | 20 | #### Example 21 | 22 | ```lua 23 | local producer = useRootProducer() 24 | producer.increment() 25 | ``` 26 | 27 | @return The root producer 28 | ]=] 29 | local function useProducer(): T 30 | local producer = React.useContext(ReflexContext) 31 | assert(producer, "useProducer must be used within a component") 32 | return producer 33 | end 34 | 35 | return useProducer 36 | -------------------------------------------------------------------------------- /src/hooks/useSelector.luau: -------------------------------------------------------------------------------- 1 | local React = require(script.Parent.Parent.React) 2 | local useProducer = require(script.Parent.useProducer) 3 | 4 | --[=[ 5 | A hook that returns the result of a selector function applied to the current 6 | state. This type is typically unnecessary if your selector function is defined 7 | with an explicit `state` parameter type. 8 | 9 | #### Example 10 | 11 | ```lua 12 | local useRootSelector = useSelector :: UseSelectorHook 13 | ``` 14 | 15 | @param selector A function that takes the current state and returns a value 16 | @param equalityFn An optional function that determines if the component should re-render 17 | @return The result of the selector function 18 | ]=] 19 | export type UseSelectorHook = ( 20 | selector: (state: State) -> Result, 21 | equalityFn: ((next: Result, prev: Result) -> boolean)? 22 | ) -> Result 23 | 24 | --[=[ 25 | Returns the result of a selector function applied to the current state. 26 | 27 | #### Example 28 | 29 | ```lua 30 | local counter = useSelector(function(state: RootState) 31 | return state.counter 32 | end) 33 | ``` 34 | 35 | @param selector A function that takes the current state and returns a value 36 | @param equalityFn An optional function that determines if the component should re-render 37 | @return The result of the selector function 38 | ]=] 39 | local function useSelector(selector: (state: any) -> T, equalityFn: ((next: T, prev: T) -> boolean)?): T 40 | local producer = useProducer() 41 | local latestSelector = React.useRef(selector) :: { current: typeof(selector) } 42 | 43 | local result, setResult = React.useState(function() 44 | return selector(producer:getState()) 45 | end) 46 | 47 | React.useEffect(function() 48 | setResult(selector(producer:getState())) 49 | latestSelector.current = selector 50 | end, { selector }) 51 | 52 | React.useEffect(function() 53 | local prevResult = result 54 | 55 | return producer:subscribe(function(nextState) 56 | local nextResult = latestSelector.current(nextState) 57 | local shouldUpdate = if equalityFn then not equalityFn(nextResult, prevResult) else nextResult ~= prevResult 58 | 59 | if shouldUpdate then 60 | prevResult = nextResult 61 | setResult(nextResult) 62 | end 63 | end) 64 | end, { producer }) 65 | 66 | return result 67 | end 68 | 69 | return useSelector 70 | -------------------------------------------------------------------------------- /src/hooks/useSelectorCreator.luau: -------------------------------------------------------------------------------- 1 | local React = require(script.Parent.Parent.React) 2 | local useSelector = require(script.Parent.useSelector) 3 | 4 | local function pack(...) 5 | return { ... } 6 | end 7 | 8 | --[=[ 9 | Similar to `useSelector`, but accepts a selector factory that returns a 10 | selector. The selector factory is only called when the arguments change, and 11 | the selector is memoized. 12 | 13 | #### Example 14 | 15 | ```lua 16 | local useRootSelectorCreator = useSelectorCreator :: UseSelectorCreatorHook 17 | ``` 18 | 19 | @param selectorFactory A function that returns a selector 20 | @param ... Arguments to pass to the selector factory 21 | @return The result of the selector 22 | ]=] 23 | export type UseSelectorCreatorHook = ( 24 | selectorFactory: (Args...) -> (state: State) -> Result, 25 | Args... 26 | ) -> Result 27 | 28 | --[=[ 29 | Similar to `useSelector`, but accepts a selector factory that returns a 30 | selector. The selector factory is only called when the arguments change, and 31 | the selector is memoized. 32 | 33 | #### Example 34 | 35 | ```lua 36 | local function selectUserById(id: string) 37 | return function(state: RootState) 38 | return state.users[id] 39 | end 40 | end 41 | 42 | local user = useSelectorCreator(selectUserById, "123") 43 | ``` 44 | 45 | @param selectorFactory A function that returns a selector 46 | @param ... Arguments to pass to the selector factory 47 | @return The result of the selector 48 | ]=] 49 | local function useSelectorCreator(selectorFactory: (Args...) -> (state: any) -> Result, ...: Args...) 50 | local arguments = pack(...) 51 | 52 | local selector = React.useMemo(function() 53 | return selectorFactory(table.unpack(arguments)) 54 | end, arguments) 55 | 56 | return useSelector(selector) 57 | end 58 | 59 | return useSelectorCreator 60 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | import React from "@rbxts/react"; 2 | import { InferState, Producer } from "@rbxts/reflex"; 3 | 4 | export = ReactReflex; 5 | export as namespace ReactReflex; 6 | 7 | declare namespace ReactReflex { 8 | const ReflexContext: React.Context; 9 | 10 | interface ReflexProviderProps { 11 | /** 12 | * The root producer to provide to the Reflex context. 13 | */ 14 | producer: Producer; 15 | /** 16 | * An optional initial state snapshot to merge into the producer's state. 17 | */ 18 | initialState?: Partial; 19 | /** 20 | * The children to render. 21 | */ 22 | children?: React.ReactNode; 23 | } 24 | 25 | function ReflexProvider(props: ReflexProviderProps): React.Element; 26 | 27 | /** 28 | * Returns the root producer passed to the ``. 29 | * 30 | * @example 31 | * const useRootProducer: UseProducerHook = useProducer; 32 | * 33 | * @returns The root producer passed to the ``. 34 | */ 35 | type UseProducerHook = () => Producer; 36 | 37 | /** 38 | * Returns the root producer passed to the ``. 39 | * 40 | * @example 41 | * const rootProducer = useProducer(); 42 | * 43 | * @returns The root producer passed to the ``. 44 | */ 45 | function useProducer(): T; 46 | 47 | /** 48 | * Returns the result of a selector function applied to the current state. 49 | * 50 | * @example 51 | * const useRootSelector: UseSelectorHook = useSelector; 52 | * 53 | * @param selector A function that takes the current state and returns a value 54 | * @param equalityFn An optional function that determines whether the 55 | * component should re-render 56 | * @returns The result of the selector function 57 | */ 58 | export type UseSelectorHook = ( 59 | selector: (state: InferState) => Result, 60 | equalityFn?: (next: Result, prev: Result) => boolean, 61 | ) => Result; 62 | 63 | /** 64 | * Returns the result of a selector function applied to the current state. 65 | * 66 | * @example 67 | * const selectedValue = useSelector((state: RootState) => state.value); 68 | * 69 | * @param selector A function that takes the current state and returns a value 70 | * @param equalityFn An optional function that determines whether the 71 | * component should re-render 72 | * @returns The result of the selector function 73 | */ 74 | function useSelector( 75 | selector: (state: any) => Result, 76 | equalityFn?: (next: Result, prev: Result) => boolean, 77 | ): Result; 78 | 79 | /** 80 | * Similar to `useSelector`, but accepts a selector factory that returns a 81 | * selector. The selector factory is only called when the arguments change, 82 | * and the selector is memoized. 83 | * 84 | * @example 85 | * const useRootSelectorCreator: UseSelectorCreatorHook = useSelectorCreator; 86 | * 87 | * @param selectorFactory A function that returns a selector 88 | * @param args Arguments to pass to the selector factory 89 | * @returns The result of the selector function 90 | */ 91 | export type UseSelectorCreatorHook = ( 92 | selectorFactory: (...args: Args) => (state: InferState) => Result, 93 | ...args: Args 94 | ) => Result; 95 | 96 | /** 97 | * Similar to `useSelector`, but accepts a selector factory that returns a 98 | * selector. The selector factory is only called when the arguments change, 99 | * and the selector is memoized. 100 | * 101 | * @example 102 | * const selectById = (id: string) => (state: RootState) => state[id]; 103 | * const result = useSelectorCreator(selectById, "hello-world"); 104 | * 105 | * @param selectorFactory A function that returns a selector 106 | * @param args Arguments to pass to the selector factory 107 | * @returns The result of the selector function 108 | */ 109 | function useSelectorCreator( 110 | selectorFactory: (...args: Args) => (state: any) => Result, 111 | ...args: Args 112 | ): Result; 113 | } 114 | -------------------------------------------------------------------------------- /src/init.luau: -------------------------------------------------------------------------------- 1 | local ReflexContext = require(script.components.ReflexContext) 2 | local ReflexProvider = require(script.components.ReflexProvider) 3 | local useProducer = require(script.hooks.useProducer) 4 | local useSelector = require(script.hooks.useSelector) 5 | local useSelectorCreator = require(script.hooks.useSelectorCreator) 6 | 7 | export type UseProducerHook = useProducer.UseProducerHook 8 | export type UseSelectorHook = useSelector.UseSelectorHook 9 | export type UseSelectorCreatorHook = useSelectorCreator.UseSelectorCreatorHook 10 | 11 | return { 12 | ReflexContext = ReflexContext, 13 | ReflexProvider = ReflexProvider, 14 | useProducer = useProducer, 15 | useSelector = useSelector, 16 | useSelectorCreator = useSelectorCreator, 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // required 4 | "allowSyntheticDefaultImports": true, 5 | "downlevelIteration": true, 6 | "jsx": "react", 7 | "jsxFactory": "React.createElement", 8 | "jsxFragmentFactory": "React.Fragment", 9 | "module": "commonjs", 10 | "moduleResolution": "Node", 11 | "noLib": true, 12 | "resolveJsonModule": true, 13 | "experimentalDecorators": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "moduleDetection": "force", 16 | "strict": true, 17 | "target": "ESNext", 18 | "typeRoots": ["node_modules/@rbxts"], 19 | 20 | // configurable 21 | "rootDir": "src", 22 | "outDir": "out", 23 | "incremental": true, 24 | "tsBuildInfoFile": "out/tsconfig.tsbuildinfo", 25 | "declaration": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wally.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Wally. 2 | # It is not intended for manual editing. 3 | registry = "test" 4 | 5 | [[package]] 6 | name = "evaera/promise" 7 | version = "4.0.0" 8 | dependencies = [] 9 | 10 | [[package]] 11 | name = "jsdotlua/boolean" 12 | version = "1.2.6" 13 | dependencies = [["number", "jsdotlua/number@1.2.6"]] 14 | 15 | [[package]] 16 | name = "jsdotlua/collections" 17 | version = "1.2.6" 18 | dependencies = [["es7-types", "jsdotlua/es7-types@1.2.6"], ["instance-of", "jsdotlua/instance-of@1.2.6"]] 19 | 20 | [[package]] 21 | name = "jsdotlua/console" 22 | version = "1.2.6" 23 | dependencies = [["collections", "jsdotlua/collections@1.2.6"]] 24 | 25 | [[package]] 26 | name = "jsdotlua/es7-types" 27 | version = "1.2.6" 28 | dependencies = [] 29 | 30 | [[package]] 31 | name = "jsdotlua/instance-of" 32 | version = "1.2.6" 33 | dependencies = [] 34 | 35 | [[package]] 36 | name = "jsdotlua/luau-polyfill" 37 | version = "1.2.6" 38 | dependencies = [["boolean", "jsdotlua/boolean@1.2.6"], ["collections", "jsdotlua/collections@1.2.6"], ["console", "jsdotlua/console@1.2.6"], ["es7-types", "jsdotlua/es7-types@1.2.6"], ["instance-of", "jsdotlua/instance-of@1.2.6"], ["math", "jsdotlua/math@1.2.6"], ["number", "jsdotlua/number@1.2.6"], ["string", "jsdotlua/string@1.2.6"], ["symbol-luau", "jsdotlua/symbol-luau@1.0.1"], ["timers", "jsdotlua/timers@1.2.6"]] 39 | 40 | [[package]] 41 | name = "jsdotlua/math" 42 | version = "1.2.6" 43 | dependencies = [] 44 | 45 | [[package]] 46 | name = "jsdotlua/number" 47 | version = "1.2.6" 48 | dependencies = [] 49 | 50 | [[package]] 51 | name = "jsdotlua/react" 52 | version = "17.1.0" 53 | dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.6"], ["shared", "jsdotlua/shared@17.1.0"]] 54 | 55 | [[package]] 56 | name = "jsdotlua/shared" 57 | version = "17.1.0" 58 | dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.6"]] 59 | 60 | [[package]] 61 | name = "jsdotlua/string" 62 | version = "1.2.6" 63 | dependencies = [["es7-types", "jsdotlua/es7-types@1.2.6"], ["number", "jsdotlua/number@1.2.6"]] 64 | 65 | [[package]] 66 | name = "jsdotlua/symbol-luau" 67 | version = "1.0.1" 68 | dependencies = [] 69 | 70 | [[package]] 71 | name = "jsdotlua/timers" 72 | version = "1.2.6" 73 | dependencies = [["collections", "jsdotlua/collections@1.2.6"]] 74 | 75 | [[package]] 76 | name = "littensy/react-reflex" 77 | version = "0.3.6" 78 | dependencies = [["React", "jsdotlua/react@17.1.0"], ["Reflex", "littensy/reflex@4.3.1"]] 79 | 80 | [[package]] 81 | name = "littensy/reflex" 82 | version = "4.3.1" 83 | dependencies = [["Promise", "evaera/promise@4.0.0"]] 84 | -------------------------------------------------------------------------------- /wally.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "littensy/react-reflex" 3 | description = "Use Reflex with React" 4 | version = "0.3.6" 5 | license = "MIT" 6 | registry = "https://github.com/UpliftGames/wally-index" 7 | realm = "shared" 8 | exclude = ["**"] 9 | include = ["src", "src/**", "default.project.json", "wally.toml", "LICENSE.md"] 10 | 11 | [dependencies] 12 | React = "jsdotlua/react@17.1.0" 13 | Reflex = "littensy/reflex@4.3.1" 14 | --------------------------------------------------------------------------------