├── .gitignore ├── LICENSE ├── README.md ├── lib └── put-openrct2.d.ts-here.md ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── plugin.ts └── startup.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # OpenRCT2 TypeScript API declaration file 2 | lib/openrct2.d.ts 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Microbundle cache 60 | .rpt2_cache/ 61 | .rts2_cache_cjs/ 62 | .rts2_cache_es/ 63 | .rts2_cache_umd/ 64 | 65 | # Optional REPL history 66 | .node_repl_history 67 | 68 | # Output of 'npm pack' 69 | *.tgz 70 | 71 | # Yarn Integrity file 72 | .yarn-integrity 73 | 74 | # dotenv environment variables file 75 | .env 76 | .env.test 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | 81 | # Next.js build output 82 | .next 83 | 84 | # Nuxt.js build / generate output 85 | .nuxt 86 | dist 87 | 88 | # Gatsby files 89 | .cache/ 90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 | # https://nextjs.org/blog/next-9-1#public-directory-support 92 | # public 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # TernJS port file 107 | .tern-port 108 | 109 | # Visual Studio 110 | .vs/ 111 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple OpenRCT2 plugin template with Typescript 2 | 3 | A simple and minimal template for OpenRCT2 plugins, using Typescript, without any unnecessary extra's. 4 | 5 | Also supports: 6 | - Automatic plugin reload in OpenRCT2 (hot reload); 7 | - Out of the box minification to improve file sizes; 8 | - Support for external NPM packages (like FlexUI). 9 | 10 | ## How to start 11 | 12 | 1. Install latest version of [Node](https://nodejs.org/en/) and make sure to include NPM and enable the "Add to PATH" option during installation. 13 | 2. Use the green "Use this template" button in the top right corner of this page, or download the project to a location of your choice on your PC. 14 | 3. Open a terminal or command prompt. 15 | 4. Use `cd` to change your current directory to the root folder of this project. 16 | 5. Run `npm install` to install the project's dependencies. 17 | 6. Find `openrct2.d.ts` TypeScript API declaration file in OpenRCT2 files. copy it to `./lib/` folder. 18 | - This file can usually be found in the [OpenRCT2 installation directory](#openrct2-installation-directory). 19 | - Alternatively you can download the file from Github [here](https://raw.githubusercontent.com/OpenRCT2/OpenRCT2/develop/distribution/openrct2.d.ts). 20 | - Another option is to make a symbolic link instead of copying the file, which will keep the file up to date whenever you install new versions of OpenRCT2. 21 | 7. In `./src/plugin.ts`, change the name and author of the plugin to your liking. 22 | 8. In `./rollup.config.js`, change the filename of the outputted plugin. 23 | 24 | --- 25 | 26 | ## Commands 27 | 28 | The template comes with several terminal commands to make developing plugins easier. 29 | 30 | `npm run build` 31 | 32 | Creates a release build of your plugin. This version is optimized for sharing with others, using Terser to make the file as small as possible. By default, the plugin will be outputted to `./dist/`. 33 | 34 | `npm run build:dev` 35 | 36 | Creates a develop build of your plugin. This version is not optimized for sharing, but easier to read in case you want to see the outputted Javascript. By default, the plugin will be outputted in the plugin folder of the default [OpenRCT2 user directory](#openrct2-user-directory). 37 | 38 | `npm start` or `npm run start` 39 | 40 | Will start a script that will automatically run `npm run build:dev` every time you make a change to any Typescript or Javascript file inside the `./src/` folder. 41 | 42 | ### Output paths 43 | 44 | These output paths can be changed in `rollup.config.js`. In this file you can also change the outputted filename of the plugin. 45 | 46 | --- 47 | 48 | ## Access game logs 49 | 50 | When your plugin is not loading properly, it may be useful to be able to read the logs of the game to see if there are any errors. Furthermore, if you use the `console.log` function, the resulting logs can be read here as well. 51 | 52 | ### Windows 53 | 54 | 1. Navigate to the folder where [OpenRCT2 is installed](#openrct2-installation-directory). 55 | 2. Launch the `openrct2.com` file located there (the MS-DOS application). 56 | - If file extensions are hidden, make sure to [enable them](https://support.microsoft.com/en-us/windows/common-file-name-extensions-in-windows-da4a4430-8e76-89c5-59f7-1cdbbc75cb01). 57 | 58 | ### MacOS 59 | 60 | 1. Launch a terminal or another command-line prompt. 61 | 2. Using the `cd` command, navigate to the folder where [OpenRCT2 is installed](#openrct2-installation-directory). 62 | 3. Run `open OpenRCT2.app/Contents/MacOS/OpenRCT2` to launch OpenRCT2 with logging enabled. 63 | 64 | --- 65 | 66 | ## Hot reload 67 | 68 | This project supports the [OpenRCT2 hot reload feature](https://github.com/OpenRCT2/OpenRCT2/blob/master/distribution/scripting.md#writing-scripts) for development. 69 | 70 | 1. Navigate to your [OpenRCT2 user directory](#openrct2-user-directory) and open the `config.ini` file. 71 | 2. Enable hot reload by setting `enable_hot_reloading = true` in `config.ini`. 72 | 3. Run `npm start` in the directory of this project to start the hot reload server. 73 | 4. Start the OpenRCT2 and load a save or start a new game. 74 | 5. Each time you save any of the files in `./src/`, the server will compile `./src/registerPlugin.ts` and place compiled plugin file inside your local OpenRCT2 plugin directory. 75 | 6. OpenRCT2 will notice file changes and it will reload the plugin. 76 | 77 | --- 78 | 79 | ## Folders 80 | 81 | ### OpenRCT2 installation directory 82 | 83 | This is the directory where the game is installed. 84 | 85 | - **Windows:** usually `C:/Users//Documents/OpenRCT2/bin/` when using the launcher or `C:/Program Files/OpenRCT2/` when an installer was used. 86 | - **MacOS:** the folder where the `OpenRCT2.app` application file was placed. 87 | - **Linux:** depends on the distro, but likely either `/usr/share/openrct2` when installed through a package manager, or mounted in `/tmp` when using an AppImage. 88 | 89 | ### OpenRCT2 user directory 90 | 91 | This is the directory where the game stores user data, like save games and plugins. 92 | 93 | - **Windows:** usually `Documents/OpenRCT2/` or `C:/Users//Documents/OpenRCT2/`. 94 | - **MacOS:** usually `/Users//Library/Application Support/OpenRCT2/`. Note that `Library` is a hidden folder in your user directory, so by default it will not show up in Finder. 95 | - **Linux:** usually `/home//.config`, `$HOME/.config`, or where the environment variable `$XDG_CONFIG_HOME` points to if it's set. 96 | 97 | You can also open this folder from inside OpenRCT2, by selecting "Open custom content folder" in the dropdown under the red toolbox in the main menu. 98 | 99 | --- 100 | 101 | ## Dependencies 102 | 103 | The following libraries and tools are used in this template: 104 | 105 | - **NodeJS** is the JavaScript engine used to develop and run code when the game is not running. 106 | - **NPM** is a library and package manager for JavasScript and TypeScript and can be used to install new packages and update existing packages in the project. 107 | - **TypeScript** is a expansion language to JavaScript that adds type checking when you are writing the code. It allows you to specify rules for how objects and values look like, so TypeScript can report back if your code follows these rules (instead of crashes or errors in-game). 108 | - **Rollup** bundles all source code, runs it through some plugins like TypeScript, and then outputs a single JavaScript plugin file. 109 | - **Nodemon** is the program that can watch a folder for changes and then trigger a specified action. It is used by `npm start` to watch the `./src/` folder and triggers `npm run build:dev` if any changes occur. -------------------------------------------------------------------------------- /lib/put-openrct2.d.ts-here.md: -------------------------------------------------------------------------------- 1 | Put the `openrct2.d.ts` file in this folder. 2 | 3 | You can take it from a OpenRCT2 installation or download it from here: 4 | 5 | https://raw.githubusercontent.com/OpenRCT2/OpenRCT2/develop/distribution/openrct2.d.ts 6 | 7 | For more information, please read the [README.md](../README.md). -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openrct2-typescript-plugin", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "openrct2-typescript-plugin", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@rollup/plugin-node-resolve": "^15.0.1", 13 | "@rollup/plugin-terser": "^0.4.0", 14 | "@rollup/plugin-typescript": "^11.0.0", 15 | "nodemon": "^2.0.22", 16 | "rollup": "^3.15.0", 17 | "tslib": "^2.5.0" 18 | } 19 | }, 20 | "node_modules/@jridgewell/gen-mapping": { 21 | "version": "0.3.3", 22 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 23 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 24 | "dev": true, 25 | "dependencies": { 26 | "@jridgewell/set-array": "^1.0.1", 27 | "@jridgewell/sourcemap-codec": "^1.4.10", 28 | "@jridgewell/trace-mapping": "^0.3.9" 29 | }, 30 | "engines": { 31 | "node": ">=6.0.0" 32 | } 33 | }, 34 | "node_modules/@jridgewell/resolve-uri": { 35 | "version": "3.1.0", 36 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", 37 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", 38 | "dev": true, 39 | "engines": { 40 | "node": ">=6.0.0" 41 | } 42 | }, 43 | "node_modules/@jridgewell/set-array": { 44 | "version": "1.1.2", 45 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 46 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 47 | "dev": true, 48 | "engines": { 49 | "node": ">=6.0.0" 50 | } 51 | }, 52 | "node_modules/@jridgewell/source-map": { 53 | "version": "0.3.3", 54 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", 55 | "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", 56 | "dev": true, 57 | "dependencies": { 58 | "@jridgewell/gen-mapping": "^0.3.0", 59 | "@jridgewell/trace-mapping": "^0.3.9" 60 | } 61 | }, 62 | "node_modules/@jridgewell/sourcemap-codec": { 63 | "version": "1.4.15", 64 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 65 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 66 | "dev": true 67 | }, 68 | "node_modules/@jridgewell/trace-mapping": { 69 | "version": "0.3.18", 70 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", 71 | "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", 72 | "dev": true, 73 | "dependencies": { 74 | "@jridgewell/resolve-uri": "3.1.0", 75 | "@jridgewell/sourcemap-codec": "1.4.14" 76 | } 77 | }, 78 | "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { 79 | "version": "1.4.14", 80 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", 81 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", 82 | "dev": true 83 | }, 84 | "node_modules/@rollup/plugin-node-resolve": { 85 | "version": "15.1.0", 86 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.1.0.tgz", 87 | "integrity": "sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==", 88 | "dev": true, 89 | "dependencies": { 90 | "@rollup/pluginutils": "^5.0.1", 91 | "@types/resolve": "1.20.2", 92 | "deepmerge": "^4.2.2", 93 | "is-builtin-module": "^3.2.1", 94 | "is-module": "^1.0.0", 95 | "resolve": "^1.22.1" 96 | }, 97 | "engines": { 98 | "node": ">=14.0.0" 99 | }, 100 | "peerDependencies": { 101 | "rollup": "^2.78.0||^3.0.0" 102 | }, 103 | "peerDependenciesMeta": { 104 | "rollup": { 105 | "optional": true 106 | } 107 | } 108 | }, 109 | "node_modules/@rollup/plugin-terser": { 110 | "version": "0.4.3", 111 | "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz", 112 | "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==", 113 | "dev": true, 114 | "dependencies": { 115 | "serialize-javascript": "^6.0.1", 116 | "smob": "^1.0.0", 117 | "terser": "^5.17.4" 118 | }, 119 | "engines": { 120 | "node": ">=14.0.0" 121 | }, 122 | "peerDependencies": { 123 | "rollup": "^2.x || ^3.x" 124 | }, 125 | "peerDependenciesMeta": { 126 | "rollup": { 127 | "optional": true 128 | } 129 | } 130 | }, 131 | "node_modules/@rollup/plugin-typescript": { 132 | "version": "11.1.2", 133 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.2.tgz", 134 | "integrity": "sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg==", 135 | "dev": true, 136 | "dependencies": { 137 | "@rollup/pluginutils": "^5.0.1", 138 | "resolve": "^1.22.1" 139 | }, 140 | "engines": { 141 | "node": ">=14.0.0" 142 | }, 143 | "peerDependencies": { 144 | "rollup": "^2.14.0||^3.0.0", 145 | "tslib": "*", 146 | "typescript": ">=3.7.0" 147 | }, 148 | "peerDependenciesMeta": { 149 | "rollup": { 150 | "optional": true 151 | }, 152 | "tslib": { 153 | "optional": true 154 | } 155 | } 156 | }, 157 | "node_modules/@rollup/pluginutils": { 158 | "version": "5.0.2", 159 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", 160 | "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", 161 | "dev": true, 162 | "dependencies": { 163 | "@types/estree": "^1.0.0", 164 | "estree-walker": "^2.0.2", 165 | "picomatch": "^2.3.1" 166 | }, 167 | "engines": { 168 | "node": ">=14.0.0" 169 | }, 170 | "peerDependencies": { 171 | "rollup": "^1.20.0||^2.0.0||^3.0.0" 172 | }, 173 | "peerDependenciesMeta": { 174 | "rollup": { 175 | "optional": true 176 | } 177 | } 178 | }, 179 | "node_modules/@types/estree": { 180 | "version": "1.0.1", 181 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", 182 | "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", 183 | "dev": true 184 | }, 185 | "node_modules/@types/resolve": { 186 | "version": "1.20.2", 187 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", 188 | "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", 189 | "dev": true 190 | }, 191 | "node_modules/abbrev": { 192 | "version": "1.1.1", 193 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 194 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 195 | "dev": true 196 | }, 197 | "node_modules/acorn": { 198 | "version": "8.9.0", 199 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", 200 | "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", 201 | "dev": true, 202 | "bin": { 203 | "acorn": "bin/acorn" 204 | }, 205 | "engines": { 206 | "node": ">=0.4.0" 207 | } 208 | }, 209 | "node_modules/anymatch": { 210 | "version": "3.1.3", 211 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 212 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 213 | "dev": true, 214 | "dependencies": { 215 | "normalize-path": "^3.0.0", 216 | "picomatch": "^2.0.4" 217 | }, 218 | "engines": { 219 | "node": ">= 8" 220 | } 221 | }, 222 | "node_modules/balanced-match": { 223 | "version": "1.0.2", 224 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 225 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 226 | "dev": true 227 | }, 228 | "node_modules/binary-extensions": { 229 | "version": "2.2.0", 230 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 231 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 232 | "dev": true, 233 | "engines": { 234 | "node": ">=8" 235 | } 236 | }, 237 | "node_modules/brace-expansion": { 238 | "version": "1.1.11", 239 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 240 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 241 | "dev": true, 242 | "dependencies": { 243 | "balanced-match": "^1.0.0", 244 | "concat-map": "0.0.1" 245 | } 246 | }, 247 | "node_modules/braces": { 248 | "version": "3.0.2", 249 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 250 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 251 | "dev": true, 252 | "dependencies": { 253 | "fill-range": "^7.0.1" 254 | }, 255 | "engines": { 256 | "node": ">=8" 257 | } 258 | }, 259 | "node_modules/buffer-from": { 260 | "version": "1.1.2", 261 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 262 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 263 | "dev": true 264 | }, 265 | "node_modules/builtin-modules": { 266 | "version": "3.3.0", 267 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", 268 | "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", 269 | "dev": true, 270 | "engines": { 271 | "node": ">=6" 272 | }, 273 | "funding": { 274 | "url": "https://github.com/sponsors/sindresorhus" 275 | } 276 | }, 277 | "node_modules/chokidar": { 278 | "version": "3.5.3", 279 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 280 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 281 | "dev": true, 282 | "funding": [ 283 | { 284 | "type": "individual", 285 | "url": "https://paulmillr.com/funding/" 286 | } 287 | ], 288 | "dependencies": { 289 | "anymatch": "~3.1.2", 290 | "braces": "~3.0.2", 291 | "glob-parent": "~5.1.2", 292 | "is-binary-path": "~2.1.0", 293 | "is-glob": "~4.0.1", 294 | "normalize-path": "~3.0.0", 295 | "readdirp": "~3.6.0" 296 | }, 297 | "engines": { 298 | "node": ">= 8.10.0" 299 | }, 300 | "optionalDependencies": { 301 | "fsevents": "~2.3.2" 302 | } 303 | }, 304 | "node_modules/commander": { 305 | "version": "2.20.3", 306 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 307 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 308 | "dev": true 309 | }, 310 | "node_modules/concat-map": { 311 | "version": "0.0.1", 312 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 313 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 314 | "dev": true 315 | }, 316 | "node_modules/debug": { 317 | "version": "3.2.7", 318 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 319 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 320 | "dev": true, 321 | "dependencies": { 322 | "ms": "^2.1.1" 323 | } 324 | }, 325 | "node_modules/deepmerge": { 326 | "version": "4.3.1", 327 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 328 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 329 | "dev": true, 330 | "engines": { 331 | "node": ">=0.10.0" 332 | } 333 | }, 334 | "node_modules/estree-walker": { 335 | "version": "2.0.2", 336 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 337 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 338 | "dev": true 339 | }, 340 | "node_modules/fill-range": { 341 | "version": "7.0.1", 342 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 343 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 344 | "dev": true, 345 | "dependencies": { 346 | "to-regex-range": "^5.0.1" 347 | }, 348 | "engines": { 349 | "node": ">=8" 350 | } 351 | }, 352 | "node_modules/fsevents": { 353 | "version": "2.3.2", 354 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 355 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 356 | "dev": true, 357 | "hasInstallScript": true, 358 | "optional": true, 359 | "os": [ 360 | "darwin" 361 | ], 362 | "engines": { 363 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 364 | } 365 | }, 366 | "node_modules/function-bind": { 367 | "version": "1.1.1", 368 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 369 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 370 | "dev": true 371 | }, 372 | "node_modules/glob-parent": { 373 | "version": "5.1.2", 374 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 375 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 376 | "dev": true, 377 | "dependencies": { 378 | "is-glob": "^4.0.1" 379 | }, 380 | "engines": { 381 | "node": ">= 6" 382 | } 383 | }, 384 | "node_modules/has": { 385 | "version": "1.0.3", 386 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 387 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 388 | "dev": true, 389 | "dependencies": { 390 | "function-bind": "^1.1.1" 391 | }, 392 | "engines": { 393 | "node": ">= 0.4.0" 394 | } 395 | }, 396 | "node_modules/has-flag": { 397 | "version": "3.0.0", 398 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 399 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 400 | "dev": true, 401 | "engines": { 402 | "node": ">=4" 403 | } 404 | }, 405 | "node_modules/ignore-by-default": { 406 | "version": "1.0.1", 407 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 408 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 409 | "dev": true 410 | }, 411 | "node_modules/is-binary-path": { 412 | "version": "2.1.0", 413 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 414 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 415 | "dev": true, 416 | "dependencies": { 417 | "binary-extensions": "^2.0.0" 418 | }, 419 | "engines": { 420 | "node": ">=8" 421 | } 422 | }, 423 | "node_modules/is-builtin-module": { 424 | "version": "3.2.1", 425 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", 426 | "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", 427 | "dev": true, 428 | "dependencies": { 429 | "builtin-modules": "^3.3.0" 430 | }, 431 | "engines": { 432 | "node": ">=6" 433 | }, 434 | "funding": { 435 | "url": "https://github.com/sponsors/sindresorhus" 436 | } 437 | }, 438 | "node_modules/is-core-module": { 439 | "version": "2.12.1", 440 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", 441 | "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", 442 | "dev": true, 443 | "dependencies": { 444 | "has": "^1.0.3" 445 | }, 446 | "funding": { 447 | "url": "https://github.com/sponsors/ljharb" 448 | } 449 | }, 450 | "node_modules/is-extglob": { 451 | "version": "2.1.1", 452 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 453 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 454 | "dev": true, 455 | "engines": { 456 | "node": ">=0.10.0" 457 | } 458 | }, 459 | "node_modules/is-glob": { 460 | "version": "4.0.3", 461 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 462 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 463 | "dev": true, 464 | "dependencies": { 465 | "is-extglob": "^2.1.1" 466 | }, 467 | "engines": { 468 | "node": ">=0.10.0" 469 | } 470 | }, 471 | "node_modules/is-module": { 472 | "version": "1.0.0", 473 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 474 | "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", 475 | "dev": true 476 | }, 477 | "node_modules/is-number": { 478 | "version": "7.0.0", 479 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 480 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 481 | "dev": true, 482 | "engines": { 483 | "node": ">=0.12.0" 484 | } 485 | }, 486 | "node_modules/minimatch": { 487 | "version": "3.1.2", 488 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 489 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 490 | "dev": true, 491 | "dependencies": { 492 | "brace-expansion": "^1.1.7" 493 | }, 494 | "engines": { 495 | "node": "*" 496 | } 497 | }, 498 | "node_modules/ms": { 499 | "version": "2.1.3", 500 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 501 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 502 | "dev": true 503 | }, 504 | "node_modules/nodemon": { 505 | "version": "2.0.22", 506 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", 507 | "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", 508 | "dev": true, 509 | "dependencies": { 510 | "chokidar": "^3.5.2", 511 | "debug": "^3.2.7", 512 | "ignore-by-default": "^1.0.1", 513 | "minimatch": "^3.1.2", 514 | "pstree.remy": "^1.1.8", 515 | "semver": "^5.7.1", 516 | "simple-update-notifier": "^1.0.7", 517 | "supports-color": "^5.5.0", 518 | "touch": "^3.1.0", 519 | "undefsafe": "^2.0.5" 520 | }, 521 | "bin": { 522 | "nodemon": "bin/nodemon.js" 523 | }, 524 | "engines": { 525 | "node": ">=8.10.0" 526 | }, 527 | "funding": { 528 | "type": "opencollective", 529 | "url": "https://opencollective.com/nodemon" 530 | } 531 | }, 532 | "node_modules/nopt": { 533 | "version": "1.0.10", 534 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 535 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", 536 | "dev": true, 537 | "dependencies": { 538 | "abbrev": "1" 539 | }, 540 | "bin": { 541 | "nopt": "bin/nopt.js" 542 | }, 543 | "engines": { 544 | "node": "*" 545 | } 546 | }, 547 | "node_modules/normalize-path": { 548 | "version": "3.0.0", 549 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 550 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 551 | "dev": true, 552 | "engines": { 553 | "node": ">=0.10.0" 554 | } 555 | }, 556 | "node_modules/path-parse": { 557 | "version": "1.0.7", 558 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 559 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 560 | "dev": true 561 | }, 562 | "node_modules/picomatch": { 563 | "version": "2.3.1", 564 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 565 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 566 | "dev": true, 567 | "engines": { 568 | "node": ">=8.6" 569 | }, 570 | "funding": { 571 | "url": "https://github.com/sponsors/jonschlinkert" 572 | } 573 | }, 574 | "node_modules/pstree.remy": { 575 | "version": "1.1.8", 576 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 577 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 578 | "dev": true 579 | }, 580 | "node_modules/randombytes": { 581 | "version": "2.1.0", 582 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 583 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 584 | "dev": true, 585 | "dependencies": { 586 | "safe-buffer": "^5.1.0" 587 | } 588 | }, 589 | "node_modules/readdirp": { 590 | "version": "3.6.0", 591 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 592 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 593 | "dev": true, 594 | "dependencies": { 595 | "picomatch": "^2.2.1" 596 | }, 597 | "engines": { 598 | "node": ">=8.10.0" 599 | } 600 | }, 601 | "node_modules/resolve": { 602 | "version": "1.22.2", 603 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", 604 | "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", 605 | "dev": true, 606 | "dependencies": { 607 | "is-core-module": "^2.11.0", 608 | "path-parse": "^1.0.7", 609 | "supports-preserve-symlinks-flag": "^1.0.0" 610 | }, 611 | "bin": { 612 | "resolve": "bin/resolve" 613 | }, 614 | "funding": { 615 | "url": "https://github.com/sponsors/ljharb" 616 | } 617 | }, 618 | "node_modules/rollup": { 619 | "version": "3.25.3", 620 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.3.tgz", 621 | "integrity": "sha512-ZT279hx8gszBj9uy5FfhoG4bZx8c+0A1sbqtr7Q3KNWIizpTdDEPZbV2xcbvHsnFp4MavCQYZyzApJ+virB8Yw==", 622 | "dev": true, 623 | "bin": { 624 | "rollup": "dist/bin/rollup" 625 | }, 626 | "engines": { 627 | "node": ">=14.18.0", 628 | "npm": ">=8.0.0" 629 | }, 630 | "optionalDependencies": { 631 | "fsevents": "~2.3.2" 632 | } 633 | }, 634 | "node_modules/safe-buffer": { 635 | "version": "5.2.1", 636 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 637 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 638 | "dev": true, 639 | "funding": [ 640 | { 641 | "type": "github", 642 | "url": "https://github.com/sponsors/feross" 643 | }, 644 | { 645 | "type": "patreon", 646 | "url": "https://www.patreon.com/feross" 647 | }, 648 | { 649 | "type": "consulting", 650 | "url": "https://feross.org/support" 651 | } 652 | ] 653 | }, 654 | "node_modules/semver": { 655 | "version": "5.7.1", 656 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 657 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 658 | "dev": true, 659 | "bin": { 660 | "semver": "bin/semver" 661 | } 662 | }, 663 | "node_modules/serialize-javascript": { 664 | "version": "6.0.1", 665 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", 666 | "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", 667 | "dev": true, 668 | "dependencies": { 669 | "randombytes": "^2.1.0" 670 | } 671 | }, 672 | "node_modules/simple-update-notifier": { 673 | "version": "1.1.0", 674 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", 675 | "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", 676 | "dev": true, 677 | "dependencies": { 678 | "semver": "~7.0.0" 679 | }, 680 | "engines": { 681 | "node": ">=8.10.0" 682 | } 683 | }, 684 | "node_modules/simple-update-notifier/node_modules/semver": { 685 | "version": "7.0.0", 686 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 687 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", 688 | "dev": true, 689 | "bin": { 690 | "semver": "bin/semver.js" 691 | } 692 | }, 693 | "node_modules/smob": { 694 | "version": "1.4.0", 695 | "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.0.tgz", 696 | "integrity": "sha512-MqR3fVulhjWuRNSMydnTlweu38UhQ0HXM4buStD/S3mc/BzX3CuM9OmhyQpmtYCvoYdl5ris6TI0ZqH355Ymqg==", 697 | "dev": true 698 | }, 699 | "node_modules/source-map": { 700 | "version": "0.6.1", 701 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 702 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 703 | "dev": true, 704 | "engines": { 705 | "node": ">=0.10.0" 706 | } 707 | }, 708 | "node_modules/source-map-support": { 709 | "version": "0.5.21", 710 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 711 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 712 | "dev": true, 713 | "dependencies": { 714 | "buffer-from": "^1.0.0", 715 | "source-map": "^0.6.0" 716 | } 717 | }, 718 | "node_modules/supports-color": { 719 | "version": "5.5.0", 720 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 721 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 722 | "dev": true, 723 | "dependencies": { 724 | "has-flag": "^3.0.0" 725 | }, 726 | "engines": { 727 | "node": ">=4" 728 | } 729 | }, 730 | "node_modules/supports-preserve-symlinks-flag": { 731 | "version": "1.0.0", 732 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 733 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 734 | "dev": true, 735 | "engines": { 736 | "node": ">= 0.4" 737 | }, 738 | "funding": { 739 | "url": "https://github.com/sponsors/ljharb" 740 | } 741 | }, 742 | "node_modules/terser": { 743 | "version": "5.18.2", 744 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.18.2.tgz", 745 | "integrity": "sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==", 746 | "dev": true, 747 | "dependencies": { 748 | "@jridgewell/source-map": "^0.3.3", 749 | "acorn": "^8.8.2", 750 | "commander": "^2.20.0", 751 | "source-map-support": "~0.5.20" 752 | }, 753 | "bin": { 754 | "terser": "bin/terser" 755 | }, 756 | "engines": { 757 | "node": ">=10" 758 | } 759 | }, 760 | "node_modules/to-regex-range": { 761 | "version": "5.0.1", 762 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 763 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 764 | "dev": true, 765 | "dependencies": { 766 | "is-number": "^7.0.0" 767 | }, 768 | "engines": { 769 | "node": ">=8.0" 770 | } 771 | }, 772 | "node_modules/touch": { 773 | "version": "3.1.0", 774 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 775 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 776 | "dev": true, 777 | "dependencies": { 778 | "nopt": "~1.0.10" 779 | }, 780 | "bin": { 781 | "nodetouch": "bin/nodetouch.js" 782 | } 783 | }, 784 | "node_modules/tslib": { 785 | "version": "2.6.0", 786 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", 787 | "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", 788 | "dev": true 789 | }, 790 | "node_modules/typescript": { 791 | "version": "5.1.5", 792 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.5.tgz", 793 | "integrity": "sha512-FOH+WN/DQjUvN6WgW+c4Ml3yi0PH+a/8q+kNIfRehv1wLhWONedw85iu+vQ39Wp49IzTJEsZ2lyLXpBF7mkF1g==", 794 | "dev": true, 795 | "peer": true, 796 | "bin": { 797 | "tsc": "bin/tsc", 798 | "tsserver": "bin/tsserver" 799 | }, 800 | "engines": { 801 | "node": ">=14.17" 802 | } 803 | }, 804 | "node_modules/undefsafe": { 805 | "version": "2.0.5", 806 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 807 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 808 | "dev": true 809 | } 810 | } 811 | } 812 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openrct2-typescript-plugin", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "nodemon --watch ./src --ext js,ts --exec \"npm run build:dev\"", 8 | "build": "rollup --config rollup.config.js --environment BUILD:production", 9 | "build:dev": "rollup --config rollup.config.js" 10 | }, 11 | "devDependencies": { 12 | "@rollup/plugin-node-resolve": "^15.0.1", 13 | "@rollup/plugin-terser": "^0.4.0", 14 | "@rollup/plugin-typescript": "^11.0.0", 15 | "nodemon": "^2.0.22", 16 | "rollup": "^3.15.0", 17 | "tslib": "^2.5.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from "@rollup/plugin-node-resolve"; 2 | import terser from "@rollup/plugin-terser"; 3 | import typescript from "@rollup/plugin-typescript"; 4 | import { exec } from "child_process"; 5 | import { homedir } from "os"; 6 | import { promisify } from "util"; 7 | 8 | 9 | const options = 10 | { 11 | /** 12 | * Change the file name of the output file here. 13 | */ 14 | filename: "my-plugin.js", 15 | 16 | /** 17 | * Determines in what build mode the plugin should be build. The default here takes 18 | * from the environment (ex. CLI arguments) with "development" as fallback. 19 | */ 20 | build: process.env.BUILD || "development" 21 | }; 22 | 23 | /** 24 | * Tip: if you change the path here to your personal user folder, 25 | * you can ignore this change in git with: 26 | * ``` 27 | * > git update-index --skip-worktree rollup.config.js 28 | * ``` 29 | * To accept changes on this file again, use: 30 | * ``` 31 | * > git update-index --no-skip-worktree rollup.config.js 32 | * ``` 33 | */ 34 | async function getOutput() 35 | { 36 | if (options.build !== "development") 37 | { 38 | return `./dist/${options.filename}`; 39 | } 40 | 41 | const platform = process.platform; 42 | const pluginPath = `OpenRCT2/plugin/${options.filename}`; 43 | 44 | if (platform === "win32") // Windows 45 | { 46 | const { stdout } = await promisify(exec)("powershell -command \"[Environment]::GetFolderPath('MyDocuments')\""); 47 | return `${stdout.trim()}/${pluginPath}`; 48 | } 49 | else if (platform === "darwin") // MacOS 50 | { 51 | return `${homedir()}/Library/Application Support/${pluginPath}`; 52 | } 53 | else // Linux 54 | { 55 | const configFolder = process.env.XDG_CONFIG_HOME || `${homedir()}/.config`; 56 | return `${configFolder}/${pluginPath}`; 57 | } 58 | } 59 | 60 | 61 | /** 62 | * @type {import("rollup").RollupOptions} 63 | */ 64 | const config = { 65 | input: "./src/plugin.ts", 66 | output: { 67 | file: await getOutput(), 68 | format: "iife", 69 | compact: true 70 | }, 71 | treeshake: "smallest", 72 | plugins: [ 73 | resolve(), 74 | typescript(), 75 | terser({ 76 | compress: { 77 | passes: 5, 78 | toplevel: true, 79 | unsafe: true 80 | }, 81 | format: { 82 | comments: false, 83 | quote_style: 1, 84 | wrap_iife: true, 85 | beautify: (options.build === "development"), 86 | } 87 | }) 88 | ] 89 | }; 90 | export default config; -------------------------------------------------------------------------------- /src/plugin.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { startup } from "./startup"; 4 | 5 | registerPlugin({ 6 | name: "Name of your plugin", 7 | version: "1.0", 8 | authors: [ "Your name" ], 9 | type: "remote", 10 | licence: "MIT", 11 | /** 12 | * This field determines which OpenRCT2 API version to use. It's best to always use the 13 | * latest release version, unless you want to use specific versions from a newer develop 14 | * version. Version 70 equals the v0.4.4 release. 15 | * @see https://github.com/OpenRCT2/OpenRCT2/blob/v0.4.4/src/openrct2/scripting/ScriptEngine.h#L50 16 | */ 17 | targetApiVersion: 70, 18 | main: startup, 19 | }); -------------------------------------------------------------------------------- /src/startup.ts: -------------------------------------------------------------------------------- 1 | function onClickMenuItem() 2 | { 3 | // Write code here that should happen when the player clicks the menu item under the map icon. 4 | 5 | console.log("Hello world!"); 6 | } 7 | 8 | 9 | export function startup() 10 | { 11 | // Write code here that should happen on startup of the plugin. 12 | 13 | 14 | 15 | // Register a menu item under the map icon: 16 | if (typeof ui !== "undefined") 17 | { 18 | ui.registerMenuItem("My plugin", () => onClickMenuItem()); 19 | } 20 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "forceConsistentCasingInFileNames": true, 5 | "module": "ES2020", 6 | "moduleResolution": "node", 7 | "noFallthroughCasesInSwitch": true, 8 | "noImplicitAny": true, 9 | "noImplicitOverride": true, 10 | "noImplicitReturns": true, 11 | "noImplicitThis": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "outDir": "out", 15 | "strict": true, 16 | "target": "es5", 17 | "lib": [ "es5" ] 18 | }, 19 | "include": [ 20 | "./lib/**/*.ts", 21 | "./src/**/*.ts", 22 | ], 23 | "noEmit": true 24 | } 25 | --------------------------------------------------------------------------------