├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src ├── builder.ts ├── cli.ts ├── frameworks │ └── nextjs.ts ├── kits │ ├── nextjs-shadcn.json │ └── nextjs.json ├── legacy │ ├── cli.js │ ├── lib.js │ └── next.js ├── lib.ts └── templator.ts ├── templates ├── auth.js ├── fastify-vite.config.js ├── fastify.js ├── next │ ├── globals.css │ ├── layout.tsx │ ├── metadata.js │ ├── page.tsx │ ├── shadcn.css │ ├── starter.tsx │ ├── startershadcn.tsx │ └── tsconfig.json └── starter.jsx └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | user.*sx 3 | .snaptail 4 | .env 5 | dist/ 6 | _playground/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Snaptail 2 | 3 | A tool for building web apps with React based on Nextjs with single file. 4 | 5 | Note that this is alpha version and things may change or break after upgrading. 6 | 7 | **Minimal setup:** 8 | 9 | ```sh 10 | echo 'export const App = () =>
Hello
' > start.tsx 11 | npx snaptail@latest run start.tsx 12 | ``` 13 | 14 | Or start with `init` command: 15 | 16 | ```sh 17 | npx snaptail@latest init 18 | npx snaptail@latest run starter.tsx 19 | ``` 20 | 21 | **Shadcn UI starter:** 22 | 23 | ```sh 24 | # with shadcn support, every component installed 25 | npx snaptail@latest init --ui shadcn 26 | npx snaptail@latest run starter.tsx 27 | ``` 28 | 29 | Next step is to redesign the CLI so that the init step does all heavy lifting. 30 | 31 | ## One file applications 32 | 33 | Snaptail **hides build system** under .snaptail dir and allows you to prototype and experiment with **single react file**. 34 | 35 | ### Includes: 36 | 37 | - tailwindcss added 38 | - allows you to define apis within the file 39 | - auto-detects packages and installs them 40 | - typescript support 41 | - shadcn support (alpha) 42 | 43 | ## Why 44 | 45 | When you want to build something small or try an idea out and you don't want to setup entire project for that. Use this. **You can deploy it too. It is nextjs app at the end.** 46 | 47 | Also it works great with LLMs, you can generate entire app and just paste it into the file and it will work. 48 | 49 | And this project explores how far we can take the idea of single source file applications. 50 | 51 | ## Usage 52 | 53 | The single tsx or jsx file needs to export App component and may export api array that defines api routes and handlers. 54 | 55 | The [starter template](./templates/next/starter.tsx) is the best way to explore it. You can use `npx snaptail init` and take a look. 56 | 57 | When you use snaptail init, by default tsconfig is created to help your IDE support ts type hints. 58 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snaptail", 3 | "version": "0.0.5", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "snaptail", 9 | "version": "0.0.5", 10 | "license": "MIT", 11 | "dependencies": { 12 | "bcryptjs": "^2.4.3", 13 | "chokidar": "^3.6.0", 14 | "commander": "^12.1.0", 15 | "detype": "^1.0.10", 16 | "fs-extra": "^11.2.0" 17 | }, 18 | "bin": { 19 | "snaptail": "dist/cli.js" 20 | }, 21 | "devDependencies": { 22 | "@types/fs-extra": "^11.0.4", 23 | "@types/node": "~20.10.0", 24 | "create-vite": "^5.5.1", 25 | "typescript": "^5.5.4", 26 | "vite": "^5.4.0" 27 | } 28 | }, 29 | "node_modules/@ampproject/remapping": { 30 | "version": "2.3.0", 31 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 32 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 33 | "dependencies": { 34 | "@jridgewell/gen-mapping": "^0.3.5", 35 | "@jridgewell/trace-mapping": "^0.3.24" 36 | }, 37 | "engines": { 38 | "node": ">=6.0.0" 39 | } 40 | }, 41 | "node_modules/@babel/code-frame": { 42 | "version": "7.24.7", 43 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", 44 | "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", 45 | "dependencies": { 46 | "@babel/highlight": "^7.24.7", 47 | "picocolors": "^1.0.0" 48 | }, 49 | "engines": { 50 | "node": ">=6.9.0" 51 | } 52 | }, 53 | "node_modules/@babel/compat-data": { 54 | "version": "7.25.4", 55 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", 56 | "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", 57 | "engines": { 58 | "node": ">=6.9.0" 59 | } 60 | }, 61 | "node_modules/@babel/core": { 62 | "version": "7.25.2", 63 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", 64 | "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", 65 | "dependencies": { 66 | "@ampproject/remapping": "^2.2.0", 67 | "@babel/code-frame": "^7.24.7", 68 | "@babel/generator": "^7.25.0", 69 | "@babel/helper-compilation-targets": "^7.25.2", 70 | "@babel/helper-module-transforms": "^7.25.2", 71 | "@babel/helpers": "^7.25.0", 72 | "@babel/parser": "^7.25.0", 73 | "@babel/template": "^7.25.0", 74 | "@babel/traverse": "^7.25.2", 75 | "@babel/types": "^7.25.2", 76 | "convert-source-map": "^2.0.0", 77 | "debug": "^4.1.0", 78 | "gensync": "^1.0.0-beta.2", 79 | "json5": "^2.2.3", 80 | "semver": "^6.3.1" 81 | }, 82 | "engines": { 83 | "node": ">=6.9.0" 84 | }, 85 | "funding": { 86 | "type": "opencollective", 87 | "url": "https://opencollective.com/babel" 88 | } 89 | }, 90 | "node_modules/@babel/generator": { 91 | "version": "7.25.4", 92 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.4.tgz", 93 | "integrity": "sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==", 94 | "dependencies": { 95 | "@babel/types": "^7.25.4", 96 | "@jridgewell/gen-mapping": "^0.3.5", 97 | "@jridgewell/trace-mapping": "^0.3.25", 98 | "jsesc": "^2.5.1" 99 | }, 100 | "engines": { 101 | "node": ">=6.9.0" 102 | } 103 | }, 104 | "node_modules/@babel/helper-annotate-as-pure": { 105 | "version": "7.24.7", 106 | "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", 107 | "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", 108 | "dependencies": { 109 | "@babel/types": "^7.24.7" 110 | }, 111 | "engines": { 112 | "node": ">=6.9.0" 113 | } 114 | }, 115 | "node_modules/@babel/helper-compilation-targets": { 116 | "version": "7.25.2", 117 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", 118 | "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", 119 | "dependencies": { 120 | "@babel/compat-data": "^7.25.2", 121 | "@babel/helper-validator-option": "^7.24.8", 122 | "browserslist": "^4.23.1", 123 | "lru-cache": "^5.1.1", 124 | "semver": "^6.3.1" 125 | }, 126 | "engines": { 127 | "node": ">=6.9.0" 128 | } 129 | }, 130 | "node_modules/@babel/helper-create-class-features-plugin": { 131 | "version": "7.25.4", 132 | "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", 133 | "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", 134 | "dependencies": { 135 | "@babel/helper-annotate-as-pure": "^7.24.7", 136 | "@babel/helper-member-expression-to-functions": "^7.24.8", 137 | "@babel/helper-optimise-call-expression": "^7.24.7", 138 | "@babel/helper-replace-supers": "^7.25.0", 139 | "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", 140 | "@babel/traverse": "^7.25.4", 141 | "semver": "^6.3.1" 142 | }, 143 | "engines": { 144 | "node": ">=6.9.0" 145 | }, 146 | "peerDependencies": { 147 | "@babel/core": "^7.0.0" 148 | } 149 | }, 150 | "node_modules/@babel/helper-member-expression-to-functions": { 151 | "version": "7.24.8", 152 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", 153 | "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", 154 | "dependencies": { 155 | "@babel/traverse": "^7.24.8", 156 | "@babel/types": "^7.24.8" 157 | }, 158 | "engines": { 159 | "node": ">=6.9.0" 160 | } 161 | }, 162 | "node_modules/@babel/helper-module-imports": { 163 | "version": "7.24.7", 164 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", 165 | "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", 166 | "dependencies": { 167 | "@babel/traverse": "^7.24.7", 168 | "@babel/types": "^7.24.7" 169 | }, 170 | "engines": { 171 | "node": ">=6.9.0" 172 | } 173 | }, 174 | "node_modules/@babel/helper-module-transforms": { 175 | "version": "7.25.2", 176 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", 177 | "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", 178 | "dependencies": { 179 | "@babel/helper-module-imports": "^7.24.7", 180 | "@babel/helper-simple-access": "^7.24.7", 181 | "@babel/helper-validator-identifier": "^7.24.7", 182 | "@babel/traverse": "^7.25.2" 183 | }, 184 | "engines": { 185 | "node": ">=6.9.0" 186 | }, 187 | "peerDependencies": { 188 | "@babel/core": "^7.0.0" 189 | } 190 | }, 191 | "node_modules/@babel/helper-optimise-call-expression": { 192 | "version": "7.24.7", 193 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", 194 | "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", 195 | "dependencies": { 196 | "@babel/types": "^7.24.7" 197 | }, 198 | "engines": { 199 | "node": ">=6.9.0" 200 | } 201 | }, 202 | "node_modules/@babel/helper-plugin-utils": { 203 | "version": "7.24.8", 204 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", 205 | "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", 206 | "engines": { 207 | "node": ">=6.9.0" 208 | } 209 | }, 210 | "node_modules/@babel/helper-replace-supers": { 211 | "version": "7.25.0", 212 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", 213 | "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", 214 | "dependencies": { 215 | "@babel/helper-member-expression-to-functions": "^7.24.8", 216 | "@babel/helper-optimise-call-expression": "^7.24.7", 217 | "@babel/traverse": "^7.25.0" 218 | }, 219 | "engines": { 220 | "node": ">=6.9.0" 221 | }, 222 | "peerDependencies": { 223 | "@babel/core": "^7.0.0" 224 | } 225 | }, 226 | "node_modules/@babel/helper-simple-access": { 227 | "version": "7.24.7", 228 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", 229 | "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", 230 | "dependencies": { 231 | "@babel/traverse": "^7.24.7", 232 | "@babel/types": "^7.24.7" 233 | }, 234 | "engines": { 235 | "node": ">=6.9.0" 236 | } 237 | }, 238 | "node_modules/@babel/helper-skip-transparent-expression-wrappers": { 239 | "version": "7.24.7", 240 | "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", 241 | "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", 242 | "dependencies": { 243 | "@babel/traverse": "^7.24.7", 244 | "@babel/types": "^7.24.7" 245 | }, 246 | "engines": { 247 | "node": ">=6.9.0" 248 | } 249 | }, 250 | "node_modules/@babel/helper-string-parser": { 251 | "version": "7.24.8", 252 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", 253 | "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", 254 | "engines": { 255 | "node": ">=6.9.0" 256 | } 257 | }, 258 | "node_modules/@babel/helper-validator-identifier": { 259 | "version": "7.24.7", 260 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", 261 | "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", 262 | "engines": { 263 | "node": ">=6.9.0" 264 | } 265 | }, 266 | "node_modules/@babel/helper-validator-option": { 267 | "version": "7.24.8", 268 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", 269 | "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", 270 | "engines": { 271 | "node": ">=6.9.0" 272 | } 273 | }, 274 | "node_modules/@babel/helpers": { 275 | "version": "7.25.0", 276 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", 277 | "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", 278 | "dependencies": { 279 | "@babel/template": "^7.25.0", 280 | "@babel/types": "^7.25.0" 281 | }, 282 | "engines": { 283 | "node": ">=6.9.0" 284 | } 285 | }, 286 | "node_modules/@babel/highlight": { 287 | "version": "7.24.7", 288 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", 289 | "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", 290 | "dependencies": { 291 | "@babel/helper-validator-identifier": "^7.24.7", 292 | "chalk": "^2.4.2", 293 | "js-tokens": "^4.0.0", 294 | "picocolors": "^1.0.0" 295 | }, 296 | "engines": { 297 | "node": ">=6.9.0" 298 | } 299 | }, 300 | "node_modules/@babel/parser": { 301 | "version": "7.25.4", 302 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", 303 | "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", 304 | "dependencies": { 305 | "@babel/types": "^7.25.4" 306 | }, 307 | "bin": { 308 | "parser": "bin/babel-parser.js" 309 | }, 310 | "engines": { 311 | "node": ">=6.0.0" 312 | } 313 | }, 314 | "node_modules/@babel/plugin-syntax-jsx": { 315 | "version": "7.24.7", 316 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", 317 | "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", 318 | "dependencies": { 319 | "@babel/helper-plugin-utils": "^7.24.7" 320 | }, 321 | "engines": { 322 | "node": ">=6.9.0" 323 | }, 324 | "peerDependencies": { 325 | "@babel/core": "^7.0.0-0" 326 | } 327 | }, 328 | "node_modules/@babel/plugin-syntax-typescript": { 329 | "version": "7.25.4", 330 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", 331 | "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", 332 | "dependencies": { 333 | "@babel/helper-plugin-utils": "^7.24.8" 334 | }, 335 | "engines": { 336 | "node": ">=6.9.0" 337 | }, 338 | "peerDependencies": { 339 | "@babel/core": "^7.0.0-0" 340 | } 341 | }, 342 | "node_modules/@babel/plugin-transform-modules-commonjs": { 343 | "version": "7.24.8", 344 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", 345 | "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", 346 | "dependencies": { 347 | "@babel/helper-module-transforms": "^7.24.8", 348 | "@babel/helper-plugin-utils": "^7.24.8", 349 | "@babel/helper-simple-access": "^7.24.7" 350 | }, 351 | "engines": { 352 | "node": ">=6.9.0" 353 | }, 354 | "peerDependencies": { 355 | "@babel/core": "^7.0.0-0" 356 | } 357 | }, 358 | "node_modules/@babel/plugin-transform-typescript": { 359 | "version": "7.25.2", 360 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", 361 | "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", 362 | "dependencies": { 363 | "@babel/helper-annotate-as-pure": "^7.24.7", 364 | "@babel/helper-create-class-features-plugin": "^7.25.0", 365 | "@babel/helper-plugin-utils": "^7.24.8", 366 | "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", 367 | "@babel/plugin-syntax-typescript": "^7.24.7" 368 | }, 369 | "engines": { 370 | "node": ">=6.9.0" 371 | }, 372 | "peerDependencies": { 373 | "@babel/core": "^7.0.0-0" 374 | } 375 | }, 376 | "node_modules/@babel/preset-typescript": { 377 | "version": "7.24.7", 378 | "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", 379 | "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", 380 | "dependencies": { 381 | "@babel/helper-plugin-utils": "^7.24.7", 382 | "@babel/helper-validator-option": "^7.24.7", 383 | "@babel/plugin-syntax-jsx": "^7.24.7", 384 | "@babel/plugin-transform-modules-commonjs": "^7.24.7", 385 | "@babel/plugin-transform-typescript": "^7.24.7" 386 | }, 387 | "engines": { 388 | "node": ">=6.9.0" 389 | }, 390 | "peerDependencies": { 391 | "@babel/core": "^7.0.0-0" 392 | } 393 | }, 394 | "node_modules/@babel/template": { 395 | "version": "7.25.0", 396 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", 397 | "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", 398 | "dependencies": { 399 | "@babel/code-frame": "^7.24.7", 400 | "@babel/parser": "^7.25.0", 401 | "@babel/types": "^7.25.0" 402 | }, 403 | "engines": { 404 | "node": ">=6.9.0" 405 | } 406 | }, 407 | "node_modules/@babel/traverse": { 408 | "version": "7.25.4", 409 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", 410 | "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", 411 | "dependencies": { 412 | "@babel/code-frame": "^7.24.7", 413 | "@babel/generator": "^7.25.4", 414 | "@babel/parser": "^7.25.4", 415 | "@babel/template": "^7.25.0", 416 | "@babel/types": "^7.25.4", 417 | "debug": "^4.3.1", 418 | "globals": "^11.1.0" 419 | }, 420 | "engines": { 421 | "node": ">=6.9.0" 422 | } 423 | }, 424 | "node_modules/@babel/types": { 425 | "version": "7.25.4", 426 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", 427 | "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", 428 | "dependencies": { 429 | "@babel/helper-string-parser": "^7.24.8", 430 | "@babel/helper-validator-identifier": "^7.24.7", 431 | "to-fast-properties": "^2.0.0" 432 | }, 433 | "engines": { 434 | "node": ">=6.9.0" 435 | } 436 | }, 437 | "node_modules/@esbuild/aix-ppc64": { 438 | "version": "0.21.5", 439 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 440 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 441 | "cpu": [ 442 | "ppc64" 443 | ], 444 | "dev": true, 445 | "optional": true, 446 | "os": [ 447 | "aix" 448 | ], 449 | "engines": { 450 | "node": ">=12" 451 | } 452 | }, 453 | "node_modules/@esbuild/android-arm": { 454 | "version": "0.21.5", 455 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 456 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 457 | "cpu": [ 458 | "arm" 459 | ], 460 | "dev": true, 461 | "optional": true, 462 | "os": [ 463 | "android" 464 | ], 465 | "engines": { 466 | "node": ">=12" 467 | } 468 | }, 469 | "node_modules/@esbuild/android-arm64": { 470 | "version": "0.21.5", 471 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 472 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 473 | "cpu": [ 474 | "arm64" 475 | ], 476 | "dev": true, 477 | "optional": true, 478 | "os": [ 479 | "android" 480 | ], 481 | "engines": { 482 | "node": ">=12" 483 | } 484 | }, 485 | "node_modules/@esbuild/android-x64": { 486 | "version": "0.21.5", 487 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 488 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 489 | "cpu": [ 490 | "x64" 491 | ], 492 | "dev": true, 493 | "optional": true, 494 | "os": [ 495 | "android" 496 | ], 497 | "engines": { 498 | "node": ">=12" 499 | } 500 | }, 501 | "node_modules/@esbuild/darwin-arm64": { 502 | "version": "0.21.5", 503 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 504 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 505 | "cpu": [ 506 | "arm64" 507 | ], 508 | "dev": true, 509 | "optional": true, 510 | "os": [ 511 | "darwin" 512 | ], 513 | "engines": { 514 | "node": ">=12" 515 | } 516 | }, 517 | "node_modules/@esbuild/darwin-x64": { 518 | "version": "0.21.5", 519 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 520 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 521 | "cpu": [ 522 | "x64" 523 | ], 524 | "dev": true, 525 | "optional": true, 526 | "os": [ 527 | "darwin" 528 | ], 529 | "engines": { 530 | "node": ">=12" 531 | } 532 | }, 533 | "node_modules/@esbuild/freebsd-arm64": { 534 | "version": "0.21.5", 535 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 536 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 537 | "cpu": [ 538 | "arm64" 539 | ], 540 | "dev": true, 541 | "optional": true, 542 | "os": [ 543 | "freebsd" 544 | ], 545 | "engines": { 546 | "node": ">=12" 547 | } 548 | }, 549 | "node_modules/@esbuild/freebsd-x64": { 550 | "version": "0.21.5", 551 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 552 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 553 | "cpu": [ 554 | "x64" 555 | ], 556 | "dev": true, 557 | "optional": true, 558 | "os": [ 559 | "freebsd" 560 | ], 561 | "engines": { 562 | "node": ">=12" 563 | } 564 | }, 565 | "node_modules/@esbuild/linux-arm": { 566 | "version": "0.21.5", 567 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 568 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 569 | "cpu": [ 570 | "arm" 571 | ], 572 | "dev": true, 573 | "optional": true, 574 | "os": [ 575 | "linux" 576 | ], 577 | "engines": { 578 | "node": ">=12" 579 | } 580 | }, 581 | "node_modules/@esbuild/linux-arm64": { 582 | "version": "0.21.5", 583 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 584 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 585 | "cpu": [ 586 | "arm64" 587 | ], 588 | "dev": true, 589 | "optional": true, 590 | "os": [ 591 | "linux" 592 | ], 593 | "engines": { 594 | "node": ">=12" 595 | } 596 | }, 597 | "node_modules/@esbuild/linux-ia32": { 598 | "version": "0.21.5", 599 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 600 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 601 | "cpu": [ 602 | "ia32" 603 | ], 604 | "dev": true, 605 | "optional": true, 606 | "os": [ 607 | "linux" 608 | ], 609 | "engines": { 610 | "node": ">=12" 611 | } 612 | }, 613 | "node_modules/@esbuild/linux-loong64": { 614 | "version": "0.21.5", 615 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 616 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 617 | "cpu": [ 618 | "loong64" 619 | ], 620 | "dev": true, 621 | "optional": true, 622 | "os": [ 623 | "linux" 624 | ], 625 | "engines": { 626 | "node": ">=12" 627 | } 628 | }, 629 | "node_modules/@esbuild/linux-mips64el": { 630 | "version": "0.21.5", 631 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 632 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 633 | "cpu": [ 634 | "mips64el" 635 | ], 636 | "dev": true, 637 | "optional": true, 638 | "os": [ 639 | "linux" 640 | ], 641 | "engines": { 642 | "node": ">=12" 643 | } 644 | }, 645 | "node_modules/@esbuild/linux-ppc64": { 646 | "version": "0.21.5", 647 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 648 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 649 | "cpu": [ 650 | "ppc64" 651 | ], 652 | "dev": true, 653 | "optional": true, 654 | "os": [ 655 | "linux" 656 | ], 657 | "engines": { 658 | "node": ">=12" 659 | } 660 | }, 661 | "node_modules/@esbuild/linux-riscv64": { 662 | "version": "0.21.5", 663 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 664 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 665 | "cpu": [ 666 | "riscv64" 667 | ], 668 | "dev": true, 669 | "optional": true, 670 | "os": [ 671 | "linux" 672 | ], 673 | "engines": { 674 | "node": ">=12" 675 | } 676 | }, 677 | "node_modules/@esbuild/linux-s390x": { 678 | "version": "0.21.5", 679 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 680 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 681 | "cpu": [ 682 | "s390x" 683 | ], 684 | "dev": true, 685 | "optional": true, 686 | "os": [ 687 | "linux" 688 | ], 689 | "engines": { 690 | "node": ">=12" 691 | } 692 | }, 693 | "node_modules/@esbuild/linux-x64": { 694 | "version": "0.21.5", 695 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 696 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 697 | "cpu": [ 698 | "x64" 699 | ], 700 | "dev": true, 701 | "optional": true, 702 | "os": [ 703 | "linux" 704 | ], 705 | "engines": { 706 | "node": ">=12" 707 | } 708 | }, 709 | "node_modules/@esbuild/netbsd-x64": { 710 | "version": "0.21.5", 711 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 712 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 713 | "cpu": [ 714 | "x64" 715 | ], 716 | "dev": true, 717 | "optional": true, 718 | "os": [ 719 | "netbsd" 720 | ], 721 | "engines": { 722 | "node": ">=12" 723 | } 724 | }, 725 | "node_modules/@esbuild/openbsd-x64": { 726 | "version": "0.21.5", 727 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 728 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 729 | "cpu": [ 730 | "x64" 731 | ], 732 | "dev": true, 733 | "optional": true, 734 | "os": [ 735 | "openbsd" 736 | ], 737 | "engines": { 738 | "node": ">=12" 739 | } 740 | }, 741 | "node_modules/@esbuild/sunos-x64": { 742 | "version": "0.21.5", 743 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 744 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 745 | "cpu": [ 746 | "x64" 747 | ], 748 | "dev": true, 749 | "optional": true, 750 | "os": [ 751 | "sunos" 752 | ], 753 | "engines": { 754 | "node": ">=12" 755 | } 756 | }, 757 | "node_modules/@esbuild/win32-arm64": { 758 | "version": "0.21.5", 759 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 760 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 761 | "cpu": [ 762 | "arm64" 763 | ], 764 | "dev": true, 765 | "optional": true, 766 | "os": [ 767 | "win32" 768 | ], 769 | "engines": { 770 | "node": ">=12" 771 | } 772 | }, 773 | "node_modules/@esbuild/win32-ia32": { 774 | "version": "0.21.5", 775 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 776 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 777 | "cpu": [ 778 | "ia32" 779 | ], 780 | "dev": true, 781 | "optional": true, 782 | "os": [ 783 | "win32" 784 | ], 785 | "engines": { 786 | "node": ">=12" 787 | } 788 | }, 789 | "node_modules/@esbuild/win32-x64": { 790 | "version": "0.21.5", 791 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 792 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 793 | "cpu": [ 794 | "x64" 795 | ], 796 | "dev": true, 797 | "optional": true, 798 | "os": [ 799 | "win32" 800 | ], 801 | "engines": { 802 | "node": ">=12" 803 | } 804 | }, 805 | "node_modules/@jridgewell/gen-mapping": { 806 | "version": "0.3.5", 807 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 808 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 809 | "dependencies": { 810 | "@jridgewell/set-array": "^1.2.1", 811 | "@jridgewell/sourcemap-codec": "^1.4.10", 812 | "@jridgewell/trace-mapping": "^0.3.24" 813 | }, 814 | "engines": { 815 | "node": ">=6.0.0" 816 | } 817 | }, 818 | "node_modules/@jridgewell/resolve-uri": { 819 | "version": "3.1.2", 820 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 821 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 822 | "engines": { 823 | "node": ">=6.0.0" 824 | } 825 | }, 826 | "node_modules/@jridgewell/set-array": { 827 | "version": "1.2.1", 828 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 829 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 830 | "engines": { 831 | "node": ">=6.0.0" 832 | } 833 | }, 834 | "node_modules/@jridgewell/sourcemap-codec": { 835 | "version": "1.5.0", 836 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 837 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" 838 | }, 839 | "node_modules/@jridgewell/trace-mapping": { 840 | "version": "0.3.25", 841 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 842 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 843 | "dependencies": { 844 | "@jridgewell/resolve-uri": "^3.1.0", 845 | "@jridgewell/sourcemap-codec": "^1.4.14" 846 | } 847 | }, 848 | "node_modules/@nodelib/fs.scandir": { 849 | "version": "2.1.5", 850 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 851 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 852 | "dependencies": { 853 | "@nodelib/fs.stat": "2.0.5", 854 | "run-parallel": "^1.1.9" 855 | }, 856 | "engines": { 857 | "node": ">= 8" 858 | } 859 | }, 860 | "node_modules/@nodelib/fs.stat": { 861 | "version": "2.0.5", 862 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 863 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 864 | "engines": { 865 | "node": ">= 8" 866 | } 867 | }, 868 | "node_modules/@nodelib/fs.walk": { 869 | "version": "1.2.8", 870 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 871 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 872 | "dependencies": { 873 | "@nodelib/fs.scandir": "2.1.5", 874 | "fastq": "^1.6.0" 875 | }, 876 | "engines": { 877 | "node": ">= 8" 878 | } 879 | }, 880 | "node_modules/@rollup/rollup-android-arm-eabi": { 881 | "version": "4.20.0", 882 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz", 883 | "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==", 884 | "cpu": [ 885 | "arm" 886 | ], 887 | "dev": true, 888 | "optional": true, 889 | "os": [ 890 | "android" 891 | ] 892 | }, 893 | "node_modules/@rollup/rollup-android-arm64": { 894 | "version": "4.20.0", 895 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz", 896 | "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==", 897 | "cpu": [ 898 | "arm64" 899 | ], 900 | "dev": true, 901 | "optional": true, 902 | "os": [ 903 | "android" 904 | ] 905 | }, 906 | "node_modules/@rollup/rollup-darwin-arm64": { 907 | "version": "4.20.0", 908 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz", 909 | "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==", 910 | "cpu": [ 911 | "arm64" 912 | ], 913 | "dev": true, 914 | "optional": true, 915 | "os": [ 916 | "darwin" 917 | ] 918 | }, 919 | "node_modules/@rollup/rollup-darwin-x64": { 920 | "version": "4.20.0", 921 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz", 922 | "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==", 923 | "cpu": [ 924 | "x64" 925 | ], 926 | "dev": true, 927 | "optional": true, 928 | "os": [ 929 | "darwin" 930 | ] 931 | }, 932 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 933 | "version": "4.20.0", 934 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz", 935 | "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==", 936 | "cpu": [ 937 | "arm" 938 | ], 939 | "dev": true, 940 | "optional": true, 941 | "os": [ 942 | "linux" 943 | ] 944 | }, 945 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 946 | "version": "4.20.0", 947 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz", 948 | "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==", 949 | "cpu": [ 950 | "arm" 951 | ], 952 | "dev": true, 953 | "optional": true, 954 | "os": [ 955 | "linux" 956 | ] 957 | }, 958 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 959 | "version": "4.20.0", 960 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz", 961 | "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==", 962 | "cpu": [ 963 | "arm64" 964 | ], 965 | "dev": true, 966 | "optional": true, 967 | "os": [ 968 | "linux" 969 | ] 970 | }, 971 | "node_modules/@rollup/rollup-linux-arm64-musl": { 972 | "version": "4.20.0", 973 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz", 974 | "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==", 975 | "cpu": [ 976 | "arm64" 977 | ], 978 | "dev": true, 979 | "optional": true, 980 | "os": [ 981 | "linux" 982 | ] 983 | }, 984 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 985 | "version": "4.20.0", 986 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz", 987 | "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==", 988 | "cpu": [ 989 | "ppc64" 990 | ], 991 | "dev": true, 992 | "optional": true, 993 | "os": [ 994 | "linux" 995 | ] 996 | }, 997 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 998 | "version": "4.20.0", 999 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz", 1000 | "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==", 1001 | "cpu": [ 1002 | "riscv64" 1003 | ], 1004 | "dev": true, 1005 | "optional": true, 1006 | "os": [ 1007 | "linux" 1008 | ] 1009 | }, 1010 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 1011 | "version": "4.20.0", 1012 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz", 1013 | "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==", 1014 | "cpu": [ 1015 | "s390x" 1016 | ], 1017 | "dev": true, 1018 | "optional": true, 1019 | "os": [ 1020 | "linux" 1021 | ] 1022 | }, 1023 | "node_modules/@rollup/rollup-linux-x64-gnu": { 1024 | "version": "4.20.0", 1025 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", 1026 | "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", 1027 | "cpu": [ 1028 | "x64" 1029 | ], 1030 | "dev": true, 1031 | "optional": true, 1032 | "os": [ 1033 | "linux" 1034 | ] 1035 | }, 1036 | "node_modules/@rollup/rollup-linux-x64-musl": { 1037 | "version": "4.20.0", 1038 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz", 1039 | "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==", 1040 | "cpu": [ 1041 | "x64" 1042 | ], 1043 | "dev": true, 1044 | "optional": true, 1045 | "os": [ 1046 | "linux" 1047 | ] 1048 | }, 1049 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 1050 | "version": "4.20.0", 1051 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz", 1052 | "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==", 1053 | "cpu": [ 1054 | "arm64" 1055 | ], 1056 | "dev": true, 1057 | "optional": true, 1058 | "os": [ 1059 | "win32" 1060 | ] 1061 | }, 1062 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 1063 | "version": "4.20.0", 1064 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz", 1065 | "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==", 1066 | "cpu": [ 1067 | "ia32" 1068 | ], 1069 | "dev": true, 1070 | "optional": true, 1071 | "os": [ 1072 | "win32" 1073 | ] 1074 | }, 1075 | "node_modules/@rollup/rollup-win32-x64-msvc": { 1076 | "version": "4.20.0", 1077 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz", 1078 | "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==", 1079 | "cpu": [ 1080 | "x64" 1081 | ], 1082 | "dev": true, 1083 | "optional": true, 1084 | "os": [ 1085 | "win32" 1086 | ] 1087 | }, 1088 | "node_modules/@types/estree": { 1089 | "version": "1.0.5", 1090 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 1091 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 1092 | "dev": true 1093 | }, 1094 | "node_modules/@types/fs-extra": { 1095 | "version": "11.0.4", 1096 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", 1097 | "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", 1098 | "dev": true, 1099 | "dependencies": { 1100 | "@types/jsonfile": "*", 1101 | "@types/node": "*" 1102 | } 1103 | }, 1104 | "node_modules/@types/jsonfile": { 1105 | "version": "6.1.4", 1106 | "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", 1107 | "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", 1108 | "dev": true, 1109 | "dependencies": { 1110 | "@types/node": "*" 1111 | } 1112 | }, 1113 | "node_modules/@types/node": { 1114 | "version": "20.10.8", 1115 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", 1116 | "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", 1117 | "dev": true, 1118 | "dependencies": { 1119 | "undici-types": "~5.26.4" 1120 | } 1121 | }, 1122 | "node_modules/@vue/compiler-core": { 1123 | "version": "3.4.38", 1124 | "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.38.tgz", 1125 | "integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==", 1126 | "dependencies": { 1127 | "@babel/parser": "^7.24.7", 1128 | "@vue/shared": "3.4.38", 1129 | "entities": "^4.5.0", 1130 | "estree-walker": "^2.0.2", 1131 | "source-map-js": "^1.2.0" 1132 | } 1133 | }, 1134 | "node_modules/@vue/compiler-dom": { 1135 | "version": "3.4.38", 1136 | "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz", 1137 | "integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==", 1138 | "dependencies": { 1139 | "@vue/compiler-core": "3.4.38", 1140 | "@vue/shared": "3.4.38" 1141 | } 1142 | }, 1143 | "node_modules/@vue/compiler-sfc": { 1144 | "version": "3.4.38", 1145 | "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz", 1146 | "integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==", 1147 | "dependencies": { 1148 | "@babel/parser": "^7.24.7", 1149 | "@vue/compiler-core": "3.4.38", 1150 | "@vue/compiler-dom": "3.4.38", 1151 | "@vue/compiler-ssr": "3.4.38", 1152 | "@vue/shared": "3.4.38", 1153 | "estree-walker": "^2.0.2", 1154 | "magic-string": "^0.30.10", 1155 | "postcss": "^8.4.40", 1156 | "source-map-js": "^1.2.0" 1157 | } 1158 | }, 1159 | "node_modules/@vue/compiler-ssr": { 1160 | "version": "3.4.38", 1161 | "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz", 1162 | "integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==", 1163 | "dependencies": { 1164 | "@vue/compiler-dom": "3.4.38", 1165 | "@vue/shared": "3.4.38" 1166 | } 1167 | }, 1168 | "node_modules/@vue/shared": { 1169 | "version": "3.4.38", 1170 | "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.38.tgz", 1171 | "integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==" 1172 | }, 1173 | "node_modules/@vuedx/compiler-sfc": { 1174 | "version": "0.7.1", 1175 | "resolved": "https://registry.npmjs.org/@vuedx/compiler-sfc/-/compiler-sfc-0.7.1.tgz", 1176 | "integrity": "sha512-M+j3COLqmTFgtsDOJEeeijUFCk7FF8x7vQsdORPPxipZF1S2vPvlcLg1bKVE6NF4wh7Gaq9Wvwv0zPi87pWRVA==", 1177 | "dependencies": { 1178 | "@vue/compiler-core": "^3.0.2", 1179 | "lru-cache": "^6.0.0", 1180 | "source-map": "^0.6.1" 1181 | }, 1182 | "funding": { 1183 | "type": "individual", 1184 | "url": "https://github.com/sponsors/znck" 1185 | } 1186 | }, 1187 | "node_modules/@vuedx/compiler-sfc/node_modules/lru-cache": { 1188 | "version": "6.0.0", 1189 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1190 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1191 | "dependencies": { 1192 | "yallist": "^4.0.0" 1193 | }, 1194 | "engines": { 1195 | "node": ">=10" 1196 | } 1197 | }, 1198 | "node_modules/@vuedx/compiler-sfc/node_modules/yallist": { 1199 | "version": "4.0.0", 1200 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1201 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1202 | }, 1203 | "node_modules/@vuedx/template-ast-types": { 1204 | "version": "0.7.1", 1205 | "resolved": "https://registry.npmjs.org/@vuedx/template-ast-types/-/template-ast-types-0.7.1.tgz", 1206 | "integrity": "sha512-Mqugk/F0lFN2u9bhimH6G1kSu2hhLi2WoqgCVxrMvgxm2kDc30DtdvVGRq+UgEmKVP61OudcMtZqkUoGQeFBUQ==", 1207 | "dependencies": { 1208 | "@vue/compiler-core": "^3.0.0" 1209 | }, 1210 | "funding": { 1211 | "type": "individual", 1212 | "url": "https://github.com/sponsors/znck" 1213 | } 1214 | }, 1215 | "node_modules/ansi-styles": { 1216 | "version": "3.2.1", 1217 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1218 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1219 | "dependencies": { 1220 | "color-convert": "^1.9.0" 1221 | }, 1222 | "engines": { 1223 | "node": ">=4" 1224 | } 1225 | }, 1226 | "node_modules/anymatch": { 1227 | "version": "3.1.3", 1228 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 1229 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 1230 | "dependencies": { 1231 | "normalize-path": "^3.0.0", 1232 | "picomatch": "^2.0.4" 1233 | }, 1234 | "engines": { 1235 | "node": ">= 8" 1236 | } 1237 | }, 1238 | "node_modules/array-buffer-byte-length": { 1239 | "version": "1.0.1", 1240 | "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", 1241 | "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", 1242 | "dependencies": { 1243 | "call-bind": "^1.0.5", 1244 | "is-array-buffer": "^3.0.4" 1245 | }, 1246 | "engines": { 1247 | "node": ">= 0.4" 1248 | }, 1249 | "funding": { 1250 | "url": "https://github.com/sponsors/ljharb" 1251 | } 1252 | }, 1253 | "node_modules/arraybuffer.prototype.slice": { 1254 | "version": "1.0.3", 1255 | "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", 1256 | "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", 1257 | "dependencies": { 1258 | "array-buffer-byte-length": "^1.0.1", 1259 | "call-bind": "^1.0.5", 1260 | "define-properties": "^1.2.1", 1261 | "es-abstract": "^1.22.3", 1262 | "es-errors": "^1.2.1", 1263 | "get-intrinsic": "^1.2.3", 1264 | "is-array-buffer": "^3.0.4", 1265 | "is-shared-array-buffer": "^1.0.2" 1266 | }, 1267 | "engines": { 1268 | "node": ">= 0.4" 1269 | }, 1270 | "funding": { 1271 | "url": "https://github.com/sponsors/ljharb" 1272 | } 1273 | }, 1274 | "node_modules/available-typed-arrays": { 1275 | "version": "1.0.7", 1276 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", 1277 | "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", 1278 | "dependencies": { 1279 | "possible-typed-array-names": "^1.0.0" 1280 | }, 1281 | "engines": { 1282 | "node": ">= 0.4" 1283 | }, 1284 | "funding": { 1285 | "url": "https://github.com/sponsors/ljharb" 1286 | } 1287 | }, 1288 | "node_modules/bcryptjs": { 1289 | "version": "2.4.3", 1290 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", 1291 | "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" 1292 | }, 1293 | "node_modules/binary-extensions": { 1294 | "version": "2.3.0", 1295 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 1296 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 1297 | "engines": { 1298 | "node": ">=8" 1299 | }, 1300 | "funding": { 1301 | "url": "https://github.com/sponsors/sindresorhus" 1302 | } 1303 | }, 1304 | "node_modules/braces": { 1305 | "version": "3.0.3", 1306 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 1307 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 1308 | "dependencies": { 1309 | "fill-range": "^7.1.1" 1310 | }, 1311 | "engines": { 1312 | "node": ">=8" 1313 | } 1314 | }, 1315 | "node_modules/browserslist": { 1316 | "version": "4.23.3", 1317 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", 1318 | "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", 1319 | "funding": [ 1320 | { 1321 | "type": "opencollective", 1322 | "url": "https://opencollective.com/browserslist" 1323 | }, 1324 | { 1325 | "type": "tidelift", 1326 | "url": "https://tidelift.com/funding/github/npm/browserslist" 1327 | }, 1328 | { 1329 | "type": "github", 1330 | "url": "https://github.com/sponsors/ai" 1331 | } 1332 | ], 1333 | "dependencies": { 1334 | "caniuse-lite": "^1.0.30001646", 1335 | "electron-to-chromium": "^1.5.4", 1336 | "node-releases": "^2.0.18", 1337 | "update-browserslist-db": "^1.1.0" 1338 | }, 1339 | "bin": { 1340 | "browserslist": "cli.js" 1341 | }, 1342 | "engines": { 1343 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 1344 | } 1345 | }, 1346 | "node_modules/call-bind": { 1347 | "version": "1.0.7", 1348 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 1349 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 1350 | "dependencies": { 1351 | "es-define-property": "^1.0.0", 1352 | "es-errors": "^1.3.0", 1353 | "function-bind": "^1.1.2", 1354 | "get-intrinsic": "^1.2.4", 1355 | "set-function-length": "^1.2.1" 1356 | }, 1357 | "engines": { 1358 | "node": ">= 0.4" 1359 | }, 1360 | "funding": { 1361 | "url": "https://github.com/sponsors/ljharb" 1362 | } 1363 | }, 1364 | "node_modules/caniuse-lite": { 1365 | "version": "1.0.30001651", 1366 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", 1367 | "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", 1368 | "funding": [ 1369 | { 1370 | "type": "opencollective", 1371 | "url": "https://opencollective.com/browserslist" 1372 | }, 1373 | { 1374 | "type": "tidelift", 1375 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 1376 | }, 1377 | { 1378 | "type": "github", 1379 | "url": "https://github.com/sponsors/ai" 1380 | } 1381 | ] 1382 | }, 1383 | "node_modules/chalk": { 1384 | "version": "2.4.2", 1385 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 1386 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 1387 | "dependencies": { 1388 | "ansi-styles": "^3.2.1", 1389 | "escape-string-regexp": "^1.0.5", 1390 | "supports-color": "^5.3.0" 1391 | }, 1392 | "engines": { 1393 | "node": ">=4" 1394 | } 1395 | }, 1396 | "node_modules/chokidar": { 1397 | "version": "3.6.0", 1398 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 1399 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 1400 | "dependencies": { 1401 | "anymatch": "~3.1.2", 1402 | "braces": "~3.0.2", 1403 | "glob-parent": "~5.1.2", 1404 | "is-binary-path": "~2.1.0", 1405 | "is-glob": "~4.0.1", 1406 | "normalize-path": "~3.0.0", 1407 | "readdirp": "~3.6.0" 1408 | }, 1409 | "engines": { 1410 | "node": ">= 8.10.0" 1411 | }, 1412 | "funding": { 1413 | "url": "https://paulmillr.com/funding/" 1414 | }, 1415 | "optionalDependencies": { 1416 | "fsevents": "~2.3.2" 1417 | } 1418 | }, 1419 | "node_modules/color-convert": { 1420 | "version": "1.9.3", 1421 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1422 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1423 | "dependencies": { 1424 | "color-name": "1.1.3" 1425 | } 1426 | }, 1427 | "node_modules/color-name": { 1428 | "version": "1.1.3", 1429 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1430 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" 1431 | }, 1432 | "node_modules/commander": { 1433 | "version": "12.1.0", 1434 | "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", 1435 | "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", 1436 | "engines": { 1437 | "node": ">=18" 1438 | } 1439 | }, 1440 | "node_modules/convert-source-map": { 1441 | "version": "2.0.0", 1442 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 1443 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" 1444 | }, 1445 | "node_modules/create-vite": { 1446 | "version": "5.5.1", 1447 | "resolved": "https://registry.npmjs.org/create-vite/-/create-vite-5.5.1.tgz", 1448 | "integrity": "sha512-+mHQ/4JYyDyY/7TmYIh1FYuGZdUQTrMl8JCyhiioVapAwpTrUyGMIP8qrcFfXUuYAk+DuiAbI/6xOhM4MS7rQQ==", 1449 | "dev": true, 1450 | "bin": { 1451 | "create-vite": "index.js", 1452 | "cva": "index.js" 1453 | }, 1454 | "engines": { 1455 | "node": "^18.0.0 || >=20.0.0" 1456 | }, 1457 | "funding": { 1458 | "url": "https://github.com/vitejs/vite?sponsor=1" 1459 | } 1460 | }, 1461 | "node_modules/data-view-buffer": { 1462 | "version": "1.0.1", 1463 | "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", 1464 | "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", 1465 | "dependencies": { 1466 | "call-bind": "^1.0.6", 1467 | "es-errors": "^1.3.0", 1468 | "is-data-view": "^1.0.1" 1469 | }, 1470 | "engines": { 1471 | "node": ">= 0.4" 1472 | }, 1473 | "funding": { 1474 | "url": "https://github.com/sponsors/ljharb" 1475 | } 1476 | }, 1477 | "node_modules/data-view-byte-length": { 1478 | "version": "1.0.1", 1479 | "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", 1480 | "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", 1481 | "dependencies": { 1482 | "call-bind": "^1.0.7", 1483 | "es-errors": "^1.3.0", 1484 | "is-data-view": "^1.0.1" 1485 | }, 1486 | "engines": { 1487 | "node": ">= 0.4" 1488 | }, 1489 | "funding": { 1490 | "url": "https://github.com/sponsors/ljharb" 1491 | } 1492 | }, 1493 | "node_modules/data-view-byte-offset": { 1494 | "version": "1.0.0", 1495 | "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", 1496 | "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", 1497 | "dependencies": { 1498 | "call-bind": "^1.0.6", 1499 | "es-errors": "^1.3.0", 1500 | "is-data-view": "^1.0.1" 1501 | }, 1502 | "engines": { 1503 | "node": ">= 0.4" 1504 | }, 1505 | "funding": { 1506 | "url": "https://github.com/sponsors/ljharb" 1507 | } 1508 | }, 1509 | "node_modules/debug": { 1510 | "version": "4.3.6", 1511 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", 1512 | "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", 1513 | "dependencies": { 1514 | "ms": "2.1.2" 1515 | }, 1516 | "engines": { 1517 | "node": ">=6.0" 1518 | }, 1519 | "peerDependenciesMeta": { 1520 | "supports-color": { 1521 | "optional": true 1522 | } 1523 | } 1524 | }, 1525 | "node_modules/define-data-property": { 1526 | "version": "1.1.4", 1527 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 1528 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 1529 | "dependencies": { 1530 | "es-define-property": "^1.0.0", 1531 | "es-errors": "^1.3.0", 1532 | "gopd": "^1.0.1" 1533 | }, 1534 | "engines": { 1535 | "node": ">= 0.4" 1536 | }, 1537 | "funding": { 1538 | "url": "https://github.com/sponsors/ljharb" 1539 | } 1540 | }, 1541 | "node_modules/define-properties": { 1542 | "version": "1.2.1", 1543 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", 1544 | "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", 1545 | "dependencies": { 1546 | "define-data-property": "^1.0.1", 1547 | "has-property-descriptors": "^1.0.0", 1548 | "object-keys": "^1.1.1" 1549 | }, 1550 | "engines": { 1551 | "node": ">= 0.4" 1552 | }, 1553 | "funding": { 1554 | "url": "https://github.com/sponsors/ljharb" 1555 | } 1556 | }, 1557 | "node_modules/detype": { 1558 | "version": "1.0.10", 1559 | "resolved": "https://registry.npmjs.org/detype/-/detype-1.0.10.tgz", 1560 | "integrity": "sha512-JQt5G1BK7kGVnuqcFgcVUoG7qzN7f3vGp0FbmyC+AO0LwvRpjVqb6O9tlAHMsWnoR/RcoDn109ksr2Tf+CqmRg==", 1561 | "dependencies": { 1562 | "@babel/core": "^7.25.2", 1563 | "@babel/preset-typescript": "^7.24.7", 1564 | "@babel/traverse": "^7.25.3", 1565 | "@vue/compiler-dom": "^3.4.37", 1566 | "@vue/compiler-sfc": "^3.4.37", 1567 | "@vuedx/compiler-sfc": "0.7.1", 1568 | "@vuedx/template-ast-types": "0.7.1", 1569 | "fast-glob": "^3.3.2", 1570 | "prettier": "^3.3.3", 1571 | "string.prototype.replaceall": "^1.0.10" 1572 | }, 1573 | "bin": { 1574 | "detype": "detype.js" 1575 | } 1576 | }, 1577 | "node_modules/electron-to-chromium": { 1578 | "version": "1.5.13", 1579 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", 1580 | "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==" 1581 | }, 1582 | "node_modules/entities": { 1583 | "version": "4.5.0", 1584 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 1585 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 1586 | "engines": { 1587 | "node": ">=0.12" 1588 | }, 1589 | "funding": { 1590 | "url": "https://github.com/fb55/entities?sponsor=1" 1591 | } 1592 | }, 1593 | "node_modules/es-abstract": { 1594 | "version": "1.23.3", 1595 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", 1596 | "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", 1597 | "dependencies": { 1598 | "array-buffer-byte-length": "^1.0.1", 1599 | "arraybuffer.prototype.slice": "^1.0.3", 1600 | "available-typed-arrays": "^1.0.7", 1601 | "call-bind": "^1.0.7", 1602 | "data-view-buffer": "^1.0.1", 1603 | "data-view-byte-length": "^1.0.1", 1604 | "data-view-byte-offset": "^1.0.0", 1605 | "es-define-property": "^1.0.0", 1606 | "es-errors": "^1.3.0", 1607 | "es-object-atoms": "^1.0.0", 1608 | "es-set-tostringtag": "^2.0.3", 1609 | "es-to-primitive": "^1.2.1", 1610 | "function.prototype.name": "^1.1.6", 1611 | "get-intrinsic": "^1.2.4", 1612 | "get-symbol-description": "^1.0.2", 1613 | "globalthis": "^1.0.3", 1614 | "gopd": "^1.0.1", 1615 | "has-property-descriptors": "^1.0.2", 1616 | "has-proto": "^1.0.3", 1617 | "has-symbols": "^1.0.3", 1618 | "hasown": "^2.0.2", 1619 | "internal-slot": "^1.0.7", 1620 | "is-array-buffer": "^3.0.4", 1621 | "is-callable": "^1.2.7", 1622 | "is-data-view": "^1.0.1", 1623 | "is-negative-zero": "^2.0.3", 1624 | "is-regex": "^1.1.4", 1625 | "is-shared-array-buffer": "^1.0.3", 1626 | "is-string": "^1.0.7", 1627 | "is-typed-array": "^1.1.13", 1628 | "is-weakref": "^1.0.2", 1629 | "object-inspect": "^1.13.1", 1630 | "object-keys": "^1.1.1", 1631 | "object.assign": "^4.1.5", 1632 | "regexp.prototype.flags": "^1.5.2", 1633 | "safe-array-concat": "^1.1.2", 1634 | "safe-regex-test": "^1.0.3", 1635 | "string.prototype.trim": "^1.2.9", 1636 | "string.prototype.trimend": "^1.0.8", 1637 | "string.prototype.trimstart": "^1.0.8", 1638 | "typed-array-buffer": "^1.0.2", 1639 | "typed-array-byte-length": "^1.0.1", 1640 | "typed-array-byte-offset": "^1.0.2", 1641 | "typed-array-length": "^1.0.6", 1642 | "unbox-primitive": "^1.0.2", 1643 | "which-typed-array": "^1.1.15" 1644 | }, 1645 | "engines": { 1646 | "node": ">= 0.4" 1647 | }, 1648 | "funding": { 1649 | "url": "https://github.com/sponsors/ljharb" 1650 | } 1651 | }, 1652 | "node_modules/es-define-property": { 1653 | "version": "1.0.0", 1654 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 1655 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 1656 | "dependencies": { 1657 | "get-intrinsic": "^1.2.4" 1658 | }, 1659 | "engines": { 1660 | "node": ">= 0.4" 1661 | } 1662 | }, 1663 | "node_modules/es-errors": { 1664 | "version": "1.3.0", 1665 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1666 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1667 | "engines": { 1668 | "node": ">= 0.4" 1669 | } 1670 | }, 1671 | "node_modules/es-object-atoms": { 1672 | "version": "1.0.0", 1673 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", 1674 | "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", 1675 | "dependencies": { 1676 | "es-errors": "^1.3.0" 1677 | }, 1678 | "engines": { 1679 | "node": ">= 0.4" 1680 | } 1681 | }, 1682 | "node_modules/es-set-tostringtag": { 1683 | "version": "2.0.3", 1684 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", 1685 | "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", 1686 | "dependencies": { 1687 | "get-intrinsic": "^1.2.4", 1688 | "has-tostringtag": "^1.0.2", 1689 | "hasown": "^2.0.1" 1690 | }, 1691 | "engines": { 1692 | "node": ">= 0.4" 1693 | } 1694 | }, 1695 | "node_modules/es-to-primitive": { 1696 | "version": "1.2.1", 1697 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 1698 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 1699 | "dependencies": { 1700 | "is-callable": "^1.1.4", 1701 | "is-date-object": "^1.0.1", 1702 | "is-symbol": "^1.0.2" 1703 | }, 1704 | "engines": { 1705 | "node": ">= 0.4" 1706 | }, 1707 | "funding": { 1708 | "url": "https://github.com/sponsors/ljharb" 1709 | } 1710 | }, 1711 | "node_modules/esbuild": { 1712 | "version": "0.21.5", 1713 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 1714 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 1715 | "dev": true, 1716 | "hasInstallScript": true, 1717 | "bin": { 1718 | "esbuild": "bin/esbuild" 1719 | }, 1720 | "engines": { 1721 | "node": ">=12" 1722 | }, 1723 | "optionalDependencies": { 1724 | "@esbuild/aix-ppc64": "0.21.5", 1725 | "@esbuild/android-arm": "0.21.5", 1726 | "@esbuild/android-arm64": "0.21.5", 1727 | "@esbuild/android-x64": "0.21.5", 1728 | "@esbuild/darwin-arm64": "0.21.5", 1729 | "@esbuild/darwin-x64": "0.21.5", 1730 | "@esbuild/freebsd-arm64": "0.21.5", 1731 | "@esbuild/freebsd-x64": "0.21.5", 1732 | "@esbuild/linux-arm": "0.21.5", 1733 | "@esbuild/linux-arm64": "0.21.5", 1734 | "@esbuild/linux-ia32": "0.21.5", 1735 | "@esbuild/linux-loong64": "0.21.5", 1736 | "@esbuild/linux-mips64el": "0.21.5", 1737 | "@esbuild/linux-ppc64": "0.21.5", 1738 | "@esbuild/linux-riscv64": "0.21.5", 1739 | "@esbuild/linux-s390x": "0.21.5", 1740 | "@esbuild/linux-x64": "0.21.5", 1741 | "@esbuild/netbsd-x64": "0.21.5", 1742 | "@esbuild/openbsd-x64": "0.21.5", 1743 | "@esbuild/sunos-x64": "0.21.5", 1744 | "@esbuild/win32-arm64": "0.21.5", 1745 | "@esbuild/win32-ia32": "0.21.5", 1746 | "@esbuild/win32-x64": "0.21.5" 1747 | } 1748 | }, 1749 | "node_modules/escalade": { 1750 | "version": "3.1.2", 1751 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", 1752 | "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", 1753 | "engines": { 1754 | "node": ">=6" 1755 | } 1756 | }, 1757 | "node_modules/escape-string-regexp": { 1758 | "version": "1.0.5", 1759 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 1760 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 1761 | "engines": { 1762 | "node": ">=0.8.0" 1763 | } 1764 | }, 1765 | "node_modules/estree-walker": { 1766 | "version": "2.0.2", 1767 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 1768 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" 1769 | }, 1770 | "node_modules/fast-glob": { 1771 | "version": "3.3.2", 1772 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", 1773 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 1774 | "dependencies": { 1775 | "@nodelib/fs.stat": "^2.0.2", 1776 | "@nodelib/fs.walk": "^1.2.3", 1777 | "glob-parent": "^5.1.2", 1778 | "merge2": "^1.3.0", 1779 | "micromatch": "^4.0.4" 1780 | }, 1781 | "engines": { 1782 | "node": ">=8.6.0" 1783 | } 1784 | }, 1785 | "node_modules/fastq": { 1786 | "version": "1.17.1", 1787 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", 1788 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 1789 | "dependencies": { 1790 | "reusify": "^1.0.4" 1791 | } 1792 | }, 1793 | "node_modules/fill-range": { 1794 | "version": "7.1.1", 1795 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1796 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1797 | "dependencies": { 1798 | "to-regex-range": "^5.0.1" 1799 | }, 1800 | "engines": { 1801 | "node": ">=8" 1802 | } 1803 | }, 1804 | "node_modules/for-each": { 1805 | "version": "0.3.3", 1806 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 1807 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 1808 | "dependencies": { 1809 | "is-callable": "^1.1.3" 1810 | } 1811 | }, 1812 | "node_modules/fs-extra": { 1813 | "version": "11.2.0", 1814 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", 1815 | "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", 1816 | "dependencies": { 1817 | "graceful-fs": "^4.2.0", 1818 | "jsonfile": "^6.0.1", 1819 | "universalify": "^2.0.0" 1820 | }, 1821 | "engines": { 1822 | "node": ">=14.14" 1823 | } 1824 | }, 1825 | "node_modules/fsevents": { 1826 | "version": "2.3.3", 1827 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1828 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1829 | "hasInstallScript": true, 1830 | "optional": true, 1831 | "os": [ 1832 | "darwin" 1833 | ], 1834 | "engines": { 1835 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1836 | } 1837 | }, 1838 | "node_modules/function-bind": { 1839 | "version": "1.1.2", 1840 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1841 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1842 | "funding": { 1843 | "url": "https://github.com/sponsors/ljharb" 1844 | } 1845 | }, 1846 | "node_modules/function.prototype.name": { 1847 | "version": "1.1.6", 1848 | "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", 1849 | "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", 1850 | "dependencies": { 1851 | "call-bind": "^1.0.2", 1852 | "define-properties": "^1.2.0", 1853 | "es-abstract": "^1.22.1", 1854 | "functions-have-names": "^1.2.3" 1855 | }, 1856 | "engines": { 1857 | "node": ">= 0.4" 1858 | }, 1859 | "funding": { 1860 | "url": "https://github.com/sponsors/ljharb" 1861 | } 1862 | }, 1863 | "node_modules/functions-have-names": { 1864 | "version": "1.2.3", 1865 | "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", 1866 | "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", 1867 | "funding": { 1868 | "url": "https://github.com/sponsors/ljharb" 1869 | } 1870 | }, 1871 | "node_modules/gensync": { 1872 | "version": "1.0.0-beta.2", 1873 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 1874 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 1875 | "engines": { 1876 | "node": ">=6.9.0" 1877 | } 1878 | }, 1879 | "node_modules/get-intrinsic": { 1880 | "version": "1.2.4", 1881 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 1882 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 1883 | "dependencies": { 1884 | "es-errors": "^1.3.0", 1885 | "function-bind": "^1.1.2", 1886 | "has-proto": "^1.0.1", 1887 | "has-symbols": "^1.0.3", 1888 | "hasown": "^2.0.0" 1889 | }, 1890 | "engines": { 1891 | "node": ">= 0.4" 1892 | }, 1893 | "funding": { 1894 | "url": "https://github.com/sponsors/ljharb" 1895 | } 1896 | }, 1897 | "node_modules/get-symbol-description": { 1898 | "version": "1.0.2", 1899 | "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", 1900 | "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", 1901 | "dependencies": { 1902 | "call-bind": "^1.0.5", 1903 | "es-errors": "^1.3.0", 1904 | "get-intrinsic": "^1.2.4" 1905 | }, 1906 | "engines": { 1907 | "node": ">= 0.4" 1908 | }, 1909 | "funding": { 1910 | "url": "https://github.com/sponsors/ljharb" 1911 | } 1912 | }, 1913 | "node_modules/glob-parent": { 1914 | "version": "5.1.2", 1915 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1916 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1917 | "dependencies": { 1918 | "is-glob": "^4.0.1" 1919 | }, 1920 | "engines": { 1921 | "node": ">= 6" 1922 | } 1923 | }, 1924 | "node_modules/globals": { 1925 | "version": "11.12.0", 1926 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1927 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 1928 | "engines": { 1929 | "node": ">=4" 1930 | } 1931 | }, 1932 | "node_modules/globalthis": { 1933 | "version": "1.0.4", 1934 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", 1935 | "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", 1936 | "dependencies": { 1937 | "define-properties": "^1.2.1", 1938 | "gopd": "^1.0.1" 1939 | }, 1940 | "engines": { 1941 | "node": ">= 0.4" 1942 | }, 1943 | "funding": { 1944 | "url": "https://github.com/sponsors/ljharb" 1945 | } 1946 | }, 1947 | "node_modules/gopd": { 1948 | "version": "1.0.1", 1949 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 1950 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 1951 | "dependencies": { 1952 | "get-intrinsic": "^1.1.3" 1953 | }, 1954 | "funding": { 1955 | "url": "https://github.com/sponsors/ljharb" 1956 | } 1957 | }, 1958 | "node_modules/graceful-fs": { 1959 | "version": "4.2.11", 1960 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1961 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 1962 | }, 1963 | "node_modules/has-bigints": { 1964 | "version": "1.0.2", 1965 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", 1966 | "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", 1967 | "funding": { 1968 | "url": "https://github.com/sponsors/ljharb" 1969 | } 1970 | }, 1971 | "node_modules/has-flag": { 1972 | "version": "3.0.0", 1973 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1974 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 1975 | "engines": { 1976 | "node": ">=4" 1977 | } 1978 | }, 1979 | "node_modules/has-property-descriptors": { 1980 | "version": "1.0.2", 1981 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 1982 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 1983 | "dependencies": { 1984 | "es-define-property": "^1.0.0" 1985 | }, 1986 | "funding": { 1987 | "url": "https://github.com/sponsors/ljharb" 1988 | } 1989 | }, 1990 | "node_modules/has-proto": { 1991 | "version": "1.0.3", 1992 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 1993 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 1994 | "engines": { 1995 | "node": ">= 0.4" 1996 | }, 1997 | "funding": { 1998 | "url": "https://github.com/sponsors/ljharb" 1999 | } 2000 | }, 2001 | "node_modules/has-symbols": { 2002 | "version": "1.0.3", 2003 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 2004 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 2005 | "engines": { 2006 | "node": ">= 0.4" 2007 | }, 2008 | "funding": { 2009 | "url": "https://github.com/sponsors/ljharb" 2010 | } 2011 | }, 2012 | "node_modules/has-tostringtag": { 2013 | "version": "1.0.2", 2014 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 2015 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 2016 | "dependencies": { 2017 | "has-symbols": "^1.0.3" 2018 | }, 2019 | "engines": { 2020 | "node": ">= 0.4" 2021 | }, 2022 | "funding": { 2023 | "url": "https://github.com/sponsors/ljharb" 2024 | } 2025 | }, 2026 | "node_modules/hasown": { 2027 | "version": "2.0.2", 2028 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 2029 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 2030 | "dependencies": { 2031 | "function-bind": "^1.1.2" 2032 | }, 2033 | "engines": { 2034 | "node": ">= 0.4" 2035 | } 2036 | }, 2037 | "node_modules/internal-slot": { 2038 | "version": "1.0.7", 2039 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", 2040 | "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", 2041 | "dependencies": { 2042 | "es-errors": "^1.3.0", 2043 | "hasown": "^2.0.0", 2044 | "side-channel": "^1.0.4" 2045 | }, 2046 | "engines": { 2047 | "node": ">= 0.4" 2048 | } 2049 | }, 2050 | "node_modules/is-array-buffer": { 2051 | "version": "3.0.4", 2052 | "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", 2053 | "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", 2054 | "dependencies": { 2055 | "call-bind": "^1.0.2", 2056 | "get-intrinsic": "^1.2.1" 2057 | }, 2058 | "engines": { 2059 | "node": ">= 0.4" 2060 | }, 2061 | "funding": { 2062 | "url": "https://github.com/sponsors/ljharb" 2063 | } 2064 | }, 2065 | "node_modules/is-bigint": { 2066 | "version": "1.0.4", 2067 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", 2068 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", 2069 | "dependencies": { 2070 | "has-bigints": "^1.0.1" 2071 | }, 2072 | "funding": { 2073 | "url": "https://github.com/sponsors/ljharb" 2074 | } 2075 | }, 2076 | "node_modules/is-binary-path": { 2077 | "version": "2.1.0", 2078 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2079 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2080 | "dependencies": { 2081 | "binary-extensions": "^2.0.0" 2082 | }, 2083 | "engines": { 2084 | "node": ">=8" 2085 | } 2086 | }, 2087 | "node_modules/is-boolean-object": { 2088 | "version": "1.1.2", 2089 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", 2090 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", 2091 | "dependencies": { 2092 | "call-bind": "^1.0.2", 2093 | "has-tostringtag": "^1.0.0" 2094 | }, 2095 | "engines": { 2096 | "node": ">= 0.4" 2097 | }, 2098 | "funding": { 2099 | "url": "https://github.com/sponsors/ljharb" 2100 | } 2101 | }, 2102 | "node_modules/is-callable": { 2103 | "version": "1.2.7", 2104 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 2105 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 2106 | "engines": { 2107 | "node": ">= 0.4" 2108 | }, 2109 | "funding": { 2110 | "url": "https://github.com/sponsors/ljharb" 2111 | } 2112 | }, 2113 | "node_modules/is-data-view": { 2114 | "version": "1.0.1", 2115 | "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", 2116 | "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", 2117 | "dependencies": { 2118 | "is-typed-array": "^1.1.13" 2119 | }, 2120 | "engines": { 2121 | "node": ">= 0.4" 2122 | }, 2123 | "funding": { 2124 | "url": "https://github.com/sponsors/ljharb" 2125 | } 2126 | }, 2127 | "node_modules/is-date-object": { 2128 | "version": "1.0.5", 2129 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", 2130 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", 2131 | "dependencies": { 2132 | "has-tostringtag": "^1.0.0" 2133 | }, 2134 | "engines": { 2135 | "node": ">= 0.4" 2136 | }, 2137 | "funding": { 2138 | "url": "https://github.com/sponsors/ljharb" 2139 | } 2140 | }, 2141 | "node_modules/is-extglob": { 2142 | "version": "2.1.1", 2143 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2144 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 2145 | "engines": { 2146 | "node": ">=0.10.0" 2147 | } 2148 | }, 2149 | "node_modules/is-glob": { 2150 | "version": "4.0.3", 2151 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2152 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2153 | "dependencies": { 2154 | "is-extglob": "^2.1.1" 2155 | }, 2156 | "engines": { 2157 | "node": ">=0.10.0" 2158 | } 2159 | }, 2160 | "node_modules/is-negative-zero": { 2161 | "version": "2.0.3", 2162 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", 2163 | "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", 2164 | "engines": { 2165 | "node": ">= 0.4" 2166 | }, 2167 | "funding": { 2168 | "url": "https://github.com/sponsors/ljharb" 2169 | } 2170 | }, 2171 | "node_modules/is-number": { 2172 | "version": "7.0.0", 2173 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2174 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 2175 | "engines": { 2176 | "node": ">=0.12.0" 2177 | } 2178 | }, 2179 | "node_modules/is-number-object": { 2180 | "version": "1.0.7", 2181 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", 2182 | "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", 2183 | "dependencies": { 2184 | "has-tostringtag": "^1.0.0" 2185 | }, 2186 | "engines": { 2187 | "node": ">= 0.4" 2188 | }, 2189 | "funding": { 2190 | "url": "https://github.com/sponsors/ljharb" 2191 | } 2192 | }, 2193 | "node_modules/is-regex": { 2194 | "version": "1.1.4", 2195 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", 2196 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", 2197 | "dependencies": { 2198 | "call-bind": "^1.0.2", 2199 | "has-tostringtag": "^1.0.0" 2200 | }, 2201 | "engines": { 2202 | "node": ">= 0.4" 2203 | }, 2204 | "funding": { 2205 | "url": "https://github.com/sponsors/ljharb" 2206 | } 2207 | }, 2208 | "node_modules/is-shared-array-buffer": { 2209 | "version": "1.0.3", 2210 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", 2211 | "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", 2212 | "dependencies": { 2213 | "call-bind": "^1.0.7" 2214 | }, 2215 | "engines": { 2216 | "node": ">= 0.4" 2217 | }, 2218 | "funding": { 2219 | "url": "https://github.com/sponsors/ljharb" 2220 | } 2221 | }, 2222 | "node_modules/is-string": { 2223 | "version": "1.0.7", 2224 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", 2225 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", 2226 | "dependencies": { 2227 | "has-tostringtag": "^1.0.0" 2228 | }, 2229 | "engines": { 2230 | "node": ">= 0.4" 2231 | }, 2232 | "funding": { 2233 | "url": "https://github.com/sponsors/ljharb" 2234 | } 2235 | }, 2236 | "node_modules/is-symbol": { 2237 | "version": "1.0.4", 2238 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 2239 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 2240 | "dependencies": { 2241 | "has-symbols": "^1.0.2" 2242 | }, 2243 | "engines": { 2244 | "node": ">= 0.4" 2245 | }, 2246 | "funding": { 2247 | "url": "https://github.com/sponsors/ljharb" 2248 | } 2249 | }, 2250 | "node_modules/is-typed-array": { 2251 | "version": "1.1.13", 2252 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", 2253 | "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", 2254 | "dependencies": { 2255 | "which-typed-array": "^1.1.14" 2256 | }, 2257 | "engines": { 2258 | "node": ">= 0.4" 2259 | }, 2260 | "funding": { 2261 | "url": "https://github.com/sponsors/ljharb" 2262 | } 2263 | }, 2264 | "node_modules/is-weakref": { 2265 | "version": "1.0.2", 2266 | "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", 2267 | "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", 2268 | "dependencies": { 2269 | "call-bind": "^1.0.2" 2270 | }, 2271 | "funding": { 2272 | "url": "https://github.com/sponsors/ljharb" 2273 | } 2274 | }, 2275 | "node_modules/isarray": { 2276 | "version": "2.0.5", 2277 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", 2278 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" 2279 | }, 2280 | "node_modules/js-tokens": { 2281 | "version": "4.0.0", 2282 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 2283 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 2284 | }, 2285 | "node_modules/jsesc": { 2286 | "version": "2.5.2", 2287 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 2288 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 2289 | "bin": { 2290 | "jsesc": "bin/jsesc" 2291 | }, 2292 | "engines": { 2293 | "node": ">=4" 2294 | } 2295 | }, 2296 | "node_modules/json5": { 2297 | "version": "2.2.3", 2298 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 2299 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 2300 | "bin": { 2301 | "json5": "lib/cli.js" 2302 | }, 2303 | "engines": { 2304 | "node": ">=6" 2305 | } 2306 | }, 2307 | "node_modules/jsonfile": { 2308 | "version": "6.1.0", 2309 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 2310 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 2311 | "dependencies": { 2312 | "universalify": "^2.0.0" 2313 | }, 2314 | "optionalDependencies": { 2315 | "graceful-fs": "^4.1.6" 2316 | } 2317 | }, 2318 | "node_modules/lru-cache": { 2319 | "version": "5.1.1", 2320 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 2321 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 2322 | "dependencies": { 2323 | "yallist": "^3.0.2" 2324 | } 2325 | }, 2326 | "node_modules/magic-string": { 2327 | "version": "0.30.11", 2328 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", 2329 | "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", 2330 | "dependencies": { 2331 | "@jridgewell/sourcemap-codec": "^1.5.0" 2332 | } 2333 | }, 2334 | "node_modules/merge2": { 2335 | "version": "1.4.1", 2336 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2337 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 2338 | "engines": { 2339 | "node": ">= 8" 2340 | } 2341 | }, 2342 | "node_modules/micromatch": { 2343 | "version": "4.0.7", 2344 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", 2345 | "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", 2346 | "dependencies": { 2347 | "braces": "^3.0.3", 2348 | "picomatch": "^2.3.1" 2349 | }, 2350 | "engines": { 2351 | "node": ">=8.6" 2352 | } 2353 | }, 2354 | "node_modules/ms": { 2355 | "version": "2.1.2", 2356 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2357 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2358 | }, 2359 | "node_modules/nanoid": { 2360 | "version": "3.3.7", 2361 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 2362 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 2363 | "funding": [ 2364 | { 2365 | "type": "github", 2366 | "url": "https://github.com/sponsors/ai" 2367 | } 2368 | ], 2369 | "bin": { 2370 | "nanoid": "bin/nanoid.cjs" 2371 | }, 2372 | "engines": { 2373 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 2374 | } 2375 | }, 2376 | "node_modules/node-releases": { 2377 | "version": "2.0.18", 2378 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", 2379 | "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" 2380 | }, 2381 | "node_modules/normalize-path": { 2382 | "version": "3.0.0", 2383 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2384 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 2385 | "engines": { 2386 | "node": ">=0.10.0" 2387 | } 2388 | }, 2389 | "node_modules/object-inspect": { 2390 | "version": "1.13.2", 2391 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 2392 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 2393 | "engines": { 2394 | "node": ">= 0.4" 2395 | }, 2396 | "funding": { 2397 | "url": "https://github.com/sponsors/ljharb" 2398 | } 2399 | }, 2400 | "node_modules/object-keys": { 2401 | "version": "1.1.1", 2402 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 2403 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 2404 | "engines": { 2405 | "node": ">= 0.4" 2406 | } 2407 | }, 2408 | "node_modules/object.assign": { 2409 | "version": "4.1.5", 2410 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", 2411 | "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", 2412 | "dependencies": { 2413 | "call-bind": "^1.0.5", 2414 | "define-properties": "^1.2.1", 2415 | "has-symbols": "^1.0.3", 2416 | "object-keys": "^1.1.1" 2417 | }, 2418 | "engines": { 2419 | "node": ">= 0.4" 2420 | }, 2421 | "funding": { 2422 | "url": "https://github.com/sponsors/ljharb" 2423 | } 2424 | }, 2425 | "node_modules/picocolors": { 2426 | "version": "1.0.1", 2427 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 2428 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" 2429 | }, 2430 | "node_modules/picomatch": { 2431 | "version": "2.3.1", 2432 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2433 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2434 | "engines": { 2435 | "node": ">=8.6" 2436 | }, 2437 | "funding": { 2438 | "url": "https://github.com/sponsors/jonschlinkert" 2439 | } 2440 | }, 2441 | "node_modules/possible-typed-array-names": { 2442 | "version": "1.0.0", 2443 | "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", 2444 | "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", 2445 | "engines": { 2446 | "node": ">= 0.4" 2447 | } 2448 | }, 2449 | "node_modules/postcss": { 2450 | "version": "8.4.41", 2451 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", 2452 | "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", 2453 | "funding": [ 2454 | { 2455 | "type": "opencollective", 2456 | "url": "https://opencollective.com/postcss/" 2457 | }, 2458 | { 2459 | "type": "tidelift", 2460 | "url": "https://tidelift.com/funding/github/npm/postcss" 2461 | }, 2462 | { 2463 | "type": "github", 2464 | "url": "https://github.com/sponsors/ai" 2465 | } 2466 | ], 2467 | "dependencies": { 2468 | "nanoid": "^3.3.7", 2469 | "picocolors": "^1.0.1", 2470 | "source-map-js": "^1.2.0" 2471 | }, 2472 | "engines": { 2473 | "node": "^10 || ^12 || >=14" 2474 | } 2475 | }, 2476 | "node_modules/prettier": { 2477 | "version": "3.3.3", 2478 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", 2479 | "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", 2480 | "bin": { 2481 | "prettier": "bin/prettier.cjs" 2482 | }, 2483 | "engines": { 2484 | "node": ">=14" 2485 | }, 2486 | "funding": { 2487 | "url": "https://github.com/prettier/prettier?sponsor=1" 2488 | } 2489 | }, 2490 | "node_modules/queue-microtask": { 2491 | "version": "1.2.3", 2492 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2493 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2494 | "funding": [ 2495 | { 2496 | "type": "github", 2497 | "url": "https://github.com/sponsors/feross" 2498 | }, 2499 | { 2500 | "type": "patreon", 2501 | "url": "https://www.patreon.com/feross" 2502 | }, 2503 | { 2504 | "type": "consulting", 2505 | "url": "https://feross.org/support" 2506 | } 2507 | ] 2508 | }, 2509 | "node_modules/readdirp": { 2510 | "version": "3.6.0", 2511 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2512 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2513 | "dependencies": { 2514 | "picomatch": "^2.2.1" 2515 | }, 2516 | "engines": { 2517 | "node": ">=8.10.0" 2518 | } 2519 | }, 2520 | "node_modules/regexp.prototype.flags": { 2521 | "version": "1.5.2", 2522 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", 2523 | "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", 2524 | "dependencies": { 2525 | "call-bind": "^1.0.6", 2526 | "define-properties": "^1.2.1", 2527 | "es-errors": "^1.3.0", 2528 | "set-function-name": "^2.0.1" 2529 | }, 2530 | "engines": { 2531 | "node": ">= 0.4" 2532 | }, 2533 | "funding": { 2534 | "url": "https://github.com/sponsors/ljharb" 2535 | } 2536 | }, 2537 | "node_modules/reusify": { 2538 | "version": "1.0.4", 2539 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2540 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2541 | "engines": { 2542 | "iojs": ">=1.0.0", 2543 | "node": ">=0.10.0" 2544 | } 2545 | }, 2546 | "node_modules/rollup": { 2547 | "version": "4.20.0", 2548 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz", 2549 | "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==", 2550 | "dev": true, 2551 | "dependencies": { 2552 | "@types/estree": "1.0.5" 2553 | }, 2554 | "bin": { 2555 | "rollup": "dist/bin/rollup" 2556 | }, 2557 | "engines": { 2558 | "node": ">=18.0.0", 2559 | "npm": ">=8.0.0" 2560 | }, 2561 | "optionalDependencies": { 2562 | "@rollup/rollup-android-arm-eabi": "4.20.0", 2563 | "@rollup/rollup-android-arm64": "4.20.0", 2564 | "@rollup/rollup-darwin-arm64": "4.20.0", 2565 | "@rollup/rollup-darwin-x64": "4.20.0", 2566 | "@rollup/rollup-linux-arm-gnueabihf": "4.20.0", 2567 | "@rollup/rollup-linux-arm-musleabihf": "4.20.0", 2568 | "@rollup/rollup-linux-arm64-gnu": "4.20.0", 2569 | "@rollup/rollup-linux-arm64-musl": "4.20.0", 2570 | "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0", 2571 | "@rollup/rollup-linux-riscv64-gnu": "4.20.0", 2572 | "@rollup/rollup-linux-s390x-gnu": "4.20.0", 2573 | "@rollup/rollup-linux-x64-gnu": "4.20.0", 2574 | "@rollup/rollup-linux-x64-musl": "4.20.0", 2575 | "@rollup/rollup-win32-arm64-msvc": "4.20.0", 2576 | "@rollup/rollup-win32-ia32-msvc": "4.20.0", 2577 | "@rollup/rollup-win32-x64-msvc": "4.20.0", 2578 | "fsevents": "~2.3.2" 2579 | } 2580 | }, 2581 | "node_modules/run-parallel": { 2582 | "version": "1.2.0", 2583 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2584 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2585 | "funding": [ 2586 | { 2587 | "type": "github", 2588 | "url": "https://github.com/sponsors/feross" 2589 | }, 2590 | { 2591 | "type": "patreon", 2592 | "url": "https://www.patreon.com/feross" 2593 | }, 2594 | { 2595 | "type": "consulting", 2596 | "url": "https://feross.org/support" 2597 | } 2598 | ], 2599 | "dependencies": { 2600 | "queue-microtask": "^1.2.2" 2601 | } 2602 | }, 2603 | "node_modules/safe-array-concat": { 2604 | "version": "1.1.2", 2605 | "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", 2606 | "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", 2607 | "dependencies": { 2608 | "call-bind": "^1.0.7", 2609 | "get-intrinsic": "^1.2.4", 2610 | "has-symbols": "^1.0.3", 2611 | "isarray": "^2.0.5" 2612 | }, 2613 | "engines": { 2614 | "node": ">=0.4" 2615 | }, 2616 | "funding": { 2617 | "url": "https://github.com/sponsors/ljharb" 2618 | } 2619 | }, 2620 | "node_modules/safe-regex-test": { 2621 | "version": "1.0.3", 2622 | "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", 2623 | "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", 2624 | "dependencies": { 2625 | "call-bind": "^1.0.6", 2626 | "es-errors": "^1.3.0", 2627 | "is-regex": "^1.1.4" 2628 | }, 2629 | "engines": { 2630 | "node": ">= 0.4" 2631 | }, 2632 | "funding": { 2633 | "url": "https://github.com/sponsors/ljharb" 2634 | } 2635 | }, 2636 | "node_modules/semver": { 2637 | "version": "6.3.1", 2638 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 2639 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 2640 | "bin": { 2641 | "semver": "bin/semver.js" 2642 | } 2643 | }, 2644 | "node_modules/set-function-length": { 2645 | "version": "1.2.2", 2646 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 2647 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 2648 | "dependencies": { 2649 | "define-data-property": "^1.1.4", 2650 | "es-errors": "^1.3.0", 2651 | "function-bind": "^1.1.2", 2652 | "get-intrinsic": "^1.2.4", 2653 | "gopd": "^1.0.1", 2654 | "has-property-descriptors": "^1.0.2" 2655 | }, 2656 | "engines": { 2657 | "node": ">= 0.4" 2658 | } 2659 | }, 2660 | "node_modules/set-function-name": { 2661 | "version": "2.0.2", 2662 | "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", 2663 | "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", 2664 | "dependencies": { 2665 | "define-data-property": "^1.1.4", 2666 | "es-errors": "^1.3.0", 2667 | "functions-have-names": "^1.2.3", 2668 | "has-property-descriptors": "^1.0.2" 2669 | }, 2670 | "engines": { 2671 | "node": ">= 0.4" 2672 | } 2673 | }, 2674 | "node_modules/side-channel": { 2675 | "version": "1.0.6", 2676 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 2677 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 2678 | "dependencies": { 2679 | "call-bind": "^1.0.7", 2680 | "es-errors": "^1.3.0", 2681 | "get-intrinsic": "^1.2.4", 2682 | "object-inspect": "^1.13.1" 2683 | }, 2684 | "engines": { 2685 | "node": ">= 0.4" 2686 | }, 2687 | "funding": { 2688 | "url": "https://github.com/sponsors/ljharb" 2689 | } 2690 | }, 2691 | "node_modules/source-map": { 2692 | "version": "0.6.1", 2693 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2694 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2695 | "engines": { 2696 | "node": ">=0.10.0" 2697 | } 2698 | }, 2699 | "node_modules/source-map-js": { 2700 | "version": "1.2.0", 2701 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 2702 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 2703 | "engines": { 2704 | "node": ">=0.10.0" 2705 | } 2706 | }, 2707 | "node_modules/string.prototype.replaceall": { 2708 | "version": "1.0.10", 2709 | "resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.10.tgz", 2710 | "integrity": "sha512-PKLapcZUZmXUdfIM6rTTTMYOxaj4JiQrgl0SKEeCFug1CdMAuJq8hVZd4eek9yMXAW4ldGUq+TiZRtjLJRU96g==", 2711 | "dependencies": { 2712 | "call-bind": "^1.0.7", 2713 | "define-properties": "^1.2.1", 2714 | "es-abstract": "^1.23.2", 2715 | "es-errors": "^1.3.0", 2716 | "es-object-atoms": "^1.0.0", 2717 | "get-intrinsic": "^1.2.4", 2718 | "has-symbols": "^1.0.3", 2719 | "is-regex": "^1.1.4" 2720 | }, 2721 | "engines": { 2722 | "node": ">= 0.4" 2723 | }, 2724 | "funding": { 2725 | "url": "https://github.com/sponsors/ljharb" 2726 | } 2727 | }, 2728 | "node_modules/string.prototype.trim": { 2729 | "version": "1.2.9", 2730 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", 2731 | "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", 2732 | "dependencies": { 2733 | "call-bind": "^1.0.7", 2734 | "define-properties": "^1.2.1", 2735 | "es-abstract": "^1.23.0", 2736 | "es-object-atoms": "^1.0.0" 2737 | }, 2738 | "engines": { 2739 | "node": ">= 0.4" 2740 | }, 2741 | "funding": { 2742 | "url": "https://github.com/sponsors/ljharb" 2743 | } 2744 | }, 2745 | "node_modules/string.prototype.trimend": { 2746 | "version": "1.0.8", 2747 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", 2748 | "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", 2749 | "dependencies": { 2750 | "call-bind": "^1.0.7", 2751 | "define-properties": "^1.2.1", 2752 | "es-object-atoms": "^1.0.0" 2753 | }, 2754 | "funding": { 2755 | "url": "https://github.com/sponsors/ljharb" 2756 | } 2757 | }, 2758 | "node_modules/string.prototype.trimstart": { 2759 | "version": "1.0.8", 2760 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", 2761 | "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", 2762 | "dependencies": { 2763 | "call-bind": "^1.0.7", 2764 | "define-properties": "^1.2.1", 2765 | "es-object-atoms": "^1.0.0" 2766 | }, 2767 | "engines": { 2768 | "node": ">= 0.4" 2769 | }, 2770 | "funding": { 2771 | "url": "https://github.com/sponsors/ljharb" 2772 | } 2773 | }, 2774 | "node_modules/supports-color": { 2775 | "version": "5.5.0", 2776 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2777 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2778 | "dependencies": { 2779 | "has-flag": "^3.0.0" 2780 | }, 2781 | "engines": { 2782 | "node": ">=4" 2783 | } 2784 | }, 2785 | "node_modules/to-fast-properties": { 2786 | "version": "2.0.0", 2787 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2788 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", 2789 | "engines": { 2790 | "node": ">=4" 2791 | } 2792 | }, 2793 | "node_modules/to-regex-range": { 2794 | "version": "5.0.1", 2795 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2796 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2797 | "dependencies": { 2798 | "is-number": "^7.0.0" 2799 | }, 2800 | "engines": { 2801 | "node": ">=8.0" 2802 | } 2803 | }, 2804 | "node_modules/typed-array-buffer": { 2805 | "version": "1.0.2", 2806 | "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", 2807 | "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", 2808 | "dependencies": { 2809 | "call-bind": "^1.0.7", 2810 | "es-errors": "^1.3.0", 2811 | "is-typed-array": "^1.1.13" 2812 | }, 2813 | "engines": { 2814 | "node": ">= 0.4" 2815 | } 2816 | }, 2817 | "node_modules/typed-array-byte-length": { 2818 | "version": "1.0.1", 2819 | "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", 2820 | "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", 2821 | "dependencies": { 2822 | "call-bind": "^1.0.7", 2823 | "for-each": "^0.3.3", 2824 | "gopd": "^1.0.1", 2825 | "has-proto": "^1.0.3", 2826 | "is-typed-array": "^1.1.13" 2827 | }, 2828 | "engines": { 2829 | "node": ">= 0.4" 2830 | }, 2831 | "funding": { 2832 | "url": "https://github.com/sponsors/ljharb" 2833 | } 2834 | }, 2835 | "node_modules/typed-array-byte-offset": { 2836 | "version": "1.0.2", 2837 | "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", 2838 | "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", 2839 | "dependencies": { 2840 | "available-typed-arrays": "^1.0.7", 2841 | "call-bind": "^1.0.7", 2842 | "for-each": "^0.3.3", 2843 | "gopd": "^1.0.1", 2844 | "has-proto": "^1.0.3", 2845 | "is-typed-array": "^1.1.13" 2846 | }, 2847 | "engines": { 2848 | "node": ">= 0.4" 2849 | }, 2850 | "funding": { 2851 | "url": "https://github.com/sponsors/ljharb" 2852 | } 2853 | }, 2854 | "node_modules/typed-array-length": { 2855 | "version": "1.0.6", 2856 | "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", 2857 | "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", 2858 | "dependencies": { 2859 | "call-bind": "^1.0.7", 2860 | "for-each": "^0.3.3", 2861 | "gopd": "^1.0.1", 2862 | "has-proto": "^1.0.3", 2863 | "is-typed-array": "^1.1.13", 2864 | "possible-typed-array-names": "^1.0.0" 2865 | }, 2866 | "engines": { 2867 | "node": ">= 0.4" 2868 | }, 2869 | "funding": { 2870 | "url": "https://github.com/sponsors/ljharb" 2871 | } 2872 | }, 2873 | "node_modules/typescript": { 2874 | "version": "5.5.4", 2875 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", 2876 | "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", 2877 | "dev": true, 2878 | "bin": { 2879 | "tsc": "bin/tsc", 2880 | "tsserver": "bin/tsserver" 2881 | }, 2882 | "engines": { 2883 | "node": ">=14.17" 2884 | } 2885 | }, 2886 | "node_modules/unbox-primitive": { 2887 | "version": "1.0.2", 2888 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", 2889 | "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", 2890 | "dependencies": { 2891 | "call-bind": "^1.0.2", 2892 | "has-bigints": "^1.0.2", 2893 | "has-symbols": "^1.0.3", 2894 | "which-boxed-primitive": "^1.0.2" 2895 | }, 2896 | "funding": { 2897 | "url": "https://github.com/sponsors/ljharb" 2898 | } 2899 | }, 2900 | "node_modules/undici-types": { 2901 | "version": "5.26.5", 2902 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 2903 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 2904 | "dev": true 2905 | }, 2906 | "node_modules/universalify": { 2907 | "version": "2.0.1", 2908 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 2909 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 2910 | "engines": { 2911 | "node": ">= 10.0.0" 2912 | } 2913 | }, 2914 | "node_modules/update-browserslist-db": { 2915 | "version": "1.1.0", 2916 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", 2917 | "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", 2918 | "funding": [ 2919 | { 2920 | "type": "opencollective", 2921 | "url": "https://opencollective.com/browserslist" 2922 | }, 2923 | { 2924 | "type": "tidelift", 2925 | "url": "https://tidelift.com/funding/github/npm/browserslist" 2926 | }, 2927 | { 2928 | "type": "github", 2929 | "url": "https://github.com/sponsors/ai" 2930 | } 2931 | ], 2932 | "dependencies": { 2933 | "escalade": "^3.1.2", 2934 | "picocolors": "^1.0.1" 2935 | }, 2936 | "bin": { 2937 | "update-browserslist-db": "cli.js" 2938 | }, 2939 | "peerDependencies": { 2940 | "browserslist": ">= 4.21.0" 2941 | } 2942 | }, 2943 | "node_modules/vite": { 2944 | "version": "5.4.0", 2945 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.0.tgz", 2946 | "integrity": "sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==", 2947 | "dev": true, 2948 | "dependencies": { 2949 | "esbuild": "^0.21.3", 2950 | "postcss": "^8.4.40", 2951 | "rollup": "^4.13.0" 2952 | }, 2953 | "bin": { 2954 | "vite": "bin/vite.js" 2955 | }, 2956 | "engines": { 2957 | "node": "^18.0.0 || >=20.0.0" 2958 | }, 2959 | "funding": { 2960 | "url": "https://github.com/vitejs/vite?sponsor=1" 2961 | }, 2962 | "optionalDependencies": { 2963 | "fsevents": "~2.3.3" 2964 | }, 2965 | "peerDependencies": { 2966 | "@types/node": "^18.0.0 || >=20.0.0", 2967 | "less": "*", 2968 | "lightningcss": "^1.21.0", 2969 | "sass": "*", 2970 | "sass-embedded": "*", 2971 | "stylus": "*", 2972 | "sugarss": "*", 2973 | "terser": "^5.4.0" 2974 | }, 2975 | "peerDependenciesMeta": { 2976 | "@types/node": { 2977 | "optional": true 2978 | }, 2979 | "less": { 2980 | "optional": true 2981 | }, 2982 | "lightningcss": { 2983 | "optional": true 2984 | }, 2985 | "sass": { 2986 | "optional": true 2987 | }, 2988 | "sass-embedded": { 2989 | "optional": true 2990 | }, 2991 | "stylus": { 2992 | "optional": true 2993 | }, 2994 | "sugarss": { 2995 | "optional": true 2996 | }, 2997 | "terser": { 2998 | "optional": true 2999 | } 3000 | } 3001 | }, 3002 | "node_modules/which-boxed-primitive": { 3003 | "version": "1.0.2", 3004 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 3005 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 3006 | "dependencies": { 3007 | "is-bigint": "^1.0.1", 3008 | "is-boolean-object": "^1.1.0", 3009 | "is-number-object": "^1.0.4", 3010 | "is-string": "^1.0.5", 3011 | "is-symbol": "^1.0.3" 3012 | }, 3013 | "funding": { 3014 | "url": "https://github.com/sponsors/ljharb" 3015 | } 3016 | }, 3017 | "node_modules/which-typed-array": { 3018 | "version": "1.1.15", 3019 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", 3020 | "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", 3021 | "dependencies": { 3022 | "available-typed-arrays": "^1.0.7", 3023 | "call-bind": "^1.0.7", 3024 | "for-each": "^0.3.3", 3025 | "gopd": "^1.0.1", 3026 | "has-tostringtag": "^1.0.2" 3027 | }, 3028 | "engines": { 3029 | "node": ">= 0.4" 3030 | }, 3031 | "funding": { 3032 | "url": "https://github.com/sponsors/ljharb" 3033 | } 3034 | }, 3035 | "node_modules/yallist": { 3036 | "version": "3.1.1", 3037 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 3038 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 3039 | } 3040 | } 3041 | } 3042 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snaptail", 3 | "version": "0.0.5", 4 | "description": "Run single file application in an instant.", 5 | "type": "module", 6 | "bin": { 7 | "snaptail": "dist/cli.js" 8 | }, 9 | "scripts": { 10 | "dev": "tsc && tsc --watch", 11 | "build": "tsc" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "vite", 16 | "single file", 17 | "web app", 18 | "nextjs" 19 | ], 20 | "author": "Sandro Rybarik", 21 | "license": "MIT", 22 | "dependencies": { 23 | "bcryptjs": "^2.4.3", 24 | "chokidar": "^3.6.0", 25 | "commander": "^12.1.0", 26 | "detype": "^1.0.10", 27 | "fs-extra": "^11.2.0" 28 | }, 29 | "devDependencies": { 30 | "@types/fs-extra": "^11.0.4", 31 | "@types/node": "~20.10.0", 32 | "create-vite": "^5.5.1", 33 | "typescript": "^5.5.4", 34 | "vite": "^5.4.0" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/rybarix/snaptail.git" 39 | }, 40 | "files": [ 41 | "cli.js", 42 | "dist/", 43 | "templates/" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/builder.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | // import fs from "node:fs/promises"; 3 | 4 | const PROJECT_DIR = ".snaptail"; 5 | 6 | type InitNextJsProject = { 7 | action: "initNextJsProject"; 8 | dir: string; 9 | }; 10 | 11 | type CpAction = { 12 | action: "cp"; 13 | src: string; 14 | dst: string; 15 | }; 16 | 17 | type RmAction = { 18 | action: "rm"; 19 | src: string; 20 | }; 21 | 22 | type ConfigStep = InitNextJsProject | CpAction | RmAction | CpAction; 23 | 24 | export type StepsFile = { 25 | steps: ConfigStep[]; 26 | }; 27 | 28 | /** 29 | * Path resolution depending on the path type. 30 | * 31 | * Each path is expected to start with one of the following symbols: 32 | * 33 | * - "@" - relative path resolution to the snaptail project dir 34 | * - "~" - relate path resolution to user's dir 35 | * - "/" - relative resolution to the snaptail internal files 36 | */ 37 | export const pth = (filePath: string) => { 38 | const type = filePath.at(0); 39 | const justPath = filePath.slice(1); 40 | 41 | switch (type) { 42 | case "@": 43 | return path.join(PROJECT_DIR, justPath); 44 | case "~": 45 | // path from where user is executing the command 46 | return path.join(process.cwd(), justPath); 47 | case "/": 48 | // path from snaptail internal files 49 | return path.join(__dirname, justPath); 50 | default: 51 | throw new Error(`unknown path type ${type}`); 52 | } 53 | }; 54 | 55 | export const handleStep = async (step: ConfigStep) => { 56 | switch (step.action) { 57 | case "initNextJsProject": 58 | // await setupProject(step.dir, []); 59 | break; 60 | } 61 | }; 62 | 63 | export const loadSteps = async ( 64 | _stepsFilepath: string, 65 | _options = undefined 66 | ) => { 67 | try { 68 | // const _conf: StepsFile = JSON.parse( 69 | // await fs.readFile(stepsFilepath, "utf-8") 70 | // ); 71 | // for (const s of conf.steps) { 72 | // } 73 | } catch (error) {} 74 | }; 75 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { Command } from "commander"; 3 | import { 4 | buildProject, 5 | initializeProject, 6 | runSingleFileApplication, 7 | } from "./lib.js"; 8 | 9 | const program = new Command(); 10 | 11 | // Ensure the watcher is closed when the process exits 12 | process.on("SIGINT", () => { 13 | console.log("Shutting down..."); 14 | process.exit(0); 15 | }); 16 | 17 | program 18 | .command("init") 19 | .description("Initialize a new Snaptail project in current directory") 20 | .option("--ui ", "Specify the UI library to use (e.g., shadcn)") 21 | .option("-b, --base ", "Specify the path to Snaptail files") 22 | // .option("--hidden", "Hide the project in home dir (experimental)") 23 | .action(initializeProject); 24 | 25 | program 26 | .command("run ") 27 | .description("Run a single file application") 28 | .option("-b, --base ", "Specify the path to Snaptail files") 29 | .action(runSingleFileApplication); 30 | 31 | program 32 | .command("build") 33 | .description("Build the project for deployment") 34 | .requiredOption( 35 | "--target ", 36 | "Specify the build target (e.g., nextjs, snaptail)" 37 | ) 38 | .option("-b, --base ", "Specify the path to Snaptail files") 39 | .action(buildProject); 40 | 41 | // Add a default action for when no command is specified 42 | program.action(() => { 43 | if ( 44 | process.argv.length <= 2 || 45 | process.argv.includes("-h") || 46 | process.argv.includes("--help") 47 | ) { 48 | program.outputHelp(); 49 | } else { 50 | console.log( 51 | "Invalid command. Use --help for a list of available commands." 52 | ); 53 | } 54 | }); 55 | 56 | program.parse(); 57 | -------------------------------------------------------------------------------- /src/frameworks/nextjs.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import fs from "node:fs/promises"; 3 | import { copyFileAndCreateDir } from "../templator.js"; 4 | import { copyApiToFile, getAllImportsRawFromFile } from "../legacy/lib.js"; 5 | import { cpath, ppath } from "../lib.js"; 6 | import { generateNextApiRoutes } from "../legacy/next.js"; 7 | 8 | export const makeOnFileChangeNextJs = () => { 9 | return async (changedFile: string) => { 10 | console.log(`File changed: ${changedFile}`); 11 | const baseName = path.basename(changedFile); 12 | 13 | if (baseName === ".env") { 14 | await fs.copyFile(cpath(".env"), ppath(".env")); 15 | return; 16 | } 17 | 18 | try { 19 | const fileExt = path.extname(changedFile); 20 | 21 | // Copy the user's file to the project 22 | await copyFileAndCreateDir( 23 | changedFile, 24 | ppath("src", "app", "user", `app${fileExt}`) 25 | ); 26 | 27 | console.log("Updating API routes"); 28 | 29 | const imports = await getAllImportsRawFromFile(changedFile); 30 | await copyApiToFile(changedFile, imports, ppath("user_api.mjs")); 31 | 32 | await generateNextApiRoutes( 33 | await getAllImportsRawFromFile(ppath("user_api.mjs")), 34 | (await import(ppath("user_api.mjs"))).api, 35 | ppath("src", "pages") 36 | ); 37 | 38 | console.log("Project files updated successfully"); 39 | } catch (error) { 40 | console.error("Error updating project files:", error); 41 | } 42 | }; 43 | }; 44 | -------------------------------------------------------------------------------- /src/kits/nextjs-shadcn.json: -------------------------------------------------------------------------------- 1 | { 2 | "steps": [ 3 | { 4 | "action": "command", 5 | "args": [ 6 | "npx", 7 | "shadcn@latest", 8 | "init", 9 | "-d" 10 | ], 11 | "options": { 12 | "cwd": "@/", 13 | "stdio": "inherit" 14 | } 15 | }, 16 | { 17 | "action": "command", 18 | "args": [ 19 | "npx", 20 | "shadcn@latest", 21 | "add", 22 | "--all", 23 | "-o" 24 | ], 25 | "options": { 26 | "cwd": "@/", 27 | "stdio": "inherit" 28 | } 29 | }, 30 | { 31 | "action": "cp", 32 | "sourcePath": "/templates/next/globals.css", 33 | "destinationPath": "@/src/app/globals.css" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /src/kits/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "steps": [ 3 | { 4 | "action": "initNextJsProject", 5 | "dir": "$projectName" 6 | }, 7 | { 8 | "action": "cp", 9 | "src": "/templates/next/globals.css", 10 | "dst": "@/src/app/page.tsx" 11 | }, 12 | { 13 | "action": "rm", 14 | "src": "@/src/app/index.css" 15 | }, 16 | { 17 | "action": "cp", 18 | "src": "~/templates/next/tsconfig.json", 19 | "dst": "tsconfig.json" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /src/legacy/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { cli } from "./next.js"; 3 | cli(); 4 | -------------------------------------------------------------------------------- /src/legacy/lib.js: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises"; 2 | import path from "node:path"; 3 | import { fileURLToPath } from "node:url"; 4 | import { spawn } from "node:child_process"; 5 | import { transform } from "detype"; 6 | 7 | export const __filename = fileURLToPath(import.meta.url); 8 | export const __dirname = path.dirname(__filename); 9 | 10 | /** 11 | * @param {...string} path 12 | */ 13 | export const fromHere = (...paths) => { 14 | return path.join(/*__dirname,*/ ...paths); 15 | }; 16 | 17 | export const runAsync = (command, args, spawnArgs = undefined) => { 18 | return new Promise((resolve, reject) => { 19 | const child = spawn(command, args, spawnArgs); 20 | child.on("close", resolve); 21 | }); 22 | }; 23 | 24 | /** 25 | * @param {string} sourceFile 26 | * @param {string} imports raw javascript import statements 27 | * @param {string} targetFile 28 | */ 29 | export async function copyApiToFile(sourceFile, imports, targetFile) { 30 | try { 31 | const content = await fs.readFile(sourceFile, "utf-8"); 32 | 33 | const apiRegex = /export const api = \[[\s\S]*?\];?/; 34 | const match = content.match(apiRegex); 35 | 36 | if (match) { 37 | const toWrite = [imports, "", match[0]].join("\n"); 38 | const transformedCode = await transform(toWrite, sourceFile); 39 | 40 | await fs.writeFile(targetFile, transformedCode, { 41 | encoding: "utf8", 42 | flag: "w", 43 | }); 44 | 45 | console.log(`Successfully copied api to ${targetFile}`); 46 | } else { 47 | await fs.writeFile(targetFile, `export const api = [];`); 48 | } 49 | } catch (error) { 50 | console.error("Error:", error); 51 | } 52 | } 53 | 54 | /** 55 | * @param {string} filePath 56 | * @returns {Promise} 57 | */ 58 | export const getAllImportsRawFromFile = async (filePath) => { 59 | const content = await fs.readFile(filePath, "utf-8"); 60 | const importRegex = 61 | /import\s+(?:type\s+)?(?:(?:\w+(?:\s*,\s*\{\s*[\w\s,]+\})?|\{\s*[\w\s,]+\})|\*\s+as\s+\w+)\s+from\s+['"]([^'"]+)['"]/g; 62 | const matches = [...content.matchAll(importRegex)]; 63 | 64 | return matches.map((match) => match[0]).join(";\n"); 65 | }; 66 | 67 | /** 68 | * Check what dependencies are needed from the user's single react file 69 | * Parse the user's single react file and get the dependencies 70 | * @param {string} filePath js source file path 71 | * @returns {Promise} 72 | */ 73 | export const getDependencies = async (filePath) => { 74 | const content = await fs.readFile(filePath, "utf-8"); 75 | const importRegex = 76 | /import\s+(?:(?:\w+(?:\s*,\s*\{\s*[\w\s,]+\})?|\{\s*[\w\s,]+\})|\*\s+as\s+\w+)\s+from\s+['"]([^'"]+)['"]/g; 77 | const matches = [...content.matchAll(importRegex)]; 78 | const dependencies = new Set(matches.map((match) => match[1])); 79 | return Array.from(dependencies).filter( 80 | (dep) => !dep.startsWith(".") && !dep.startsWith("@") 81 | ); 82 | }; 83 | -------------------------------------------------------------------------------- /src/legacy/next.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from "node:fs/promises"; 4 | import fss from "node:fs"; 5 | import path from "node:path"; 6 | import { fileURLToPath, pathToFileURL } from "node:url"; 7 | import { 8 | runAsync, 9 | copyApiToFile, 10 | getAllImportsRawFromFile, 11 | getDependencies, 12 | } from "./lib.js"; 13 | import chokidar from "chokidar"; 14 | 15 | const __filename = fileURLToPath(import.meta.url); 16 | const __dirname = path.dirname(__filename); 17 | 18 | export const setupShadCnUi = async () => { 19 | // Default setup 20 | await runAsync("npx", ["--yes", "shadcn-ui@latest", "init", "-d"], { 21 | cwd: ".snaptail", 22 | }); 23 | 24 | // Install all components 25 | await runAsync("npx", ["--yes", "shadcn-ui@latest", "add", "--all"], { 26 | cwd: ".snaptail", 27 | }); 28 | 29 | const shadcnTwCssVars = await fs.readFile( 30 | path.join(__dirname, "templates", "next", "shadcn.css"), 31 | "utf-8" 32 | ); 33 | // append css variables with default style 34 | await fs.appendFile( 35 | path.join(".snaptail", "src", "app", "globals.css"), 36 | shadcnTwCssVars, 37 | "utf-8" 38 | ); 39 | }; 40 | 41 | const createNextApp = async () => { 42 | try { 43 | const postfix = Number(new Date()).toString(); 44 | const projectName = "snaptail_" + postfix; 45 | 46 | await runAsync( 47 | "npx", 48 | [ 49 | "--yes", 50 | "create-next-app@latest", 51 | projectName, 52 | "--typescript", 53 | "--eslint", 54 | "--app", 55 | "--src-dir", 56 | "--tailwind", 57 | "--app", 58 | "--import-alias", 59 | "@/*", 60 | "--use-npm", 61 | ], 62 | { stdio: "inherit" } 63 | ); 64 | 65 | // ✔ What is your project named? … my-app 66 | // ✔ Would you like to use TypeScript? … No / Yes 67 | // ✔ Would you like to use ESLint? … No / Yes 68 | // ✔ Would you like to use Tailwind CSS? … No / Yes 69 | // ✔ Would you like to use `src/` directory? … No / Yes 70 | // ✔ Would you like to use App Router? (recommended) … No / Yes 71 | // ✔ Would you like to customize the default import alias (@/*)? … No / Yes 72 | 73 | console.info(`Next.js application created successfully!`); 74 | await fs.rename(projectName, ".snaptail"); 75 | } catch (error) { 76 | console.error("Error creating Next.js application:", error); 77 | } 78 | }; 79 | 80 | /** 81 | * Generate nextjs directory structure for api routes from a json object where 82 | * path is provided, handler function is provided and method is also provided. 83 | * Make sure that file generation supports URL parameters and dynamic routes. 84 | * @param {string} imports - Raw imports from api file (user_api.mjs) 85 | * @param {Object[]} routes - Array of route objects 86 | * @param {string} routes[].path - API route path 87 | * @param {Function} routes[].handler - Route handler function 88 | * @param {string} routes[].method - HTTP method (GET, POST, etc.) 89 | * @param {string} baseDir - Base directory for API routes 90 | */ 91 | export async function generateNextApiRoutes(imports, routes, baseDir) { 92 | for (const route of routes) { 93 | const { path: pathString, handler, method } = route; 94 | const segments = pathString.split("/").filter((segment) => segment); 95 | let currentDir = baseDir; 96 | 97 | // Create directories for each segment 98 | for (let i = 0; i < segments.length - 1; i++) { 99 | const segment = segments[i]; 100 | const isParameter = segment.startsWith(":"); 101 | const dirName = isParameter ? `[${segment.slice(1)}]` : segment; 102 | currentDir = path.join(currentDir, dirName); 103 | await fs.mkdir(currentDir, { recursive: true }); 104 | } 105 | 106 | // Create the file for the last segment 107 | const lastSegment = segments[segments.length - 1]; 108 | const isParameter = lastSegment.startsWith(":"); 109 | const fileName = isParameter 110 | ? `[${lastSegment.slice(1)}].js` 111 | : `${lastSegment}.js`; 112 | const filePath = path.join(currentDir, fileName); 113 | 114 | // Generate the content for the API route file 115 | const fileContent = ` 116 | ${imports} 117 | 118 | export default function handler(req, res) { 119 | const { method } = req; 120 | 121 | if (method === '${method.toUpperCase()}') { 122 | return (${handler.toString()})(req, res); 123 | } 124 | 125 | res.setHeader('Allow', ['${method.toUpperCase()}']); 126 | res.status(405).end(\`Method \${method} Not Allowed\`); 127 | } 128 | `; 129 | 130 | await fs.writeFile(filePath, fileContent.trim()); 131 | console.log(`Generated API route: ${filePath}`); 132 | } 133 | } 134 | 135 | /** 136 | * Generates next routes by dynamically importing extracted mjs api file. 137 | */ 138 | const generateApiFiles = async () => { 139 | // There's hack used to always import the newest file and avoid hitting cache https://github.com/nodejs/help/issues/2751 140 | const importPath = 141 | pathToFileURL(path.join(".snaptail", `user_api.mjs`)) + 142 | `?version=${Number(new Date())}`; 143 | 144 | const { api: userApiConf } = await import(importPath); 145 | 146 | const imports = await getAllImportsRawFromFile(importPath); 147 | 148 | await generateNextApiRoutes( 149 | imports, 150 | userApiConf, 151 | path.join(".snaptail", "src", "pages") 152 | ); 153 | }; 154 | 155 | const setupBasicFiles = async () => { 156 | await Promise.allSettled([ 157 | fs.copyFile( 158 | path.join(__dirname, "templates", "next", "page.tsx"), 159 | path.join(".snaptail", "src", "app", "page.tsx") 160 | ), 161 | fs.copyFile( 162 | path.join(__dirname, "templates", "next", "globals.css"), 163 | path.join(".snaptail", "src", "app", "globals.css") 164 | ), 165 | fs.copyFile( 166 | path.join(__dirname, "templates", "next", "index.css"), 167 | path.join(".snaptail", "src", "app", "index.css") 168 | ), 169 | ]); 170 | }; 171 | 172 | /** 173 | * Setup's the single file app from single react file 174 | * @param {string} userFile The path to the user's single react file 175 | * @param {{ type: 'nextjs'|'react-ts', ui: 'shadcn' }|undefined} config To support multiple frameworks in the future 176 | */ 177 | export const main = async (userFile, config = undefined) => { 178 | const fileExt = userFile.split(".").pop() === "tsx" ? "tsx" : "jsx"; 179 | const isTs = fileExt === "tsx"; 180 | 181 | // Detect if project is already set-up by checking if .wiresnap dir is created 182 | if (!fss.existsSync(path.join(".snaptail"))) { 183 | console.info("Setting up the project"); 184 | 185 | if (config?.type === "nextjs") { 186 | await createNextApp(); // create .snaptail dir nextjs project 187 | await setupBasicFiles(); 188 | 189 | if (config?.ui === "shadcn") { 190 | console.info("shadcn/ui setup"); 191 | 192 | await setupShadCnUi(); 193 | } 194 | } 195 | } 196 | 197 | if (isTs) { 198 | await fs.copyFile( 199 | path.join(__dirname, "templates", "next", "tsconfig.json"), 200 | path.join(".", "tsconfig.json") 201 | ); 202 | } 203 | 204 | // copy the user's single react file and add it to the 205 | await fs.cp( 206 | userFile, 207 | path.join(".snaptail", "src", "app", "user", `app.${fileExt}`) 208 | ); 209 | 210 | console.info("Detecting dependencies"); 211 | const dependencies = await getDependencies(userFile); 212 | 213 | console.info(`Installing detected dependencies`); 214 | await runAsync("npm", ["--prefix", ".snaptail", "install", ...dependencies]); 215 | // Install typescript dependencies 216 | await runAsync("npm", [ 217 | "--prefix", 218 | ".snaptail", 219 | "install", 220 | "-D", 221 | ...dependencies.map((dep) => `@types/${dep}`), 222 | ]); 223 | 224 | console.info("Setting up api"); 225 | 226 | const imports = await getAllImportsRawFromFile(userFile); 227 | await copyApiToFile( 228 | userFile, 229 | imports, 230 | path.join(".snaptail", "user_api.mjs") 231 | ); 232 | 233 | if (!fss.existsSync(path.join(".snaptail", "src", "pages", "api"))) { 234 | await fs.mkdir(path.join(".snaptail", "src", "pages", "api"), { 235 | recursive: true, 236 | }); 237 | } 238 | 239 | await generateApiFiles(); 240 | 241 | if (fss.existsSync(path.join(".env"))) { 242 | fs.copyFile(".env", path.join(".snaptail", ".env")); 243 | } 244 | 245 | const watcher = chokidar 246 | .watch([".env", userFile]) 247 | .on("change", async (filePath) => { 248 | try { 249 | // maybe change to .tsx, we will see 250 | await fs.cp( 251 | userFile, 252 | path.join(".snaptail", "src", "app", "user", `app.${fileExt}`), 253 | { force: true } 254 | ); 255 | 256 | console.info("Updating api routes"); 257 | 258 | const imports = await getAllImportsRawFromFile(userFile); 259 | 260 | await copyApiToFile( 261 | userFile, 262 | imports, 263 | path.join(".snaptail", "user_api.mjs") 264 | ); 265 | 266 | await generateApiFiles(); 267 | 268 | if (filePath.includes(".env")) { 269 | await fs.copyFile(".env", path.join(".snaptail", ".env"), { 270 | force: true, 271 | }); 272 | } 273 | } catch (error) { 274 | console.error("Error updating .snaptail/src/user.jsx:", error); 275 | } 276 | }); 277 | 278 | process.on("SIGINT", () => { 279 | watcher.close(); 280 | }); 281 | 282 | // Run the dev project 283 | await runAsync("npm", ["--prefix", ".snaptail", "run", "dev"], { 284 | stdio: "inherit", 285 | }); 286 | }; 287 | 288 | /** 289 | * 290 | * @param {'shadcn'|undefined} ui 291 | */ 292 | export const initCmd = async (ui) => { 293 | try { 294 | if (ui === "shadcn") { 295 | await fs.copyFile( 296 | path.join(__dirname, "templates", "next", "startershadcn.tsx"), 297 | "starter.tsx" 298 | ); 299 | } else { 300 | await fs.copyFile( 301 | path.join(__dirname, "templates", "next", "starter.tsx"), 302 | "starter.tsx" 303 | ); 304 | } 305 | 306 | await fs.copyFile( 307 | path.join(__dirname, "templates", "next", "tsconfig.json"), 308 | "tsconfig.json" 309 | ); 310 | } catch (e) { 311 | console.error("unable to setup project"); 312 | } 313 | 314 | console.info("starter.tsx ..... has been created"); 315 | console.info("tsconfig.json ... has been created"); 316 | console.info("run $ npx snaptail starter.tsx"); 317 | }; 318 | 319 | export const cli = async () => { 320 | /** @type {string|undefined} */ 321 | let ui = undefined; 322 | 323 | // In current structure we need to always tell snaptail what ui we want to run. 324 | // It would be much better if this can happen in init stage instead. 325 | // But for alpha testing this is now good enoughTM. 326 | if ( 327 | process.argv.length === 5 && 328 | process.argv[3] === "--ui" && 329 | process.argv[4] === "shadcn" 330 | ) { 331 | ui = "shadcn"; 332 | } else if (process.argv.length === 5 && process.argv[3] === "--ui") { 333 | console.log("ui not supported"); 334 | process.exit(1); 335 | } 336 | 337 | if (process.argv.length >= 3 && process.argv[2] === "init") { 338 | try { 339 | await initCmd(ui); 340 | process.exit(0); 341 | } catch { 342 | process.exit(1); 343 | } 344 | } else if (process.argv.length < 3) { 345 | console.error("Usage: snaptail init|"); 346 | process.exit(1); 347 | } else { 348 | // Ensure the watcher is closed when the process exits 349 | process.on("SIGINT", () => { 350 | process.exit(0); 351 | }); 352 | 353 | main(process.argv[2], { 354 | type: "nextjs", 355 | ui, 356 | }); 357 | } 358 | }; 359 | -------------------------------------------------------------------------------- /src/lib.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import { setupProject, SetupStep } from "./templator.js"; 3 | import { makeOnFileChangeNextJs } from "./frameworks/nextjs.js"; 4 | import { PathLike } from "node:fs"; 5 | import fs2 from "fs-extra"; 6 | import { fileURLToPath } from "url"; 7 | import { createHash } from "node:crypto"; 8 | import os from "node:os"; 9 | import fs from "node:fs/promises"; 10 | 11 | const __filename = fileURLToPath(import.meta.url); 12 | const __dirname = path.dirname(__filename); 13 | 14 | enum FrameWorkEnum { 15 | Unknown = "__unknown__", 16 | NextJs = "nextjs", 17 | } 18 | 19 | const projectName = () => ".snaptail"; // project directory 20 | const starterFile = "starter.tsx"; 21 | 22 | // Path to project dir 23 | export const ppath = (...paths: string[]) => { 24 | const p = path.join(process.cwd(), projectName(), ...paths); 25 | return p; 26 | }; 27 | // Update spath function to use the provided path if available 28 | export const spath = (basePath?: string, ...paths: string[]) => { 29 | return path.join(basePath ?? __dirname, ...paths); 30 | }; 31 | // path from - relative to process execution path 32 | export const cpath = (...paths: string[]) => { 33 | const p = path.join(process.cwd(), ...paths); 34 | return p; 35 | }; 36 | 37 | const hashOfCurrentDir = () => { 38 | const toHashDir = createHash("sha256"); 39 | toHashDir.update(process.cwd()); 40 | return toHashDir.digest("hex"); 41 | }; 42 | 43 | const hiddenDirFullPath = () => { 44 | return path.join(os.homedir(), ".snaptail", hashOfCurrentDir()); 45 | }; 46 | 47 | export async function initializeProject(options: { 48 | ui: string; 49 | base?: string; 50 | hidden?: boolean; 51 | skipStarter?: boolean; // User has his own file, don't create starter.tsx 52 | }) { 53 | console.log("Initializing a new Snaptail project..."); 54 | // Get current absolute path to this folder and create hash off it. 55 | 56 | if (!options.base) { 57 | // files are compiled to dist dir, so we need to have it in the base outside of it 58 | options.base = path.join(__dirname, ".."); 59 | console.log("Base path:", options.base); 60 | } 61 | 62 | if (options.hidden) { 63 | console.log("Hiding project in home dir"); 64 | // EXPERIMENTAL TODO: try hiding project in home dir ~/ using hash of cwd 65 | const snaptailInernal = await fs.realpath(".."); // TODO: RESOLVE THIS, because this won't be working when executed from cli 66 | options.base = snaptailInernal; 67 | 68 | // Store the build dir in 69 | // const dirHash = hashOfCurrentDir(); 70 | 71 | // full path to hidden dir 72 | // const hiddenDirFullPath = path.join(os.homedir(), ".snaptail", dirHash); 73 | 74 | // If dir already exists, we don't need to create new one 75 | if (!(await fs2.exists(hiddenDirFullPath()))) { 76 | // Create hidden dir in home dir 77 | await fs.mkdir(hiddenDirFullPath(), { recursive: true }); 78 | } 79 | 80 | // Path to the hidden folder must be reflected in tsconfig.json paths... 81 | process.chdir(hiddenDirFullPath()); 82 | } 83 | 84 | // If we can't init project directly in ~/ dir, init it here, and move it after 85 | const uiLibrary = options.ui || "default"; 86 | 87 | // Steps to initialize the project 88 | const steps: SetupStep[] = [ 89 | { action: "initNextProject", directory: projectName() }, 90 | { 91 | action: "replaceFile", 92 | sourcePath: spath(options?.base, "templates", "next", "page.tsx"), 93 | targetPath: ppath("src", "app", "page.tsx"), 94 | }, 95 | { 96 | action: "replaceFile", 97 | sourcePath: spath(options?.base, "templates", "next", "globals.css"), 98 | targetPath: ppath("src", "app", "globals.css"), 99 | }, 100 | { 101 | action: "deleteFileOrDir", 102 | targetPath: ppath("src", "app", "index.css"), 103 | }, 104 | { 105 | action: "copyFile", 106 | sourcePath: spath(options?.base, "templates", "next", "tsconfig.json"), 107 | destinationPath: cpath("tsconfig.json"), 108 | }, 109 | ]; 110 | 111 | if (uiLibrary === "shadcn") { 112 | steps.push( 113 | { 114 | action: "executeCommand", 115 | command: "npx", 116 | args: ["--yes", "shadcn@2.0.7", "init", "-d"], 117 | options: { 118 | cwd: cpath(projectName()), 119 | stdio: "inherit", 120 | }, 121 | }, 122 | { 123 | action: "executeCommand", 124 | command: "npx", 125 | args: ["--yes", "shadcn@2.0.7", "add", "--all", "-o"], 126 | options: { 127 | cwd: cpath(projectName()), 128 | stdio: "inherit", 129 | }, 130 | }, 131 | { 132 | action: "appendFile", 133 | sourcePath: spath(options?.base, "templates", "next", "shadcn.css"), 134 | targetPath: ppath("src", "app", "globals.css"), 135 | }, 136 | { 137 | action: "copyFile", 138 | sourcePath: spath( 139 | options?.base, 140 | "templates", 141 | "next", 142 | "startershadcn.tsx" 143 | ), 144 | destinationPath: cpath(starterFile), 145 | }, 146 | { action: "runNpmInstall" } 147 | ); 148 | } else { 149 | steps.push({ 150 | action: "copyFile", 151 | sourcePath: spath(options?.base, "templates", "next", "starter.tsx"), 152 | destinationPath: cpath(starterFile), 153 | }); 154 | } 155 | 156 | try { 157 | await setupProject(projectName(), steps); 158 | console.log("Project initialized successfully."); 159 | console.log(`To get started, run: npx snaptail@latest run ${starterFile}`); 160 | } catch (error) { 161 | console.error("Failed to initialize project:", error); 162 | } 163 | } 164 | 165 | export async function runSingleFileApplication( 166 | file: PathLike, 167 | options: { base?: string } 168 | ) { 169 | console.log(`Running file: ${file}`); 170 | 171 | let framework: FrameWorkEnum = FrameWorkEnum.Unknown; 172 | 173 | // check if there is .snaptail folder in the current dir otherwise check for home dir 174 | if (!(await fs2.exists(cpath(".snaptail")))) { 175 | // local setup 176 | await initializeProject({ 177 | ui: "shadcn", 178 | skipStarter: true, 179 | base: options.base, 180 | }); 181 | } 182 | 183 | /*if (await fs2.exists(hiddenDirFullPath())) { 184 | // --hidden setup 185 | // check if there is .snaptail folder in the home dir 186 | process.chdir(hiddenDirFullPath()); 187 | }*/ 188 | 189 | // To detect framework we need to look for next.config.mjs 190 | if (await fs2.exists(ppath("next.config.mjs"))) { 191 | framework = FrameWorkEnum.NextJs; 192 | } 193 | 194 | let steps: SetupStep[] = []; 195 | if (framework === FrameWorkEnum.Unknown) { 196 | console.log("Unknown framework"); 197 | process.exit(1); 198 | } else if (framework === FrameWorkEnum.NextJs) { 199 | steps = [ 200 | { 201 | // detect and install dependencies 202 | action: "detectAndInstallDependencies", 203 | projectPath: cpath(projectName()), 204 | targetPaths: [cpath(file.toString())], 205 | }, 206 | { 207 | action: "watchForChanges", 208 | targetPaths: [cpath(file.toString()), cpath(".env")], 209 | callback: makeOnFileChangeNextJs(), 210 | }, 211 | { 212 | action: "runCode", 213 | callback: async () => { 214 | makeOnFileChangeNextJs()(file.toString()); 215 | }, 216 | }, 217 | { 218 | action: "executeCommand", 219 | command: "npm", 220 | args: ["--prefix", projectName(), "run", "dev"], 221 | options: { 222 | cwd: cpath("."), 223 | stdio: "inherit", 224 | }, 225 | }, 226 | ]; 227 | } 228 | 229 | try { 230 | await setupProject(projectName(), steps); 231 | } catch (error) { 232 | console.error("Failed to run the application:", error); 233 | } 234 | } 235 | 236 | export async function buildProject(options: { target: string; base?: string }) { 237 | console.log(`Building project for target: ${options.target}`); 238 | 239 | const steps: SetupStep[] = [ 240 | { action: "runNpmInstall" }, 241 | { action: "buildProject" }, 242 | ]; 243 | 244 | if (options.target === "nextjs") { 245 | // Add any Next.js specific build steps here 246 | } else if (options.target === "snaptail") { 247 | // Add any Snaptail specific build steps here 248 | } else { 249 | console.log(`Building for custom target: ${options.target}`); 250 | // Add logic for custom targets 251 | } 252 | 253 | try { 254 | await setupProject(projectName(), steps); 255 | console.log("Build completed successfully."); 256 | } catch (error) { 257 | console.error("Build failed:", error); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/templator.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises"; 2 | import { spawn } from "child_process"; 3 | import { PathLike } from "fs"; 4 | import { watch, type FSWatcher } from "chokidar"; 5 | import fse from "fs-extra/esm"; 6 | import path from "path"; 7 | import { getDependencies } from "./legacy/lib.js"; 8 | import { nextTick } from "process"; 9 | 10 | /** 11 | * Execute a shell command 12 | * @param {string} command - Command to execute 13 | * @param {string[]} args - Command arguments 14 | * @param {Object} options - Spawn options 15 | * @returns {Promise} 16 | */ 17 | async function executeCommand( 18 | command: string, 19 | args: any[] | readonly string[] | undefined, 20 | options: object = {} 21 | ): Promise { 22 | return new Promise((resolve, reject) => { 23 | const process = spawn(command, args, options); 24 | process.on("close", (code) => { 25 | if (code === 0) resolve(); 26 | else 27 | reject( 28 | new Error( 29 | `Command ${command} ${args?.join(" ")} failed with exit code ${code}` 30 | ) 31 | ); 32 | }); 33 | }); 34 | } 35 | 36 | /** 37 | * Initialize a Next.js project 38 | * @returns {Promise} 39 | */ 40 | async function initNextProject(projectDir: string): Promise { 41 | const postfix = Number(new Date()).toString(); 42 | const tmpDir = "snaptail_" + postfix; 43 | 44 | await executeCommand( 45 | "npx", 46 | [ 47 | "--yes", 48 | "create-next-app@14.2.11", 49 | tmpDir, 50 | "--typescript", 51 | "--eslint", 52 | "--app", 53 | "--src-dir", 54 | "--tailwind", 55 | "--app", 56 | "--import-alias", 57 | "@/*", 58 | "--use-npm", 59 | ], 60 | { 61 | stdio: "inherit", 62 | } 63 | ); 64 | await renameFile(tmpDir, projectDir); 65 | console.log(`Next.js project ${projectDir} initialized successfully.`); 66 | } 67 | 68 | /** 69 | * Replace a file in the project 70 | * @param {string} targetPath - Relative path of the file to be replaced 71 | * @param {string} sourcePath - Path of the custom file to replace with 72 | * @returns {Promise} 73 | */ 74 | async function replaceFile( 75 | targetPath: string, 76 | sourcePath: PathLike 77 | ): Promise { 78 | await fs.copyFile(sourcePath, targetPath); 79 | console.log(`Replaced ${targetPath} successfully.`); 80 | } 81 | 82 | /** 83 | * Copy a file to the project 84 | * @param sourcePath - Path of the file to copy 85 | * @param destinationPath - Relative path in the project to copy the file 86 | * @returns {Promise} 87 | */ 88 | async function copyFile( 89 | sourcePath: PathLike, 90 | destinationPath: PathLike 91 | ): Promise { 92 | await fs.copyFile(sourcePath, destinationPath); 93 | console.log(`Copied ${sourcePath} to ${destinationPath} successfully.`); 94 | } 95 | 96 | /** 97 | * Delete a file or directory from the project 98 | * @param {string} projectPath - Path to the project 99 | * @param {string} targetPath - Relative path of the file or directory to be deleted 100 | * @returns {Promise} 101 | */ 102 | async function deleteFileOrDir(targetPath: string): Promise { 103 | await fs.rm(targetPath, { recursive: true, force: true }); 104 | console.log(`Deleted ${targetPath} successfully.`); 105 | } 106 | 107 | /** 108 | * Create a directory in the project 109 | * @param {string} projectPath - Path to the project 110 | * @param {string} dirPath - Relative path of the directory to be created 111 | * @returns {Promise} 112 | */ 113 | async function createDirectory(dirPath: string): Promise { 114 | await fs.mkdir(dirPath, { recursive: true }); 115 | console.log(`Created directory ${dirPath} successfully.`); 116 | } 117 | 118 | /** 119 | * Run npm install in the project 120 | * @param {string} projectPath - Path to the project 121 | * @returns {Promise} 122 | */ 123 | async function runNpmInstall(projectPath: string): Promise { 124 | await executeCommand("npm", ["install"], { cwd: projectPath }); 125 | console.log("npm install completed successfully."); 126 | } 127 | 128 | /** 129 | * Build the project 130 | * @param {string} projectPath - Path to the project 131 | * @returns {Promise} 132 | */ 133 | async function buildProject(projectPath: string): Promise { 134 | await executeCommand("npm", ["run", "build"], { cwd: projectPath }); 135 | console.log("Project built successfully."); 136 | } 137 | 138 | /** 139 | * 140 | * @param {string} projectPath 141 | * @param {string[]} dependencies 142 | */ 143 | export async function installDetectedDependencies( 144 | projectPath: any, 145 | dependencies: any 146 | ) { 147 | await executeCommand("npm", ["install", ...dependencies], { 148 | cwd: projectPath, 149 | }); 150 | } 151 | 152 | /** 153 | * Append content from one file to another 154 | * @param {string} targetPath - Path of the file to append to 155 | * @param {string} sourcePath - Path of the file to append from 156 | * @returns {Promise} 157 | */ 158 | async function appendFile( 159 | targetPath: string, 160 | sourcePath: string 161 | ): Promise { 162 | const content = await fs.readFile(sourcePath, "utf-8"); 163 | await fs.appendFile(targetPath, content); 164 | console.log( 165 | `Appended content from ${sourcePath} to ${targetPath} successfully.` 166 | ); 167 | } 168 | 169 | async function renameFile( 170 | sourcePath: string, 171 | destinationPath: string 172 | ): Promise { 173 | try { 174 | await fs.rename(sourcePath, destinationPath); 175 | console.log(`File renamed from ${sourcePath} to ${destinationPath}`); 176 | } catch (error) { 177 | console.error(`Error renaming file: ${error}`); 178 | throw error; 179 | } 180 | } 181 | 182 | // useful when when we want to trigger watch file change 183 | async function touchFile(filename: string) { 184 | console.log(`Touching ${filename}`); 185 | const time = new Date(); 186 | await fs.utimes(filename, time, time).catch(async function (err) { 187 | if ("ENOENT" !== err.code) { 188 | throw err; 189 | } 190 | let fh = await fs.open(filename, "a"); 191 | await fh.close(); 192 | }); 193 | } 194 | 195 | /** 196 | * Compose and execute project setup steps 197 | * @param {string} projectName - Name of the project 198 | * @param {Array} steps - Array of step objects 199 | * @returns {Promise} 200 | */ 201 | type InitNextProjectStep = { 202 | action: "initNextProject"; 203 | /** Directory to rename the project to */ 204 | directory: string; 205 | }; 206 | 207 | type ReplaceFileStep = { 208 | action: "replaceFile"; 209 | targetPath: string; 210 | sourcePath: string; 211 | }; 212 | 213 | type CopyFileStep = { 214 | action: "copyFile"; 215 | sourcePath: string; 216 | destinationPath: string; 217 | }; 218 | 219 | type DeleteFileOrDirStep = { 220 | action: "deleteFileOrDir"; 221 | targetPath: string; 222 | }; 223 | 224 | type CreateDirectoryStep = { 225 | action: "createDirectory"; 226 | dirPath: string; 227 | }; 228 | 229 | type RunNpmInstallStep = { 230 | action: "runNpmInstall"; 231 | }; 232 | 233 | type BuildProjectStep = { 234 | action: "buildProject"; 235 | }; 236 | 237 | type WatchForChangesStep = { 238 | action: "watchForChanges"; 239 | targetPaths: string[]; 240 | callback: (filePath: string) => Promise; 241 | }; 242 | 243 | type ExecuteCommandStep = { 244 | action: "executeCommand"; 245 | command: Parameters[0]; 246 | args: Parameters[1]; 247 | options?: Parameters[2]; 248 | }; 249 | 250 | type AppendFileStep = { 251 | action: "appendFile"; 252 | targetPath: string; 253 | sourcePath: string; 254 | }; 255 | 256 | type DetectAndInstallDependenciesStep = { 257 | action: "detectAndInstallDependencies"; 258 | projectPath: string; 259 | targetPaths: PathLike[]; 260 | }; 261 | 262 | // Define the RenameFileStep type 263 | type RenameFileStep = { 264 | action: "renameFile"; 265 | sourcePath: string; 266 | destinationPath: string; 267 | }; 268 | 269 | type TouchFileStep = { 270 | action: "touchFile"; 271 | filename: string; 272 | }; 273 | 274 | // escape hatch for running arbitrary code 275 | // should be avoided if possible 276 | type RunCodeStep = { 277 | action: "runCode"; 278 | callback: () => Promise; 279 | }; 280 | 281 | export type SetupStep = 282 | | InitNextProjectStep 283 | | ReplaceFileStep 284 | | CopyFileStep 285 | | DeleteFileOrDirStep 286 | | CreateDirectoryStep 287 | | RunNpmInstallStep 288 | | BuildProjectStep 289 | | WatchForChangesStep 290 | | ExecuteCommandStep 291 | | AppendFileStep 292 | | DetectAndInstallDependenciesStep 293 | | RenameFileStep 294 | | TouchFileStep 295 | | RunCodeStep; 296 | 297 | const setupWatchForFileChanges = ( 298 | targetPaths: string[], 299 | action: ((filePath: string) => Promise) | undefined = undefined 300 | ) => { 301 | return watch(targetPaths).on("change", async (filePath) => { 302 | if (action) { 303 | await action(filePath); 304 | } 305 | }); 306 | }; 307 | 308 | const installDependencies = async ( 309 | projectPath: string, 310 | userFile: PathLike[] 311 | ) => { 312 | console.info("Detecting dependencies"); 313 | for (const file of userFile) { 314 | const dependencies = await getDependencies(file.toString()); 315 | console.info(`Installing detected dependencies of ${file.toString()}`); 316 | await executeCommand("npm", [ 317 | "--prefix", 318 | projectPath, 319 | "install", 320 | ...dependencies, 321 | ]); 322 | // Install typescript dependencies 323 | await executeCommand("npm", [ 324 | "--prefix", 325 | projectPath, 326 | "install", 327 | "-D", 328 | ...dependencies.map((dep) => `@types/${dep}`), 329 | ]); 330 | } 331 | }; 332 | 333 | export async function copyFileAndCreateDir( 334 | sourcePath: PathLike, 335 | destPath: PathLike 336 | ) { 337 | // Ensure the directory exists 338 | await fse.ensureDir(path.dirname(destPath.toString())); 339 | 340 | // Copy the file 341 | await fs.copyFile(sourcePath, destPath); 342 | console.log("File copied successfully"); 343 | } 344 | 345 | export async function setupProject( 346 | projectName: string, 347 | steps: SetupStep[] 348 | ): Promise { 349 | let watchers: FSWatcher[] = []; 350 | 351 | // TODO: Move upper level 352 | process.on("SIGINT", () => { 353 | for (const watcher of watchers) { 354 | watcher.close(); 355 | } 356 | }); 357 | 358 | try { 359 | for (const step of steps) { 360 | switch (step.action) { 361 | case "initNextProject": 362 | await initNextProject(step.directory); 363 | break; 364 | case "replaceFile": 365 | await replaceFile(step.targetPath, step.sourcePath); 366 | break; 367 | case "copyFile": 368 | await copyFile(step.sourcePath, step.destinationPath); 369 | break; 370 | case "deleteFileOrDir": 371 | await deleteFileOrDir(step.targetPath); 372 | break; 373 | case "createDirectory": 374 | await createDirectory(step.dirPath); 375 | break; 376 | case "runNpmInstall": 377 | await runNpmInstall(projectName); 378 | break; 379 | case "buildProject": 380 | await buildProject(projectName); 381 | break; 382 | case "watchForChanges": 383 | watchers.push( 384 | setupWatchForFileChanges(step.targetPaths, step?.callback) 385 | ); 386 | break; 387 | case "executeCommand": 388 | await executeCommand(step.command, step.args, step.options); 389 | break; 390 | case "appendFile": 391 | await appendFile(step.targetPath, step.sourcePath); 392 | break; 393 | case "detectAndInstallDependencies": 394 | await installDependencies(step.projectPath, step.targetPaths); 395 | break; 396 | case "renameFile": 397 | await renameFile(step.sourcePath, step.destinationPath); 398 | break; 399 | case "touchFile": 400 | nextTick(() => { 401 | touchFile(step.filename); 402 | }); 403 | break; 404 | case "runCode": 405 | await step.callback(); 406 | break; 407 | default: 408 | console.warn(`Unknown action: ${(step as SetupStep).action}`); 409 | } 410 | } 411 | console.log("Project setup completed successfully."); 412 | } catch (error) { 413 | console.error("Project setup failed:", error); 414 | } finally { 415 | for (const watcher of watchers) { 416 | watcher.close(); 417 | } 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /templates/auth.js: -------------------------------------------------------------------------------- 1 | import * as bcrypt from "bcryptjs"; 2 | import * as jwt from "jsonwebtoken"; 3 | 4 | const JWT_SECRET = "{{JWT_SECRET}}"; // Store this securely in environment variables 5 | const HASHED_PASSWORD = "{{HASHED_PASSWORD}}"; // "password", 10 6 | 7 | export default async (request, context) => { 8 | const url = new URL(request.url); 9 | const isLogin = url.pathname.indexOf("/auth/login") >= 0; 10 | const isProtected = url.pathname.indexOf("/auth/protected") >= 0; 11 | 12 | switch (request.method) { 13 | case "POST": 14 | if (isLogin) { 15 | const body = await request.json(); 16 | return handleLogin(body, context); 17 | } 18 | break; 19 | case "GET": 20 | if (isProtected) { 21 | return handleProtected(request.headers); 22 | } 23 | break; 24 | } 25 | 26 | return new Response(JSON.stringify({ error: "Not Found" }), { 27 | status: 404, 28 | headers: { "Content-Type": "application/json" }, 29 | }); 30 | }; 31 | 32 | async function handleLogin({ password }, context) { 33 | try { 34 | const isMatch = await bcrypt.compare(password, HASHED_PASSWORD); 35 | 36 | if (isMatch) { 37 | const token = jwt.sign({ user: "username" }, JWT_SECRET, { 38 | expiresIn: "1h", 39 | }); 40 | 41 | // Sets cookie to token 42 | context.cookies.set({ 43 | name: "token", 44 | value: token, 45 | httpOnly: true, 46 | secure: true, 47 | path: "/", 48 | }); 49 | 50 | return new Response(JSON.stringify({ token }), { 51 | status: 200, 52 | headers: { "Content-Type": "application/json" }, 53 | }); 54 | } else { 55 | return new Response(JSON.stringify({ error: "Invalid credentials" }), { 56 | status: 401, 57 | headers: { "Content-Type": "application/json" }, 58 | }); 59 | } 60 | } catch (error) { 61 | console.error(error); 62 | return new Response(JSON.stringify({ error: "Server error" }), { 63 | status: 500, 64 | headers: { "Content-Type": "application/json" }, 65 | }); 66 | } 67 | } 68 | 69 | function handleProtected(headers) { 70 | const token = headers.get("authorization"); 71 | if (!token) { 72 | return new Response(JSON.stringify({ error: "Access denied" }), { 73 | status: 401, 74 | headers: { "Content-Type": "application/json" }, 75 | }); 76 | } 77 | 78 | try { 79 | const verified = jwt.verify(token, JWT_SECRET); 80 | return new Response( 81 | JSON.stringify({ 82 | message: "Access granted to protected route", 83 | user: verified, 84 | }), 85 | { 86 | status: 200, 87 | headers: { "Content-Type": "application/json" }, 88 | } 89 | ); 90 | } catch (error) { 91 | return new Response(JSON.stringify({ error: "Invalid token" }), { 92 | status: 400, 93 | headers: { "Content-Type": "application/json" }, 94 | }); 95 | } 96 | } 97 | 98 | export const config = { 99 | path: ["/auth/*"], 100 | }; 101 | -------------------------------------------------------------------------------- /templates/fastify-vite.config.js: -------------------------------------------------------------------------------- 1 | import { resolve, dirname } from "node:path"; 2 | import { fileURLToPath } from "node:url"; 3 | import react from "@vitejs/plugin-react"; 4 | 5 | const path = fileURLToPath(import.meta.url); 6 | const root = resolve(dirname(path), "."); 7 | 8 | const plugins = [react()]; 9 | 10 | export default { 11 | root, 12 | plugins, 13 | }; 14 | -------------------------------------------------------------------------------- /templates/fastify.js: -------------------------------------------------------------------------------- 1 | import process from "node:process"; 2 | import Fastify from "fastify"; 3 | import FastifyVite from "@fastify/vite"; 4 | 5 | const server = Fastify(); 6 | 7 | import { api } from "./user_api.js"; 8 | 9 | // api has path, method, and handler 10 | const attachAdditionalRoutes = (userApis) => { 11 | userApis.forEach((api) => { 12 | server.route({ 13 | method: api.method, 14 | url: api.path, 15 | handler: api.handler, 16 | }); 17 | }); 18 | }; 19 | 20 | await server.register(FastifyVite, { 21 | root: import.meta.url, 22 | dev: process.argv.includes("--dev"), 23 | spa: true, 24 | }); 25 | 26 | // Handling the render of the react app 27 | server.get("/", (req, reply) => { 28 | return reply.html(); 29 | }); 30 | 31 | attachAdditionalRoutes(api); 32 | 33 | await server.vite.ready(); 34 | await server.listen({ port: 3000 }); 35 | -------------------------------------------------------------------------------- /templates/next/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer utilities { 6 | .text-balance { 7 | text-wrap: balance; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /templates/next/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Inter } from "next/font/google"; 2 | import "./globals.css"; 3 | const inter = Inter({ subsets: ["latin"] }); 4 | import { metadata } from "./user/metadata"; 5 | export { metadata } from "./user/metadata"; 6 | 7 | export default function RootLayout({ 8 | children, 9 | }: Readonly<{ 10 | children: React.ReactNode; 11 | }>) { 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /templates/next/metadata.js: -------------------------------------------------------------------------------- 1 | export const metadata = { 2 | title: "User app", 3 | description: "Single page app for user", 4 | lang: "sk", 5 | }; 6 | -------------------------------------------------------------------------------- /templates/next/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { App } from "./user/app"; 3 | export default App; 4 | -------------------------------------------------------------------------------- /templates/next/shadcn.css: -------------------------------------------------------------------------------- 1 | 2 | @layer base { 3 | :root { 4 | --background: 0 0% 100%; 5 | --foreground: 240 10% 3.9%; 6 | --card: 0 0% 100%; 7 | --card-foreground: 240 10% 3.9%; 8 | --popover: 0 0% 100%; 9 | --popover-foreground: 240 10% 3.9%; 10 | --primary: 240 5.9% 10%; 11 | --primary-foreground: 0 0% 98%; 12 | --secondary: 240 4.8% 95.9%; 13 | --secondary-foreground: 240 5.9% 10%; 14 | --muted: 240 4.8% 95.9%; 15 | --muted-foreground: 240 3.8% 46.1%; 16 | --accent: 240 4.8% 95.9%; 17 | --accent-foreground: 240 5.9% 10%; 18 | --destructive: 0 84.2% 60.2%; 19 | --destructive-foreground: 0 0% 98%; 20 | --border: 240 5.9% 90%; 21 | --input: 240 5.9% 90%; 22 | --ring: 240 5.9% 10%; 23 | --radius: 0.5rem; 24 | --chart-1: 12 76% 61%; 25 | --chart-2: 173 58% 39%; 26 | --chart-3: 197 37% 24%; 27 | --chart-4: 43 74% 66%; 28 | --chart-5: 27 87% 67%; 29 | } 30 | 31 | .dark { 32 | --background: 240 10% 3.9%; 33 | --foreground: 0 0% 98%; 34 | --card: 240 10% 3.9%; 35 | --card-foreground: 0 0% 98%; 36 | --popover: 240 10% 3.9%; 37 | --popover-foreground: 0 0% 98%; 38 | --primary: 0 0% 98%; 39 | --primary-foreground: 240 5.9% 10%; 40 | --secondary: 240 3.7% 15.9%; 41 | --secondary-foreground: 0 0% 98%; 42 | --muted: 240 3.7% 15.9%; 43 | --muted-foreground: 240 5% 64.9%; 44 | --accent: 240 3.7% 15.9%; 45 | --accent-foreground: 0 0% 98%; 46 | --destructive: 0 62.8% 30.6%; 47 | --destructive-foreground: 0 0% 98%; 48 | --border: 240 3.7% 15.9%; 49 | --input: 240 3.7% 15.9%; 50 | --ring: 240 4.9% 83.9%; 51 | --chart-1: 220 70% 50%; 52 | --chart-2: 160 60% 45%; 53 | --chart-3: 30 80% 55%; 54 | --chart-4: 280 65% 60%; 55 | --chart-5: 340 75% 55%; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /templates/next/starter.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Dependencies are auto-detected and installed. 3 | */ 4 | import type { NextApiRequest, NextApiResponse } from "next"; 5 | import { useState, useEffect } from "react"; 6 | import axios from "axios"; 7 | 8 | /** 9 | * Main App component. Feel free to create additional components within this file. 10 | */ 11 | export const App = () => { 12 | const [data, setData] = useState([]); 13 | const [emailFilter, setEmailFilter] = useState(""); 14 | 15 | useEffect(() => { 16 | fetchData(); 17 | }, [emailFilter]); 18 | 19 | const fetchData = async () => { 20 | try { 21 | const response = await axios.get(`/api/users?email=${emailFilter}`); 22 | setData(response.data); 23 | } catch (err) { 24 | console.error("Error fetching data:", err); 25 | } 26 | }; 27 | 28 | const handleEmailFilterChange = (e: React.ChangeEvent) => { 29 | setEmailFilter(e.target.value); 30 | }; 31 | 32 | return ( 33 |
34 |

User Data Table

35 |
36 | 39 | 47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {data.map((user) => ( 59 | 60 | 61 | 62 | 63 | 66 | 67 | ))} 68 | 69 |
IDNameEmailCompany
{user.id}{user.name}{user.email} 64 | {user.company.name} 65 |
70 |
71 | ); 72 | }; 73 | 74 | /** 75 | * Will auto-generate api routes for you. 76 | * For route params use :paramName in the path. 77 | */ 78 | export const api = [ 79 | { 80 | method: "GET", 81 | path: "/api/users", 82 | handler: async (req: NextApiRequest, res: NextApiResponse) => { 83 | try { 84 | const { email } = req.query; 85 | let url = "https://jsonplaceholder.typicode.com/users"; 86 | if (email) { 87 | url += `?email=${email}`; 88 | } 89 | const response = await axios.get(url); 90 | res.status(200).json(response.data); 91 | } catch (error) { 92 | res.status(500).json({ error: "Error fetching user data" }); 93 | } 94 | }, 95 | }, 96 | ]; 97 | -------------------------------------------------------------------------------- /templates/next/startershadcn.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import type { NextApiRequest, NextApiResponse } from "next"; 3 | import { Input } from "@/components/ui/input"; 4 | import { Button } from '@/components/ui/button'; 5 | import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card"; 6 | import {Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"; 7 | 8 | export const App = () => { 9 | const [name, setName] = useState(""); 10 | const [greeting, setGreeting] = useState(""); 11 | const [isLoading, setIsLoading] = useState(false); 12 | 13 | const handleGreet = async () => { 14 | setIsLoading(true); 15 | try { 16 | const response = await fetch(`/api/greet?name=${name}`); 17 | const data = await response.text(); 18 | setGreeting(data); 19 | } catch (error) { 20 | console.error("Error fetching greeting:", error); 21 | setGreeting("Failed to fetch greeting"); 22 | } finally { 23 | setIsLoading(false); 24 | } 25 | }; 26 | 27 | return ( 28 | 29 | 30 | Hello World 31 | Welcome to snaptail! 32 | 33 | 34 |
35 | setName(e.target.value)} 39 | /> 40 | 41 | 42 | 43 | 44 | 45 |

46 | This is a simple React component using shadcn/ui components. 47 |

48 |
49 |
50 |
51 |
52 | 53 | 56 | 57 | {greeting && ( 58 | 59 |

60 | {greeting} 61 |

62 |
63 | )} 64 |
65 | ); 66 | }; 67 | 68 | 69 | /** 70 | * Will auto-generate api routes for you. 71 | * For route params use :paramName in the path. 72 | */ 73 | export const api = [ 74 | { 75 | method: "GET", 76 | path: "/api/greet", 77 | handler: async (req: NextApiRequest, reply: NextApiResponse) => { 78 | return reply.send(`Hello ${req.query.name as string} from API!`); 79 | }, 80 | }, 81 | ]; -------------------------------------------------------------------------------- /templates/next/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Just to please VSCode to provide intellisense for imports 2 | { 3 | "compilerOptions": { 4 | "esModuleInterop": true, 5 | "jsx": "react-jsx", 6 | "baseUrl": ".snaptail/node_modules", // Base directory for resolving non-relative module names 7 | "typeRoots": ["./.snaptail/node_modules/@types"], 8 | "paths": { 9 | "@/*": ["../src/*"], 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /templates/starter.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import axios from "axios"; 3 | import { TextInput, Button, Container, Paper, Stack } from "@mantine/core"; 4 | 5 | export const App = () => { 6 | const [formData, setFormData] = useState({ name: "", email: "" }); 7 | 8 | const handleSubmit = async (event) => { 9 | event.preventDefault(); 10 | try { 11 | const response = await axios.post("/api/v1/user", formData); 12 | console.log("API response:", response.data); 13 | alert(JSON.stringify(response.data)); 14 | } catch (error) { 15 | console.error("API error:", error); 16 | } 17 | }; 18 | 19 | const handleChange = (event) => { 20 | setFormData({ ...formData, [event.target.name]: event.target.value }); 21 | }; 22 | 23 | return ( 24 | 25 | 26 |
27 | 28 | 35 | 43 | 44 | 45 |
46 |
47 |
48 | ); 49 | }; 50 | 51 | export const api = [ 52 | { 53 | method: "POST", 54 | path: "/api/v1/user", 55 | handler: async (req, reply) => { 56 | // Process the user data here 57 | const { name, email } = req.body; 58 | return reply.send({ 59 | message: `User ${name} with email ${email} created successfully`, 60 | }); 61 | }, 62 | }, 63 | ]; 64 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "NodeNext", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | "checkJs": false, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 63 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 64 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 65 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 66 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 67 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 68 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 69 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 70 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 71 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 72 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 73 | 74 | /* Interop Constraints */ 75 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 76 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 77 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 78 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 79 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 80 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 81 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 82 | 83 | /* Type Checking */ 84 | "strict": true, /* Enable all strict type-checking options. */ 85 | "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 86 | "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 87 | "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 88 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 89 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 90 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 91 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 92 | "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 93 | "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 94 | "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 95 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 96 | "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 97 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 98 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 99 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 100 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 101 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 102 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 103 | 104 | /* Completeness */ 105 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 106 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 107 | }, 108 | "include": ["src/**/*.ts"], 109 | "exclude": ["node_modules", "dist", "_playground"] 110 | } 111 | --------------------------------------------------------------------------------