├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── dist ├── constants │ ├── index.js │ └── templates.js ├── index.js └── utils │ ├── index.js │ ├── next.helpers.js │ └── vite.helpers.js ├── package.json ├── pnpm-lock.yaml ├── src ├── constants │ ├── index.ts │ └── templates.ts ├── index.ts └── utils │ ├── index.ts │ ├── next.helpers.ts │ └── vite.helpers.ts ├── tsconfig.json └── types.d.ts /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Consensys/create-web3-template/99710eaf75893d452acceffc2f95f10bb5475c86/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | demo 3 | *.yaml 4 | dist -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create Web3 Template CLI 2 | 3 | This is a CLI tool that scaffolds Next.js and React projects with a focus on Web3 development. 4 | 5 | ## Features 6 | 7 | - **Framework Options**: Choose between [Next.js](https://nextjs.org/) and [React with Vite](https://vitejs.dev/) for your frontend application. 8 | - **Blockchain Tooling**: Select either [Hardhat](https://hardhat.org/) or [Foundry](https://getfoundry.sh/) for smart contract development. 9 | - **Package Manager Choice**: Use your preferred package manager: **npm**, **yarn**, or **pnpm**. 10 | - **TypeScript Support**: Write strongly-typed code with built-in TypeScript support. 11 | - **Tailwind CSS**: Style your application with utility-first CSS. 12 | - **Viem and Wagmi**: Integrate with Ethereum using [Viem](https://viem.sh/) and [Wagmi](https://wagmi.sh/) libraries. 13 | - **Monorepo Setup**: Organize your frontend and smart contracts in a monorepo structure. 14 | 15 | ## Getting Started 16 | 17 | ### Installation 18 | 19 | To create a new project using the Web3 Template CLI, run one of the following commands: 20 | 21 | Using **pnpm**: 22 | 23 | ```bash 24 | pnpm create @consensys/create-web3-template [project-name] 25 | ``` 26 | 27 | Using **npx**: 28 | 29 | ```bash 30 | npx @consensys/create-web3-template [project-name] 31 | ``` 32 | 33 | ### Interactive Setup 34 | 35 | After running the command, the CLI will guide you through the setup process with the following prompts: 36 | 37 | 1. **Project Name**: Specify a name for your project if not provided in the command. 38 | 2. **Framework Selection**: Choose between **Next.js** and **React (Vite)**. 39 | 3. **Blockchain Tooling**: Select **Hardhat** or **Foundry** for smart contract development. 40 | 4. **Package Manager**: Choose your preferred package manager: **npm**, **yarn**, or **pnpm**. 41 | 42 | ### Example 43 | 44 | ```bash 45 | npx @consensys/create-web3-template my-web3-project 46 | ``` 47 | 48 | ## Project Structure 49 | 50 | The generated project will have the following structure: 51 | 52 | ``` 53 | my-web3-project/ 54 | ├── packages/ 55 | │ ├── blockchain/ # Smart contracts and blockchain tooling 56 | │ └── site/ # Frontend application (Next.js or React) 57 | ├── pnpm-workspace.yaml (if using pnpm) 58 | ├── package.json 59 | └── .gitignore 60 | ``` 61 | 62 | - **packages/blockchain**: Contains your smart contracts and related tooling. 63 | - **packages/site**: Contains your frontend application. 64 | 65 | ## Installing Dependencies 66 | 67 | Navigate to your project directory and install the dependencies: 68 | 69 | ```bash 70 | cd my-web3-project 71 | 72 | # If you chose pnpm 73 | pnpm install 74 | 75 | # If you chose npm 76 | npm install 77 | 78 | # If you chose yarn 79 | yarn install 80 | ``` 81 | 82 | ## Running the Application 83 | 84 | ### Backend (Smart Contracts) 85 | 86 | Navigate to the `blockchain` package to work on your smart contracts. 87 | 88 | ```bash 89 | cd packages/blockchain 90 | ``` 91 | 92 | - **Hardhat Users**: Refer to the [Hardhat documentation](https://hardhat.org/getting-started/) for commands to compile, test, and deploy your contracts. 93 | - **Foundry Users**: Refer to the [Foundry Book](https://book.getfoundry.sh/) for instructions on using Foundry. 94 | 95 | ### Frontend Application 96 | 97 | Navigate to the `site` package to run your frontend application. 98 | 99 | ```bash 100 | cd packages/site 101 | 102 | # Start the development server 103 | # Using pnpm 104 | pnpm run dev 105 | 106 | # Using npm 107 | npm run dev 108 | 109 | # Using yarn 110 | yarn dev 111 | ``` 112 | 113 | The development server will start, and you can view your application in the browser. 114 | 115 | ## Wagmi Configuration 116 | 117 | The project includes a default **Wagmi** configuration for connecting to the Linea Testnet. You can find this configuration in the `wagmi.config.ts` file in your frontend application: 118 | 119 | ``` 120 | import { http, createConfig } from "wagmi"; 121 | import { lineaTestnet } from "wagmi/chains"; 122 | import { metaMask } from "wagmi/connectors"; 123 | 124 | export const config = createConfig({ 125 | chains: [lineaTestnet], 126 | connectors: [metaMask()], 127 | transports: { 128 | [lineaTestnet.id]: http(), 129 | }, 130 | }); 131 | ``` 132 | 133 | Feel free to modify this configuration to connect to different networks or use different connectors. 134 | 135 | ## Monorepo Management 136 | 137 | This project uses a monorepo structure to keep your frontend and backend code organized and in sync. 138 | 139 | - **Package Management**: If you selected **pnpm**, a `pnpm-workspace.yaml` file is included to manage the monorepo packages. 140 | - **Scripts**: Each package (`blockchain` and `site`) can have its own scripts. Navigate into each package directory to run and manage scripts specific to that package. 141 | 142 | ## Customization 143 | 144 | After project creation, you can customize the setup according to your needs: 145 | 146 | - **Add Dependencies**: Install additional npm packages as required. 147 | - **Modify Configurations**: Update Tailwind CSS, TypeScript, or other configurations. 148 | - **Update Smart Contracts**: Write and deploy your own smart contracts using Hardhat or Foundry. 149 | 150 | ## Contributing 151 | 152 | Contributions are welcome! If you have suggestions or find issues, please open an issue or submit a pull request. 153 | 154 | ## License 155 | 156 | This project is licensed under the MIT License. 157 | 158 | --- 159 | -------------------------------------------------------------------------------- /dist/constants/index.js: -------------------------------------------------------------------------------- 1 | export var FRAMEWORK_CHOICES = [ 2 | { 3 | name: "React (with Vite)", 4 | value: "react", 5 | }, 6 | { 7 | name: "Next.js", 8 | value: "nextjs", 9 | }, 10 | ]; 11 | export var BLOCKCHAIN_TOOLING_CHOICES = [ 12 | { 13 | name: "HardHat", 14 | value: "hardhat", 15 | }, 16 | { 17 | name: "Foundry", 18 | value: "foundry", 19 | }, 20 | { 21 | name: "None", 22 | value: "none", 23 | }, 24 | ]; 25 | export var PACAKGE_MANAGER_CHOICES = [ 26 | { 27 | name: "Yarn", 28 | value: "yarn", 29 | }, 30 | { 31 | name: "NPM", 32 | value: "npm", 33 | }, 34 | { 35 | name: "pnpm", 36 | value: "pnpm", 37 | }, 38 | ]; 39 | export var NPM_COMMAND = function (projectName, path) { 40 | return path 41 | ? "cd ".concat(path, " && npm init vite@latest . -- --template react-ts") 42 | : "npm init vite@latest ".concat(projectName, " -- --template react-ts"); 43 | }; 44 | export var YARN_COMMAND = function (projectName, path) { 45 | return path 46 | ? "cd ".concat(path, " && yarn create vite . --template react-ts") 47 | : "yarn create vite ".concat(projectName, " --template react-ts"); 48 | }; 49 | export var PNPM_COMMAND = function (projectName, path) { 50 | return path 51 | ? "cd ".concat(path, " && pnpm create vite . --template react-ts") 52 | : "pnpm create vite ".concat(projectName, " --template react-ts"); 53 | }; 54 | -------------------------------------------------------------------------------- /dist/constants/templates.js: -------------------------------------------------------------------------------- 1 | export var TEMPLATES = [ 2 | { 3 | name: "Next Web3 Starter", 4 | id: "next-web3-starter", 5 | repo_url: "https://github.com/Consensys/next-web3-starter.git", 6 | packageName: "@consensys/web3-starter", 7 | }, 8 | { 9 | name: "React Web3 Starter", 10 | id: "react-web3-starter", 11 | repo_url: "https://github.com/Consensys/react-web3-starter.git", 12 | packageName: "@consensys/react-web3-starter", 13 | }, 14 | { 15 | name: "React/Vite and foundry starter", 16 | id: "foundry-starter", 17 | repo_url: "https://github.com/cxalem/foundry-template", 18 | packageName: "@consensys/foundry-template", 19 | }, 20 | ]; 21 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __generator = (this && this.__generator) || function (thisArg, body) { 12 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 13 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 14 | function verb(n) { return function (v) { return step([n, v]); }; } 15 | function step(op) { 16 | if (f) throw new TypeError("Generator is already executing."); 17 | while (g && (g = 0, op[0] && (_ = 0)), _) try { 18 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 19 | if (y = 0, t) op = [op[0] & 2, t.value]; 20 | switch (op[0]) { 21 | case 0: case 1: t = op; break; 22 | case 4: _.label++; return { value: op[1], done: false }; 23 | case 5: _.label++; y = op[1]; op = [0]; continue; 24 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 25 | default: 26 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 27 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 28 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 29 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 30 | if (t[2]) _.ops.pop(); 31 | _.trys.pop(); continue; 32 | } 33 | op = body.call(thisArg, _); 34 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 35 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 36 | } 37 | }; 38 | import { Command } from "commander"; 39 | import { createProject } from "./utils/index.js"; 40 | function main() { 41 | return __awaiter(this, void 0, void 0, function () { 42 | var program; 43 | return __generator(this, function (_a) { 44 | program = new Command() 45 | .name("create-web3-template") 46 | .description("Web3 starter template CLI tool.") 47 | .arguments("[project-name]") 48 | .action(function (args) { return createProject(args); }) 49 | .version("0.0.2"); 50 | program.parse(process.argv); 51 | return [2 /*return*/]; 52 | }); 53 | }); 54 | } 55 | main().catch(function (error) { 56 | console.error("An unexpected error occurred:", error); 57 | }); 58 | -------------------------------------------------------------------------------- /dist/utils/index.js: -------------------------------------------------------------------------------- 1 | var __assign = (this && this.__assign) || function () { 2 | __assign = Object.assign || function(t) { 3 | for (var s, i = 1, n = arguments.length; i < n; i++) { 4 | s = arguments[i]; 5 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 6 | t[p] = s[p]; 7 | } 8 | return t; 9 | }; 10 | return __assign.apply(this, arguments); 11 | }; 12 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 13 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 14 | return new (P || (P = Promise))(function (resolve, reject) { 15 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 16 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 17 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 18 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 19 | }); 20 | }; 21 | var __generator = (this && this.__generator) || function (thisArg, body) { 22 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 23 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 24 | function verb(n) { return function (v) { return step([n, v]); }; } 25 | function step(op) { 26 | if (f) throw new TypeError("Generator is already executing."); 27 | while (g && (g = 0, op[0] && (_ = 0)), _) try { 28 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 29 | if (y = 0, t) op = [op[0] & 2, t.value]; 30 | switch (op[0]) { 31 | case 0: case 1: t = op; break; 32 | case 4: _.label++; return { value: op[1], done: false }; 33 | case 5: _.label++; y = op[1]; op = [0]; continue; 34 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 35 | default: 36 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 37 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 38 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 39 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 40 | if (t[2]) _.ops.pop(); 41 | _.trys.pop(); continue; 42 | } 43 | op = body.call(thisArg, _); 44 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 45 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 46 | } 47 | }; 48 | import { exec } from "child_process"; 49 | import { promises as fs } from "fs"; 50 | import { BLOCKCHAIN_TOOLING_CHOICES, FRAMEWORK_CHOICES, PACAKGE_MANAGER_CHOICES, } from "../constants/index.js"; 51 | import { createReactApp } from "./vite.helpers.js"; 52 | import { createNextApp } from "./next.helpers.js"; 53 | import path from "path"; 54 | import util from "util"; 55 | import inquirer from "inquirer"; 56 | export var execAsync = util.promisify(exec); 57 | var promptForFramework = function () { return __awaiter(void 0, void 0, void 0, function () { 58 | var frameworkChoice, framework; 59 | return __generator(this, function (_a) { 60 | switch (_a.label) { 61 | case 0: 62 | frameworkChoice = FRAMEWORK_CHOICES.map(function (choice) { return choice.name; }); 63 | return [4 /*yield*/, inquirer.prompt([ 64 | { 65 | type: "list", 66 | name: "framework", 67 | message: "Please select the framework you want to use:", 68 | choices: frameworkChoice, 69 | }, 70 | ])]; 71 | case 1: 72 | framework = (_a.sent()).framework; 73 | console.log("Selected framework: ".concat(framework)); 74 | return [2 /*return*/, framework]; 75 | } 76 | }); 77 | }); }; 78 | var promptForTooling = function () { return __awaiter(void 0, void 0, void 0, function () { 79 | var toolingChoice, tooling; 80 | return __generator(this, function (_a) { 81 | switch (_a.label) { 82 | case 0: 83 | toolingChoice = BLOCKCHAIN_TOOLING_CHOICES.map(function (choice) { return choice.name; }); 84 | return [4 /*yield*/, inquirer.prompt([ 85 | { 86 | type: "list", 87 | name: "tooling", 88 | message: "Would you like to use HardHat or Foundry?", 89 | choices: toolingChoice, 90 | }, 91 | ])]; 92 | case 1: 93 | tooling = (_a.sent()).tooling; 94 | console.log("Selected tooling: ".concat(tooling)); 95 | return [2 /*return*/, tooling]; 96 | } 97 | }); 98 | }); }; 99 | var promptForPackageManager = function () { return __awaiter(void 0, void 0, void 0, function () { 100 | var packageManagerChoice, packageManager; 101 | return __generator(this, function (_a) { 102 | switch (_a.label) { 103 | case 0: 104 | packageManagerChoice = PACAKGE_MANAGER_CHOICES.map(function (choice) { return choice.name; }); 105 | return [4 /*yield*/, inquirer.prompt([ 106 | { 107 | type: "list", 108 | name: "packageManager", 109 | message: "Please select the package manager you want to use:", 110 | choices: packageManagerChoice, 111 | }, 112 | ])]; 113 | case 1: 114 | packageManager = (_a.sent()).packageManager; 115 | console.log("Selected package manager: ".concat(packageManager)); 116 | return [2 /*return*/, packageManager]; 117 | } 118 | }); 119 | }); }; 120 | var promptForProjectDetails = function (args) { return __awaiter(void 0, void 0, void 0, function () { 121 | var projectName; 122 | return __generator(this, function (_a) { 123 | switch (_a.label) { 124 | case 0: 125 | if (!!args) return [3 /*break*/, 2]; 126 | return [4 /*yield*/, inquirer.prompt([ 127 | { 128 | type: "input", 129 | name: "projectName", 130 | message: "Please specify a name for your project: ", 131 | validate: function (input) { return (input ? true : "Project name cannot be empty"); }, 132 | }, 133 | ])]; 134 | case 1: 135 | projectName = (_a.sent()).projectName; 136 | console.log("Creating project with name:", projectName); 137 | return [2 /*return*/, projectName]; 138 | case 2: return [2 /*return*/, args]; 139 | } 140 | }); 141 | }); }; 142 | var promptForOptions = function (args) { return __awaiter(void 0, void 0, void 0, function () { 143 | var projectName, framework, tooling, packageManager, options; 144 | var _a, _b, _c; 145 | return __generator(this, function (_d) { 146 | switch (_d.label) { 147 | case 0: return [4 /*yield*/, promptForProjectDetails(args)]; 148 | case 1: 149 | projectName = _d.sent(); 150 | return [4 /*yield*/, promptForFramework()]; 151 | case 2: 152 | framework = _d.sent(); 153 | return [4 /*yield*/, promptForTooling()]; 154 | case 3: 155 | tooling = _d.sent(); 156 | return [4 /*yield*/, promptForPackageManager()]; 157 | case 4: 158 | packageManager = _d.sent(); 159 | options = { 160 | projectName: projectName, 161 | framework: (_a = FRAMEWORK_CHOICES.find(function (choice) { return choice.name === framework; })) === null || _a === void 0 ? void 0 : _a.value, 162 | blockchain_tooling: (_b = BLOCKCHAIN_TOOLING_CHOICES.find(function (choice) { return choice.name === tooling; })) === null || _b === void 0 ? void 0 : _b.value, 163 | packageManager: (_c = PACAKGE_MANAGER_CHOICES.find(function (choice) { return choice.name === packageManager; })) === null || _c === void 0 ? void 0 : _c.value, 164 | }; 165 | return [2 /*return*/, options]; 166 | } 167 | }); 168 | }); }; 169 | var initializeMonorepo = function (options) { return __awaiter(void 0, void 0, void 0, function () { 170 | var projectName, packageManager; 171 | return __generator(this, function (_a) { 172 | switch (_a.label) { 173 | case 0: 174 | projectName = options.projectName, packageManager = options.packageManager; 175 | console.log("Initializing monorepo..."); 176 | if (!(packageManager === "pnpm")) return [3 /*break*/, 2]; 177 | return [4 /*yield*/, fs.writeFile(path.join(projectName, "pnpm-workspace.yaml"), "packages:\n - 'packages/*'")]; 178 | case 1: 179 | _a.sent(); 180 | _a.label = 2; 181 | case 2: return [4 /*yield*/, fs.writeFile(path.join(projectName, ".gitignore"), "node_modules")]; 182 | case 3: 183 | _a.sent(); 184 | return [4 /*yield*/, execAsync("cd ".concat(projectName, " && npm init -y"))]; 185 | case 4: 186 | _a.sent(); 187 | return [4 /*yield*/, execAsync("cd ".concat(projectName, " && npm init -w ./packages/blockchain -y"))]; 188 | case 5: 189 | _a.sent(); 190 | return [4 /*yield*/, execAsync("cd ".concat(projectName, " && npm init -w ./packages/site -y"))]; 191 | case 6: 192 | _a.sent(); 193 | return [4 /*yield*/, fs.rm(path.join(projectName, "packages", "blockchain", "package.json"))]; 194 | case 7: 195 | _a.sent(); 196 | return [4 /*yield*/, fs.rm(path.join(projectName, "packages", "site", "package.json"))]; 197 | case 8: 198 | _a.sent(); 199 | return [4 /*yield*/, fs.rm(path.join(projectName, "node_modules"), { recursive: true })]; 200 | case 9: 201 | _a.sent(); 202 | return [2 /*return*/]; 203 | } 204 | }); 205 | }); }; 206 | var createHardhatProject = function (options) { return __awaiter(void 0, void 0, void 0, function () { 207 | var projectName, framework; 208 | return __generator(this, function (_a) { 209 | switch (_a.label) { 210 | case 0: 211 | projectName = options.projectName, framework = options.framework; 212 | return [4 /*yield*/, fs.mkdir(projectName)]; 213 | case 1: 214 | _a.sent(); 215 | console.log("Creating a project with HardHat..."); 216 | return [4 /*yield*/, initializeMonorepo(options)]; 217 | case 2: 218 | _a.sent(); 219 | return [4 /*yield*/, execAsync("git clone https://github.com/cxalem/hardhat-template.git ".concat(path.join(projectName, "packages", "blockchain")))]; 220 | case 3: 221 | _a.sent(); 222 | if (!(framework === "nextjs")) return [3 /*break*/, 5]; 223 | return [4 /*yield*/, createNextApp(options, path.join(projectName, "packages", "site"))]; 224 | case 4: 225 | _a.sent(); 226 | return [3 /*break*/, 7]; 227 | case 5: return [4 /*yield*/, createReactApp(options, path.join(projectName, "packages", "site"))]; 228 | case 6: 229 | _a.sent(); 230 | _a.label = 7; 231 | case 7: return [2 /*return*/]; 232 | } 233 | }); 234 | }); }; 235 | var createFoundryProject = function (options) { return __awaiter(void 0, void 0, void 0, function () { 236 | var projectName, framework; 237 | return __generator(this, function (_a) { 238 | switch (_a.label) { 239 | case 0: 240 | projectName = options.projectName, framework = options.framework; 241 | return [4 /*yield*/, fs.mkdir(projectName)]; 242 | case 1: 243 | _a.sent(); 244 | console.log("Creating a project with Foundry..."); 245 | return [4 /*yield*/, initializeMonorepo(options)]; 246 | case 2: 247 | _a.sent(); 248 | if (!(framework === "nextjs")) return [3 /*break*/, 4]; 249 | return [4 /*yield*/, createNextApp(options, path.join(projectName, "packages", "site"))]; 250 | case 3: 251 | _a.sent(); 252 | return [3 /*break*/, 6]; 253 | case 4: return [4 /*yield*/, createReactApp(options, path.join(projectName, "packages", "site"))]; 254 | case 5: 255 | _a.sent(); 256 | _a.label = 6; 257 | case 6: return [4 /*yield*/, execAsync("\n cd ".concat(projectName, "/packages/blockchain && forge init . --no-commit\n "))]; 258 | case 7: 259 | _a.sent(); 260 | return [2 /*return*/]; 261 | } 262 | }); 263 | }); }; 264 | export var pathOrProjectName = function (projectName, projectPath) { 265 | return projectPath ? projectPath : projectName; 266 | }; 267 | export var updatePackageJsonDependencies = function (dependencies, projectPath) { return __awaiter(void 0, void 0, void 0, function () { 268 | var packageJsonPath, packageJsonContent, packageJson, newPackageJsonContent; 269 | return __generator(this, function (_a) { 270 | switch (_a.label) { 271 | case 0: 272 | packageJsonPath = path.join(projectPath, "package.json"); 273 | return [4 /*yield*/, fs.readFile(packageJsonPath, "utf-8")]; 274 | case 1: 275 | packageJsonContent = _a.sent(); 276 | packageJson = JSON.parse(packageJsonContent); 277 | packageJson.dependencies = __assign(__assign({}, packageJson.dependencies), dependencies); 278 | newPackageJsonContent = JSON.stringify(packageJson, null, 2); 279 | return [4 /*yield*/, fs.writeFile(packageJsonPath, newPackageJsonContent, "utf-8")]; 280 | case 2: 281 | _a.sent(); 282 | console.log("Dependencies added to package.json"); 283 | return [2 /*return*/]; 284 | } 285 | }); 286 | }); }; 287 | export var createWagmiConfigFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 288 | return __generator(this, function (_a) { 289 | switch (_a.label) { 290 | case 0: return [4 /*yield*/, fs.writeFile(path.join(projectPath, "wagmi.config.ts"), "\nimport { http, createConfig } from \"wagmi\";\nimport { lineaTestnet } from \"wagmi/chains\";\nimport { metaMask } from \"wagmi/connectors\";\n\nexport const config = createConfig({\n chains: [lineaTestnet],\n connectors: [metaMask()],\n transports: {\n [lineaTestnet.id]: http(),\n },\n});\n")]; 291 | case 1: 292 | _a.sent(); 293 | return [2 /*return*/]; 294 | } 295 | }); 296 | }); }; 297 | export var usePackageManager = function (packageManager) { 298 | switch (packageManager) { 299 | case "npm": 300 | return "--use-npm"; 301 | case "yarn": 302 | return "--use-yarn"; 303 | case "pnpm": 304 | return "--use-pnpm"; 305 | default: 306 | return "--use-npm"; 307 | } 308 | }; 309 | export var createProject = function (args) { return __awaiter(void 0, void 0, void 0, function () { 310 | var options, _a; 311 | return __generator(this, function (_b) { 312 | switch (_b.label) { 313 | case 0: return [4 /*yield*/, promptForOptions(args)]; 314 | case 1: 315 | options = _b.sent(); 316 | if (options.blockchain_tooling === "hardhat") { 317 | createHardhatProject(options); 318 | return [2 /*return*/]; 319 | } 320 | if (options.blockchain_tooling === "foundry") { 321 | createFoundryProject(options); 322 | return [2 /*return*/]; 323 | } 324 | _a = options.framework; 325 | switch (_a) { 326 | case "nextjs": return [3 /*break*/, 2]; 327 | case "react": return [3 /*break*/, 4]; 328 | } 329 | return [3 /*break*/, 6]; 330 | case 2: return [4 /*yield*/, createNextApp(options)]; 331 | case 3: 332 | _b.sent(); 333 | return [3 /*break*/, 7]; 334 | case 4: return [4 /*yield*/, createReactApp(options)]; 335 | case 5: 336 | _b.sent(); 337 | return [3 /*break*/, 7]; 338 | case 6: return [3 /*break*/, 7]; 339 | case 7: return [2 /*return*/]; 340 | } 341 | }); 342 | }); }; 343 | -------------------------------------------------------------------------------- /dist/utils/next.helpers.js: -------------------------------------------------------------------------------- 1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (g && (g = 0, op[0] && (_ = 0)), _) try { 17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [op[0] & 2, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | import path from "path"; 38 | import { promises as fs } from "fs"; 39 | import { createWagmiConfigFile, execAsync, pathOrProjectName, updatePackageJsonDependencies, usePackageManager, } from "./index.js"; 40 | export var createNextApp = function (options, projectPath) { return __awaiter(void 0, void 0, void 0, function () { 41 | var projectName, packageManager, command, error_1; 42 | return __generator(this, function (_a) { 43 | switch (_a.label) { 44 | case 0: 45 | console.log("Creating Next.js project..."); 46 | _a.label = 1; 47 | case 1: 48 | _a.trys.push([1, 8, , 9]); 49 | projectName = options.projectName, packageManager = options.packageManager; 50 | command = "npx create-next-app ".concat(pathOrProjectName(projectName, projectPath), " --ts --tailwind --eslint --app --src-dir --skip-install --import-alias \"@/*\" ").concat(usePackageManager(packageManager), " --turbopack"); 51 | return [4 /*yield*/, execAsync(command)]; 52 | case 2: 53 | _a.sent(); 54 | return [4 /*yield*/, updatePackageJsonDependencies({ 55 | "@consensys/connect-button": "^1.0.3", 56 | "@tanstack/react-query": "^5.51.23", 57 | viem: "2.x", 58 | wagmi: "^2.12.5", 59 | }, pathOrProjectName(projectName, projectPath))]; 60 | case 3: 61 | _a.sent(); 62 | return [4 /*yield*/, updateLayoutFile(pathOrProjectName(projectName, projectPath))]; 63 | case 4: 64 | _a.sent(); 65 | return [4 /*yield*/, createProvider(pathOrProjectName(projectName, projectPath))]; 66 | case 5: 67 | _a.sent(); 68 | return [4 /*yield*/, createWagmiConfigFile(projectPath ? "".concat(projectPath, "/src") : "".concat(projectName, "/src"))]; 69 | case 6: 70 | _a.sent(); 71 | return [4 /*yield*/, updatePageFile(pathOrProjectName(projectName, projectPath))]; 72 | case 7: 73 | _a.sent(); 74 | console.log("Next.js project created successfully!"); 75 | return [3 /*break*/, 9]; 76 | case 8: 77 | error_1 = _a.sent(); 78 | console.error("An unexpected error occurred:", error_1); 79 | return [3 /*break*/, 9]; 80 | case 9: return [2 /*return*/]; 81 | } 82 | }); 83 | }); }; 84 | var updateLayoutFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 85 | var layoutFilePath; 86 | return __generator(this, function (_a) { 87 | switch (_a.label) { 88 | case 0: 89 | layoutFilePath = path.join(projectPath, "src", "app", "layout.tsx"); 90 | return [4 /*yield*/, fs.writeFile(layoutFilePath, "\n \"use client\";\n\n import { Inter } from \"next/font/google\";\n import \"./globals.css\";\n import Provider from \"@/providers/WagmiProvider\";\n \n const inter = Inter({ subsets: [\"latin\"] });\n \n export default function RootLayout({\n children,\n }: Readonly<{\n children: React.ReactNode;\n }>) {\n return (\n \n \n {children}\n \n \n );\n }\n \n")]; 91 | case 1: 92 | _a.sent(); 93 | return [2 /*return*/]; 94 | } 95 | }); 96 | }); }; 97 | var createProvider = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 98 | var providerFilePath; 99 | return __generator(this, function (_a) { 100 | switch (_a.label) { 101 | case 0: return [4 /*yield*/, fs.mkdir(path.join(projectPath, "src", "providers"))]; 102 | case 1: 103 | _a.sent(); 104 | providerFilePath = path.join(projectPath, "src", "providers", "WagmiProvider.tsx"); 105 | return [4 /*yield*/, fs.writeFile(providerFilePath, "\n\"use client\";\n\nimport { WagmiProvider } from \"wagmi\";\nimport { config } from \"@/wagmi.config\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { createPublicClient, http } from \"viem\";\nimport { linea } from \"viem/chains\";\n\nexport const client = createPublicClient({\n chain: linea,\n transport: http(),\n});\n\ninterface WagmiProviderProps {\n children: React.ReactNode;\n}\n\nconst Provider: React.FC = ({ children }) => {\n const queryClient = new QueryClient();\n\n return (\n \n {children}\n \n );\n};\n\nexport default Provider;\n ")]; 106 | case 2: 107 | _a.sent(); 108 | return [2 /*return*/]; 109 | } 110 | }); 111 | }); }; 112 | var updatePageFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 113 | var pageFilePath; 114 | return __generator(this, function (_a) { 115 | switch (_a.label) { 116 | case 0: 117 | pageFilePath = path.join(projectPath, "src", "app", "page.tsx"); 118 | return [4 /*yield*/, fs.writeFile(pageFilePath, "\n\"use client\";\n\nimport { ConnectButton } from \"@consensys/connect-button\";\nimport { client } from \"@/providers/WagmiProvider\";\nimport { Suspense, useEffect, useState } from \"react\";\nimport { useAccount } from \"wagmi\";\n\nexport default function Home() {\n const { isConnected, address } = useAccount();\n const [blockNumber, setBlockNumber] = useState(null);\n\n useEffect(() => {\n client.getBlockNumber().then((block) => {\n setBlockNumber(block);\n });\n }, []);\n\n return (\n
\n Loading...}>\n
\n
\n \n By RAD Team\n \n
\n \n
\n\n
\n Web3 Starter template\n {isConnected && (\n \n Connected to: {address}\n \n )}\n\n
\n {!blockNumber ? (\n \"Loading block number...\"\n ) : (\n
Linea block number: {Number(blockNumber)}
\n )}\n
\n
\n
\n
\n );\n}\n ")]; 119 | case 1: 120 | _a.sent(); 121 | return [2 /*return*/]; 122 | } 123 | }); 124 | }); }; 125 | -------------------------------------------------------------------------------- /dist/utils/vite.helpers.js: -------------------------------------------------------------------------------- 1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (g && (g = 0, op[0] && (_ = 0)), _) try { 17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [op[0] & 2, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { 38 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { 39 | if (ar || !(i in from)) { 40 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); 41 | ar[i] = from[i]; 42 | } 43 | } 44 | return to.concat(ar || Array.prototype.slice.call(from)); 45 | }; 46 | import path from "path"; 47 | import { promises as fs } from "fs"; 48 | import { NPM_COMMAND, PNPM_COMMAND, YARN_COMMAND } from "../constants/index.js"; 49 | import { createWagmiConfigFile, execAsync, updatePackageJsonDependencies, } from "./index.js"; 50 | export var createReactApp = function (options_1) { 51 | var args_1 = []; 52 | for (var _i = 1; _i < arguments.length; _i++) { 53 | args_1[_i - 1] = arguments[_i]; 54 | } 55 | return __awaiter(void 0, __spreadArray([options_1], args_1, true), void 0, function (options, projectPath) { 56 | var projectName, packageManager, commands, command, error_1; 57 | if (projectPath === void 0) { projectPath = ""; } 58 | return __generator(this, function (_a) { 59 | switch (_a.label) { 60 | case 0: 61 | console.log("Creating React project..."); 62 | projectName = options.projectName, packageManager = options.packageManager; 63 | commands = { 64 | npm: NPM_COMMAND, 65 | yarn: YARN_COMMAND, 66 | pnpm: PNPM_COMMAND, 67 | }; 68 | command = commands[packageManager]; 69 | if (!command) { 70 | console.error("Unsupported package manager: ".concat(packageManager)); 71 | return [2 /*return*/]; 72 | } 73 | _a.label = 1; 74 | case 1: 75 | _a.trys.push([1, 10, , 11]); 76 | return [4 /*yield*/, execAsync(command(projectName, projectPath))]; 77 | case 2: 78 | _a.sent(); 79 | console.log("React project created successfully!"); 80 | return [4 /*yield*/, updatePackageJsonDependencies({ 81 | "@consensys/connect-button": "^1.0.3", 82 | "@tanstack/react-query": "^5.51.23", 83 | viem: "2.x", 84 | wagmi: "^2.12.5", 85 | postcss: "^8.4.41", 86 | tailwindcss: "^3.4.10", 87 | autoprefixer: "^10.4.20", 88 | }, projectPath ? projectPath : projectName)]; 89 | case 3: 90 | _a.sent(); 91 | return [4 /*yield*/, createWagmiConfigFile(projectPath ? projectPath : projectName)]; 92 | case 4: 93 | _a.sent(); 94 | return [4 /*yield*/, updateMainFile(projectPath ? projectPath : projectName)]; 95 | case 5: 96 | _a.sent(); 97 | return [4 /*yield*/, updateAppFile(projectPath ? projectPath : projectName)]; 98 | case 6: 99 | _a.sent(); 100 | return [4 /*yield*/, createClientProvider(projectPath ? projectPath : projectName)]; 101 | case 7: 102 | _a.sent(); 103 | return [4 /*yield*/, createTalwindConfig(projectPath ? projectPath : projectName)]; 104 | case 8: 105 | _a.sent(); 106 | return [4 /*yield*/, updateIndexCss(projectPath ? projectPath : projectName)]; 107 | case 9: 108 | _a.sent(); 109 | return [3 /*break*/, 11]; 110 | case 10: 111 | error_1 = _a.sent(); 112 | console.error("An error occurred during project creation:", error_1); 113 | return [3 /*break*/, 11]; 114 | case 11: return [2 /*return*/]; 115 | } 116 | }); 117 | }); 118 | }; 119 | var updateMainFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 120 | var mainFilePath; 121 | return __generator(this, function (_a) { 122 | switch (_a.label) { 123 | case 0: 124 | mainFilePath = path.join(projectPath, "src", "main.tsx"); 125 | return [4 /*yield*/, fs.writeFile(mainFilePath, "\n import React from \"react\";\n import ReactDOM from \"react-dom/client\";\n import App from \"./App.tsx\";\n import \"./index.css\";\n import { WagmiProvider } from \"wagmi\";\n import { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n import { config } from \"../wagmi.config.ts\";\n \n const queryClient = new QueryClient();\n \n ReactDOM.createRoot(document.getElementById(\"root\")!).render(\n \n \n \n \n \n \n \n );\n ")]; 126 | case 1: 127 | _a.sent(); 128 | return [2 /*return*/]; 129 | } 130 | }); 131 | }); }; 132 | var updateAppFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 133 | var appFilePath; 134 | return __generator(this, function (_a) { 135 | switch (_a.label) { 136 | case 0: 137 | appFilePath = path.join(projectPath, "src", "App.tsx"); 138 | return [4 /*yield*/, fs.writeFile(appFilePath, "\nimport { client } from \"./providers/client\";\nimport { useEffect, useState } from \"react\";\nimport { useAccount } from \"wagmi\";\nimport { ConnectButton } from \"@consensys/connect-button\";\n\nexport default function Home() {\n const { isConnected, address } = useAccount();\n const [blockNumber, setBlockNumber] = useState(null);\n\n useEffect(() => {\n client.getBlockNumber().then((block) => {\n setBlockNumber(block);\n });\n }, []);\n\n return (\n
\n
\n
\n \n By RAD Team\n \n
\n \n
\n\n
\n Web3 Starter template\n {isConnected && (\n \n Connected to: {address}\n \n )}\n\n
\n {!blockNumber ? (\n \"Loading block number...\"\n ) : (\n
Linea block number: {Number(blockNumber)}
\n )}\n
\n
\n
\n );\n}\n ")]; 139 | case 1: 140 | _a.sent(); 141 | return [2 /*return*/]; 142 | } 143 | }); 144 | }); }; 145 | var createClientProvider = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 146 | var clientFilePath; 147 | return __generator(this, function (_a) { 148 | switch (_a.label) { 149 | case 0: return [4 /*yield*/, fs.mkdir(path.join(projectPath, "src", "providers"))]; 150 | case 1: 151 | _a.sent(); 152 | clientFilePath = path.join(projectPath, "src", "providers", "client.ts"); 153 | return [4 /*yield*/, fs.writeFile(clientFilePath, "\nimport { createPublicClient, http } from \"viem\";\nimport { linea } from \"viem/chains\";\n\nexport const client = createPublicClient({\n chain: linea,\n transport: http(),\n});\n ")]; 154 | case 2: 155 | _a.sent(); 156 | return [2 /*return*/]; 157 | } 158 | }); 159 | }); }; 160 | var createTalwindConfig = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 161 | var tailwindConfigPath; 162 | return __generator(this, function (_a) { 163 | switch (_a.label) { 164 | case 0: 165 | tailwindConfigPath = path.join(projectPath, "tailwind.config.js"); 166 | return [4 /*yield*/, execAsync("cd ".concat(projectPath, " && npx tailwindcss init -p"))]; 167 | case 1: 168 | _a.sent(); 169 | return [4 /*yield*/, fs.writeFile(tailwindConfigPath, "\n/** @type {import('tailwindcss').Config} */\nexport default {\n content: [\n \"./index.html\",\n \"./src/**/*.{js,ts,jsx,tsx}\",\n ],\n theme: {\n extend: {},\n },\n plugins: [],\n}\n ")]; 170 | case 2: 171 | _a.sent(); 172 | return [2 /*return*/]; 173 | } 174 | }); 175 | }); }; 176 | var updateIndexCss = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { 177 | var indexCssPath; 178 | return __generator(this, function (_a) { 179 | switch (_a.label) { 180 | case 0: 181 | indexCssPath = path.join(projectPath, "src", "index.css"); 182 | return [4 /*yield*/, fs.writeFile(indexCssPath, "\n@tailwind base;\n@tailwind components;\n@tailwind utilities; \n")]; 183 | case 1: 184 | _a.sent(); 185 | return [2 /*return*/]; 186 | } 187 | }); 188 | }); }; 189 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@consensys/create-web3-template", 3 | "type": "module", 4 | "module": "dist/index.js", 5 | "bin": { 6 | "create-web3-template": "./dist/index.js" 7 | }, 8 | "version": "1.5.7", 9 | "description": "", 10 | "main": "index.js", 11 | "scripts": { 12 | "dev": "tsc -w", 13 | "link-cli": "yarn unlink --global create-web3-template && yarn link --global create-web3-template", 14 | "test": "vitest" 15 | }, 16 | "keywords": [ 17 | "wagmi", 18 | "web3", 19 | "viem", 20 | "consensys", 21 | "next", 22 | "react", 23 | "typescript" 24 | ], 25 | "author": "", 26 | "license": "ISC", 27 | "dependencies": { 28 | "commander": "12.0.0", 29 | "fs": "0.0.1-security", 30 | "inquirer": "9.2.15", 31 | "memfs": "^4.9.3" 32 | }, 33 | "devDependencies": { 34 | "@types/inquirer": "9.0.7", 35 | "@types/node": "20.11.25", 36 | "typescript": "5.4.2", 37 | "vitest": "^1.5.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | commander: 9 | specifier: 12.0.0 10 | version: 12.0.0 11 | fs: 12 | specifier: 0.0.1-security 13 | version: 0.0.1-security 14 | inquirer: 15 | specifier: 9.2.15 16 | version: 9.2.15 17 | memfs: 18 | specifier: ^4.9.3 19 | version: 4.11.1 20 | 21 | devDependencies: 22 | '@types/inquirer': 23 | specifier: 9.0.7 24 | version: 9.0.7 25 | '@types/node': 26 | specifier: 20.11.25 27 | version: 20.11.25 28 | typescript: 29 | specifier: 5.4.2 30 | version: 5.4.2 31 | vitest: 32 | specifier: ^1.5.0 33 | version: 1.6.0(@types/node@20.11.25) 34 | 35 | packages: 36 | 37 | /@esbuild/aix-ppc64@0.21.5: 38 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 39 | engines: {node: '>=12'} 40 | cpu: [ppc64] 41 | os: [aix] 42 | requiresBuild: true 43 | dev: true 44 | optional: true 45 | 46 | /@esbuild/android-arm64@0.21.5: 47 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 48 | engines: {node: '>=12'} 49 | cpu: [arm64] 50 | os: [android] 51 | requiresBuild: true 52 | dev: true 53 | optional: true 54 | 55 | /@esbuild/android-arm@0.21.5: 56 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 57 | engines: {node: '>=12'} 58 | cpu: [arm] 59 | os: [android] 60 | requiresBuild: true 61 | dev: true 62 | optional: true 63 | 64 | /@esbuild/android-x64@0.21.5: 65 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 66 | engines: {node: '>=12'} 67 | cpu: [x64] 68 | os: [android] 69 | requiresBuild: true 70 | dev: true 71 | optional: true 72 | 73 | /@esbuild/darwin-arm64@0.21.5: 74 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 75 | engines: {node: '>=12'} 76 | cpu: [arm64] 77 | os: [darwin] 78 | requiresBuild: true 79 | dev: true 80 | optional: true 81 | 82 | /@esbuild/darwin-x64@0.21.5: 83 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 84 | engines: {node: '>=12'} 85 | cpu: [x64] 86 | os: [darwin] 87 | requiresBuild: true 88 | dev: true 89 | optional: true 90 | 91 | /@esbuild/freebsd-arm64@0.21.5: 92 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 93 | engines: {node: '>=12'} 94 | cpu: [arm64] 95 | os: [freebsd] 96 | requiresBuild: true 97 | dev: true 98 | optional: true 99 | 100 | /@esbuild/freebsd-x64@0.21.5: 101 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 102 | engines: {node: '>=12'} 103 | cpu: [x64] 104 | os: [freebsd] 105 | requiresBuild: true 106 | dev: true 107 | optional: true 108 | 109 | /@esbuild/linux-arm64@0.21.5: 110 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 111 | engines: {node: '>=12'} 112 | cpu: [arm64] 113 | os: [linux] 114 | requiresBuild: true 115 | dev: true 116 | optional: true 117 | 118 | /@esbuild/linux-arm@0.21.5: 119 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 120 | engines: {node: '>=12'} 121 | cpu: [arm] 122 | os: [linux] 123 | requiresBuild: true 124 | dev: true 125 | optional: true 126 | 127 | /@esbuild/linux-ia32@0.21.5: 128 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 129 | engines: {node: '>=12'} 130 | cpu: [ia32] 131 | os: [linux] 132 | requiresBuild: true 133 | dev: true 134 | optional: true 135 | 136 | /@esbuild/linux-loong64@0.21.5: 137 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 138 | engines: {node: '>=12'} 139 | cpu: [loong64] 140 | os: [linux] 141 | requiresBuild: true 142 | dev: true 143 | optional: true 144 | 145 | /@esbuild/linux-mips64el@0.21.5: 146 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 147 | engines: {node: '>=12'} 148 | cpu: [mips64el] 149 | os: [linux] 150 | requiresBuild: true 151 | dev: true 152 | optional: true 153 | 154 | /@esbuild/linux-ppc64@0.21.5: 155 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 156 | engines: {node: '>=12'} 157 | cpu: [ppc64] 158 | os: [linux] 159 | requiresBuild: true 160 | dev: true 161 | optional: true 162 | 163 | /@esbuild/linux-riscv64@0.21.5: 164 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 165 | engines: {node: '>=12'} 166 | cpu: [riscv64] 167 | os: [linux] 168 | requiresBuild: true 169 | dev: true 170 | optional: true 171 | 172 | /@esbuild/linux-s390x@0.21.5: 173 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 174 | engines: {node: '>=12'} 175 | cpu: [s390x] 176 | os: [linux] 177 | requiresBuild: true 178 | dev: true 179 | optional: true 180 | 181 | /@esbuild/linux-x64@0.21.5: 182 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 183 | engines: {node: '>=12'} 184 | cpu: [x64] 185 | os: [linux] 186 | requiresBuild: true 187 | dev: true 188 | optional: true 189 | 190 | /@esbuild/netbsd-x64@0.21.5: 191 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 192 | engines: {node: '>=12'} 193 | cpu: [x64] 194 | os: [netbsd] 195 | requiresBuild: true 196 | dev: true 197 | optional: true 198 | 199 | /@esbuild/openbsd-x64@0.21.5: 200 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 201 | engines: {node: '>=12'} 202 | cpu: [x64] 203 | os: [openbsd] 204 | requiresBuild: true 205 | dev: true 206 | optional: true 207 | 208 | /@esbuild/sunos-x64@0.21.5: 209 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 210 | engines: {node: '>=12'} 211 | cpu: [x64] 212 | os: [sunos] 213 | requiresBuild: true 214 | dev: true 215 | optional: true 216 | 217 | /@esbuild/win32-arm64@0.21.5: 218 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 219 | engines: {node: '>=12'} 220 | cpu: [arm64] 221 | os: [win32] 222 | requiresBuild: true 223 | dev: true 224 | optional: true 225 | 226 | /@esbuild/win32-ia32@0.21.5: 227 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 228 | engines: {node: '>=12'} 229 | cpu: [ia32] 230 | os: [win32] 231 | requiresBuild: true 232 | dev: true 233 | optional: true 234 | 235 | /@esbuild/win32-x64@0.21.5: 236 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 237 | engines: {node: '>=12'} 238 | cpu: [x64] 239 | os: [win32] 240 | requiresBuild: true 241 | dev: true 242 | optional: true 243 | 244 | /@jest/schemas@29.6.3: 245 | resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} 246 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 247 | dependencies: 248 | '@sinclair/typebox': 0.27.8 249 | dev: true 250 | 251 | /@jridgewell/sourcemap-codec@1.5.0: 252 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 253 | dev: true 254 | 255 | /@jsonjoy.com/base64@1.1.2(tslib@2.6.3): 256 | resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} 257 | engines: {node: '>=10.0'} 258 | peerDependencies: 259 | tslib: '2' 260 | dependencies: 261 | tslib: 2.6.3 262 | dev: false 263 | 264 | /@jsonjoy.com/json-pack@1.1.0(tslib@2.6.3): 265 | resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==} 266 | engines: {node: '>=10.0'} 267 | peerDependencies: 268 | tslib: '2' 269 | dependencies: 270 | '@jsonjoy.com/base64': 1.1.2(tslib@2.6.3) 271 | '@jsonjoy.com/util': 1.3.0(tslib@2.6.3) 272 | hyperdyperid: 1.2.0 273 | thingies: 1.21.0(tslib@2.6.3) 274 | tslib: 2.6.3 275 | dev: false 276 | 277 | /@jsonjoy.com/util@1.3.0(tslib@2.6.3): 278 | resolution: {integrity: sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==} 279 | engines: {node: '>=10.0'} 280 | peerDependencies: 281 | tslib: '2' 282 | dependencies: 283 | tslib: 2.6.3 284 | dev: false 285 | 286 | /@ljharb/through@2.3.13: 287 | resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} 288 | engines: {node: '>= 0.4'} 289 | dependencies: 290 | call-bind: 1.0.7 291 | dev: false 292 | 293 | /@rollup/rollup-android-arm-eabi@4.20.0: 294 | resolution: {integrity: sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==} 295 | cpu: [arm] 296 | os: [android] 297 | requiresBuild: true 298 | dev: true 299 | optional: true 300 | 301 | /@rollup/rollup-android-arm64@4.20.0: 302 | resolution: {integrity: sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==} 303 | cpu: [arm64] 304 | os: [android] 305 | requiresBuild: true 306 | dev: true 307 | optional: true 308 | 309 | /@rollup/rollup-darwin-arm64@4.20.0: 310 | resolution: {integrity: sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==} 311 | cpu: [arm64] 312 | os: [darwin] 313 | requiresBuild: true 314 | dev: true 315 | optional: true 316 | 317 | /@rollup/rollup-darwin-x64@4.20.0: 318 | resolution: {integrity: sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==} 319 | cpu: [x64] 320 | os: [darwin] 321 | requiresBuild: true 322 | dev: true 323 | optional: true 324 | 325 | /@rollup/rollup-linux-arm-gnueabihf@4.20.0: 326 | resolution: {integrity: sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==} 327 | cpu: [arm] 328 | os: [linux] 329 | requiresBuild: true 330 | dev: true 331 | optional: true 332 | 333 | /@rollup/rollup-linux-arm-musleabihf@4.20.0: 334 | resolution: {integrity: sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==} 335 | cpu: [arm] 336 | os: [linux] 337 | requiresBuild: true 338 | dev: true 339 | optional: true 340 | 341 | /@rollup/rollup-linux-arm64-gnu@4.20.0: 342 | resolution: {integrity: sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==} 343 | cpu: [arm64] 344 | os: [linux] 345 | requiresBuild: true 346 | dev: true 347 | optional: true 348 | 349 | /@rollup/rollup-linux-arm64-musl@4.20.0: 350 | resolution: {integrity: sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==} 351 | cpu: [arm64] 352 | os: [linux] 353 | requiresBuild: true 354 | dev: true 355 | optional: true 356 | 357 | /@rollup/rollup-linux-powerpc64le-gnu@4.20.0: 358 | resolution: {integrity: sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==} 359 | cpu: [ppc64] 360 | os: [linux] 361 | requiresBuild: true 362 | dev: true 363 | optional: true 364 | 365 | /@rollup/rollup-linux-riscv64-gnu@4.20.0: 366 | resolution: {integrity: sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==} 367 | cpu: [riscv64] 368 | os: [linux] 369 | requiresBuild: true 370 | dev: true 371 | optional: true 372 | 373 | /@rollup/rollup-linux-s390x-gnu@4.20.0: 374 | resolution: {integrity: sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==} 375 | cpu: [s390x] 376 | os: [linux] 377 | requiresBuild: true 378 | dev: true 379 | optional: true 380 | 381 | /@rollup/rollup-linux-x64-gnu@4.20.0: 382 | resolution: {integrity: sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==} 383 | cpu: [x64] 384 | os: [linux] 385 | requiresBuild: true 386 | dev: true 387 | optional: true 388 | 389 | /@rollup/rollup-linux-x64-musl@4.20.0: 390 | resolution: {integrity: sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==} 391 | cpu: [x64] 392 | os: [linux] 393 | requiresBuild: true 394 | dev: true 395 | optional: true 396 | 397 | /@rollup/rollup-win32-arm64-msvc@4.20.0: 398 | resolution: {integrity: sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==} 399 | cpu: [arm64] 400 | os: [win32] 401 | requiresBuild: true 402 | dev: true 403 | optional: true 404 | 405 | /@rollup/rollup-win32-ia32-msvc@4.20.0: 406 | resolution: {integrity: sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==} 407 | cpu: [ia32] 408 | os: [win32] 409 | requiresBuild: true 410 | dev: true 411 | optional: true 412 | 413 | /@rollup/rollup-win32-x64-msvc@4.20.0: 414 | resolution: {integrity: sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==} 415 | cpu: [x64] 416 | os: [win32] 417 | requiresBuild: true 418 | dev: true 419 | optional: true 420 | 421 | /@sinclair/typebox@0.27.8: 422 | resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} 423 | dev: true 424 | 425 | /@types/estree@1.0.5: 426 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} 427 | dev: true 428 | 429 | /@types/inquirer@9.0.7: 430 | resolution: {integrity: sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==} 431 | dependencies: 432 | '@types/through': 0.0.33 433 | rxjs: 7.8.1 434 | dev: true 435 | 436 | /@types/node@20.11.25: 437 | resolution: {integrity: sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==} 438 | dependencies: 439 | undici-types: 5.26.5 440 | dev: true 441 | 442 | /@types/through@0.0.33: 443 | resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} 444 | dependencies: 445 | '@types/node': 20.11.25 446 | dev: true 447 | 448 | /@vitest/expect@1.6.0: 449 | resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} 450 | dependencies: 451 | '@vitest/spy': 1.6.0 452 | '@vitest/utils': 1.6.0 453 | chai: 4.5.0 454 | dev: true 455 | 456 | /@vitest/runner@1.6.0: 457 | resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} 458 | dependencies: 459 | '@vitest/utils': 1.6.0 460 | p-limit: 5.0.0 461 | pathe: 1.1.2 462 | dev: true 463 | 464 | /@vitest/snapshot@1.6.0: 465 | resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} 466 | dependencies: 467 | magic-string: 0.30.11 468 | pathe: 1.1.2 469 | pretty-format: 29.7.0 470 | dev: true 471 | 472 | /@vitest/spy@1.6.0: 473 | resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} 474 | dependencies: 475 | tinyspy: 2.2.1 476 | dev: true 477 | 478 | /@vitest/utils@1.6.0: 479 | resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} 480 | dependencies: 481 | diff-sequences: 29.6.3 482 | estree-walker: 3.0.3 483 | loupe: 2.3.7 484 | pretty-format: 29.7.0 485 | dev: true 486 | 487 | /acorn-walk@8.3.3: 488 | resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} 489 | engines: {node: '>=0.4.0'} 490 | dependencies: 491 | acorn: 8.12.1 492 | dev: true 493 | 494 | /acorn@8.12.1: 495 | resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} 496 | engines: {node: '>=0.4.0'} 497 | hasBin: true 498 | dev: true 499 | 500 | /ansi-escapes@4.3.2: 501 | resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} 502 | engines: {node: '>=8'} 503 | dependencies: 504 | type-fest: 0.21.3 505 | dev: false 506 | 507 | /ansi-regex@5.0.1: 508 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 509 | engines: {node: '>=8'} 510 | dev: false 511 | 512 | /ansi-styles@4.3.0: 513 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 514 | engines: {node: '>=8'} 515 | dependencies: 516 | color-convert: 2.0.1 517 | dev: false 518 | 519 | /ansi-styles@5.2.0: 520 | resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} 521 | engines: {node: '>=10'} 522 | dev: true 523 | 524 | /assertion-error@1.1.0: 525 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 526 | dev: true 527 | 528 | /base64-js@1.5.1: 529 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 530 | dev: false 531 | 532 | /bl@4.1.0: 533 | resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 534 | dependencies: 535 | buffer: 5.7.1 536 | inherits: 2.0.4 537 | readable-stream: 3.6.2 538 | dev: false 539 | 540 | /buffer@5.7.1: 541 | resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 542 | dependencies: 543 | base64-js: 1.5.1 544 | ieee754: 1.2.1 545 | dev: false 546 | 547 | /cac@6.7.14: 548 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 549 | engines: {node: '>=8'} 550 | dev: true 551 | 552 | /call-bind@1.0.7: 553 | resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} 554 | engines: {node: '>= 0.4'} 555 | dependencies: 556 | es-define-property: 1.0.0 557 | es-errors: 1.3.0 558 | function-bind: 1.1.2 559 | get-intrinsic: 1.2.4 560 | set-function-length: 1.2.2 561 | dev: false 562 | 563 | /chai@4.5.0: 564 | resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} 565 | engines: {node: '>=4'} 566 | dependencies: 567 | assertion-error: 1.1.0 568 | check-error: 1.0.3 569 | deep-eql: 4.1.4 570 | get-func-name: 2.0.2 571 | loupe: 2.3.7 572 | pathval: 1.1.1 573 | type-detect: 4.1.0 574 | dev: true 575 | 576 | /chalk@4.1.2: 577 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 578 | engines: {node: '>=10'} 579 | dependencies: 580 | ansi-styles: 4.3.0 581 | supports-color: 7.2.0 582 | dev: false 583 | 584 | /chalk@5.3.0: 585 | resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} 586 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 587 | dev: false 588 | 589 | /chardet@0.7.0: 590 | resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 591 | dev: false 592 | 593 | /check-error@1.0.3: 594 | resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} 595 | dependencies: 596 | get-func-name: 2.0.2 597 | dev: true 598 | 599 | /cli-cursor@3.1.0: 600 | resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} 601 | engines: {node: '>=8'} 602 | dependencies: 603 | restore-cursor: 3.1.0 604 | dev: false 605 | 606 | /cli-spinners@2.9.2: 607 | resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} 608 | engines: {node: '>=6'} 609 | dev: false 610 | 611 | /cli-width@4.1.0: 612 | resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} 613 | engines: {node: '>= 12'} 614 | dev: false 615 | 616 | /clone@1.0.4: 617 | resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} 618 | engines: {node: '>=0.8'} 619 | dev: false 620 | 621 | /color-convert@2.0.1: 622 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 623 | engines: {node: '>=7.0.0'} 624 | dependencies: 625 | color-name: 1.1.4 626 | dev: false 627 | 628 | /color-name@1.1.4: 629 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 630 | dev: false 631 | 632 | /commander@12.0.0: 633 | resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} 634 | engines: {node: '>=18'} 635 | dev: false 636 | 637 | /confbox@0.1.7: 638 | resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} 639 | dev: true 640 | 641 | /cross-spawn@7.0.3: 642 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 643 | engines: {node: '>= 8'} 644 | dependencies: 645 | path-key: 3.1.1 646 | shebang-command: 2.0.0 647 | which: 2.0.2 648 | dev: true 649 | 650 | /debug@4.3.6: 651 | resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} 652 | engines: {node: '>=6.0'} 653 | peerDependencies: 654 | supports-color: '*' 655 | peerDependenciesMeta: 656 | supports-color: 657 | optional: true 658 | dependencies: 659 | ms: 2.1.2 660 | dev: true 661 | 662 | /deep-eql@4.1.4: 663 | resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} 664 | engines: {node: '>=6'} 665 | dependencies: 666 | type-detect: 4.1.0 667 | dev: true 668 | 669 | /defaults@1.0.4: 670 | resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} 671 | dependencies: 672 | clone: 1.0.4 673 | dev: false 674 | 675 | /define-data-property@1.1.4: 676 | resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} 677 | engines: {node: '>= 0.4'} 678 | dependencies: 679 | es-define-property: 1.0.0 680 | es-errors: 1.3.0 681 | gopd: 1.0.1 682 | dev: false 683 | 684 | /diff-sequences@29.6.3: 685 | resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} 686 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 687 | dev: true 688 | 689 | /emoji-regex@8.0.0: 690 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 691 | dev: false 692 | 693 | /es-define-property@1.0.0: 694 | resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} 695 | engines: {node: '>= 0.4'} 696 | dependencies: 697 | get-intrinsic: 1.2.4 698 | dev: false 699 | 700 | /es-errors@1.3.0: 701 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 702 | engines: {node: '>= 0.4'} 703 | dev: false 704 | 705 | /esbuild@0.21.5: 706 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 707 | engines: {node: '>=12'} 708 | hasBin: true 709 | requiresBuild: true 710 | optionalDependencies: 711 | '@esbuild/aix-ppc64': 0.21.5 712 | '@esbuild/android-arm': 0.21.5 713 | '@esbuild/android-arm64': 0.21.5 714 | '@esbuild/android-x64': 0.21.5 715 | '@esbuild/darwin-arm64': 0.21.5 716 | '@esbuild/darwin-x64': 0.21.5 717 | '@esbuild/freebsd-arm64': 0.21.5 718 | '@esbuild/freebsd-x64': 0.21.5 719 | '@esbuild/linux-arm': 0.21.5 720 | '@esbuild/linux-arm64': 0.21.5 721 | '@esbuild/linux-ia32': 0.21.5 722 | '@esbuild/linux-loong64': 0.21.5 723 | '@esbuild/linux-mips64el': 0.21.5 724 | '@esbuild/linux-ppc64': 0.21.5 725 | '@esbuild/linux-riscv64': 0.21.5 726 | '@esbuild/linux-s390x': 0.21.5 727 | '@esbuild/linux-x64': 0.21.5 728 | '@esbuild/netbsd-x64': 0.21.5 729 | '@esbuild/openbsd-x64': 0.21.5 730 | '@esbuild/sunos-x64': 0.21.5 731 | '@esbuild/win32-arm64': 0.21.5 732 | '@esbuild/win32-ia32': 0.21.5 733 | '@esbuild/win32-x64': 0.21.5 734 | dev: true 735 | 736 | /escape-string-regexp@1.0.5: 737 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 738 | engines: {node: '>=0.8.0'} 739 | dev: false 740 | 741 | /estree-walker@3.0.3: 742 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 743 | dependencies: 744 | '@types/estree': 1.0.5 745 | dev: true 746 | 747 | /execa@8.0.1: 748 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} 749 | engines: {node: '>=16.17'} 750 | dependencies: 751 | cross-spawn: 7.0.3 752 | get-stream: 8.0.1 753 | human-signals: 5.0.0 754 | is-stream: 3.0.0 755 | merge-stream: 2.0.0 756 | npm-run-path: 5.3.0 757 | onetime: 6.0.0 758 | signal-exit: 4.1.0 759 | strip-final-newline: 3.0.0 760 | dev: true 761 | 762 | /external-editor@3.1.0: 763 | resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 764 | engines: {node: '>=4'} 765 | dependencies: 766 | chardet: 0.7.0 767 | iconv-lite: 0.4.24 768 | tmp: 0.0.33 769 | dev: false 770 | 771 | /figures@3.2.0: 772 | resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} 773 | engines: {node: '>=8'} 774 | dependencies: 775 | escape-string-regexp: 1.0.5 776 | dev: false 777 | 778 | /fs@0.0.1-security: 779 | resolution: {integrity: sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==} 780 | dev: false 781 | 782 | /fsevents@2.3.3: 783 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 784 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 785 | os: [darwin] 786 | requiresBuild: true 787 | dev: true 788 | optional: true 789 | 790 | /function-bind@1.1.2: 791 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 792 | dev: false 793 | 794 | /get-func-name@2.0.2: 795 | resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} 796 | dev: true 797 | 798 | /get-intrinsic@1.2.4: 799 | resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} 800 | engines: {node: '>= 0.4'} 801 | dependencies: 802 | es-errors: 1.3.0 803 | function-bind: 1.1.2 804 | has-proto: 1.0.3 805 | has-symbols: 1.0.3 806 | hasown: 2.0.2 807 | dev: false 808 | 809 | /get-stream@8.0.1: 810 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} 811 | engines: {node: '>=16'} 812 | dev: true 813 | 814 | /gopd@1.0.1: 815 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 816 | dependencies: 817 | get-intrinsic: 1.2.4 818 | dev: false 819 | 820 | /has-flag@4.0.0: 821 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 822 | engines: {node: '>=8'} 823 | dev: false 824 | 825 | /has-property-descriptors@1.0.2: 826 | resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 827 | dependencies: 828 | es-define-property: 1.0.0 829 | dev: false 830 | 831 | /has-proto@1.0.3: 832 | resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} 833 | engines: {node: '>= 0.4'} 834 | dev: false 835 | 836 | /has-symbols@1.0.3: 837 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 838 | engines: {node: '>= 0.4'} 839 | dev: false 840 | 841 | /hasown@2.0.2: 842 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 843 | engines: {node: '>= 0.4'} 844 | dependencies: 845 | function-bind: 1.1.2 846 | dev: false 847 | 848 | /human-signals@5.0.0: 849 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 850 | engines: {node: '>=16.17.0'} 851 | dev: true 852 | 853 | /hyperdyperid@1.2.0: 854 | resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} 855 | engines: {node: '>=10.18'} 856 | dev: false 857 | 858 | /iconv-lite@0.4.24: 859 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 860 | engines: {node: '>=0.10.0'} 861 | dependencies: 862 | safer-buffer: 2.1.2 863 | dev: false 864 | 865 | /ieee754@1.2.1: 866 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 867 | dev: false 868 | 869 | /inherits@2.0.4: 870 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 871 | dev: false 872 | 873 | /inquirer@9.2.15: 874 | resolution: {integrity: sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==} 875 | engines: {node: '>=18'} 876 | dependencies: 877 | '@ljharb/through': 2.3.13 878 | ansi-escapes: 4.3.2 879 | chalk: 5.3.0 880 | cli-cursor: 3.1.0 881 | cli-width: 4.1.0 882 | external-editor: 3.1.0 883 | figures: 3.2.0 884 | lodash: 4.17.21 885 | mute-stream: 1.0.0 886 | ora: 5.4.1 887 | run-async: 3.0.0 888 | rxjs: 7.8.1 889 | string-width: 4.2.3 890 | strip-ansi: 6.0.1 891 | wrap-ansi: 6.2.0 892 | dev: false 893 | 894 | /is-fullwidth-code-point@3.0.0: 895 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 896 | engines: {node: '>=8'} 897 | dev: false 898 | 899 | /is-interactive@1.0.0: 900 | resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} 901 | engines: {node: '>=8'} 902 | dev: false 903 | 904 | /is-stream@3.0.0: 905 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} 906 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 907 | dev: true 908 | 909 | /is-unicode-supported@0.1.0: 910 | resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} 911 | engines: {node: '>=10'} 912 | dev: false 913 | 914 | /isexe@2.0.0: 915 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 916 | dev: true 917 | 918 | /js-tokens@9.0.0: 919 | resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} 920 | dev: true 921 | 922 | /local-pkg@0.5.0: 923 | resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} 924 | engines: {node: '>=14'} 925 | dependencies: 926 | mlly: 1.7.1 927 | pkg-types: 1.1.3 928 | dev: true 929 | 930 | /lodash@4.17.21: 931 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 932 | dev: false 933 | 934 | /log-symbols@4.1.0: 935 | resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} 936 | engines: {node: '>=10'} 937 | dependencies: 938 | chalk: 4.1.2 939 | is-unicode-supported: 0.1.0 940 | dev: false 941 | 942 | /loupe@2.3.7: 943 | resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} 944 | dependencies: 945 | get-func-name: 2.0.2 946 | dev: true 947 | 948 | /magic-string@0.30.11: 949 | resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} 950 | dependencies: 951 | '@jridgewell/sourcemap-codec': 1.5.0 952 | dev: true 953 | 954 | /memfs@4.11.1: 955 | resolution: {integrity: sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==} 956 | engines: {node: '>= 4.0.0'} 957 | dependencies: 958 | '@jsonjoy.com/json-pack': 1.1.0(tslib@2.6.3) 959 | '@jsonjoy.com/util': 1.3.0(tslib@2.6.3) 960 | tree-dump: 1.0.2(tslib@2.6.3) 961 | tslib: 2.6.3 962 | dev: false 963 | 964 | /merge-stream@2.0.0: 965 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 966 | dev: true 967 | 968 | /mimic-fn@2.1.0: 969 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 970 | engines: {node: '>=6'} 971 | dev: false 972 | 973 | /mimic-fn@4.0.0: 974 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} 975 | engines: {node: '>=12'} 976 | dev: true 977 | 978 | /mlly@1.7.1: 979 | resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} 980 | dependencies: 981 | acorn: 8.12.1 982 | pathe: 1.1.2 983 | pkg-types: 1.1.3 984 | ufo: 1.5.4 985 | dev: true 986 | 987 | /ms@2.1.2: 988 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 989 | dev: true 990 | 991 | /mute-stream@1.0.0: 992 | resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} 993 | engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 994 | dev: false 995 | 996 | /nanoid@3.3.7: 997 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 998 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 999 | hasBin: true 1000 | dev: true 1001 | 1002 | /npm-run-path@5.3.0: 1003 | resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} 1004 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1005 | dependencies: 1006 | path-key: 4.0.0 1007 | dev: true 1008 | 1009 | /onetime@5.1.2: 1010 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 1011 | engines: {node: '>=6'} 1012 | dependencies: 1013 | mimic-fn: 2.1.0 1014 | dev: false 1015 | 1016 | /onetime@6.0.0: 1017 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} 1018 | engines: {node: '>=12'} 1019 | dependencies: 1020 | mimic-fn: 4.0.0 1021 | dev: true 1022 | 1023 | /ora@5.4.1: 1024 | resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} 1025 | engines: {node: '>=10'} 1026 | dependencies: 1027 | bl: 4.1.0 1028 | chalk: 4.1.2 1029 | cli-cursor: 3.1.0 1030 | cli-spinners: 2.9.2 1031 | is-interactive: 1.0.0 1032 | is-unicode-supported: 0.1.0 1033 | log-symbols: 4.1.0 1034 | strip-ansi: 6.0.1 1035 | wcwidth: 1.0.1 1036 | dev: false 1037 | 1038 | /os-tmpdir@1.0.2: 1039 | resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} 1040 | engines: {node: '>=0.10.0'} 1041 | dev: false 1042 | 1043 | /p-limit@5.0.0: 1044 | resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} 1045 | engines: {node: '>=18'} 1046 | dependencies: 1047 | yocto-queue: 1.1.1 1048 | dev: true 1049 | 1050 | /path-key@3.1.1: 1051 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1052 | engines: {node: '>=8'} 1053 | dev: true 1054 | 1055 | /path-key@4.0.0: 1056 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} 1057 | engines: {node: '>=12'} 1058 | dev: true 1059 | 1060 | /pathe@1.1.2: 1061 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} 1062 | dev: true 1063 | 1064 | /pathval@1.1.1: 1065 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 1066 | dev: true 1067 | 1068 | /picocolors@1.0.1: 1069 | resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} 1070 | dev: true 1071 | 1072 | /pkg-types@1.1.3: 1073 | resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} 1074 | dependencies: 1075 | confbox: 0.1.7 1076 | mlly: 1.7.1 1077 | pathe: 1.1.2 1078 | dev: true 1079 | 1080 | /postcss@8.4.41: 1081 | resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} 1082 | engines: {node: ^10 || ^12 || >=14} 1083 | dependencies: 1084 | nanoid: 3.3.7 1085 | picocolors: 1.0.1 1086 | source-map-js: 1.2.0 1087 | dev: true 1088 | 1089 | /pretty-format@29.7.0: 1090 | resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} 1091 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 1092 | dependencies: 1093 | '@jest/schemas': 29.6.3 1094 | ansi-styles: 5.2.0 1095 | react-is: 18.3.1 1096 | dev: true 1097 | 1098 | /react-is@18.3.1: 1099 | resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} 1100 | dev: true 1101 | 1102 | /readable-stream@3.6.2: 1103 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 1104 | engines: {node: '>= 6'} 1105 | dependencies: 1106 | inherits: 2.0.4 1107 | string_decoder: 1.3.0 1108 | util-deprecate: 1.0.2 1109 | dev: false 1110 | 1111 | /restore-cursor@3.1.0: 1112 | resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} 1113 | engines: {node: '>=8'} 1114 | dependencies: 1115 | onetime: 5.1.2 1116 | signal-exit: 3.0.7 1117 | dev: false 1118 | 1119 | /rollup@4.20.0: 1120 | resolution: {integrity: sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==} 1121 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1122 | hasBin: true 1123 | dependencies: 1124 | '@types/estree': 1.0.5 1125 | optionalDependencies: 1126 | '@rollup/rollup-android-arm-eabi': 4.20.0 1127 | '@rollup/rollup-android-arm64': 4.20.0 1128 | '@rollup/rollup-darwin-arm64': 4.20.0 1129 | '@rollup/rollup-darwin-x64': 4.20.0 1130 | '@rollup/rollup-linux-arm-gnueabihf': 4.20.0 1131 | '@rollup/rollup-linux-arm-musleabihf': 4.20.0 1132 | '@rollup/rollup-linux-arm64-gnu': 4.20.0 1133 | '@rollup/rollup-linux-arm64-musl': 4.20.0 1134 | '@rollup/rollup-linux-powerpc64le-gnu': 4.20.0 1135 | '@rollup/rollup-linux-riscv64-gnu': 4.20.0 1136 | '@rollup/rollup-linux-s390x-gnu': 4.20.0 1137 | '@rollup/rollup-linux-x64-gnu': 4.20.0 1138 | '@rollup/rollup-linux-x64-musl': 4.20.0 1139 | '@rollup/rollup-win32-arm64-msvc': 4.20.0 1140 | '@rollup/rollup-win32-ia32-msvc': 4.20.0 1141 | '@rollup/rollup-win32-x64-msvc': 4.20.0 1142 | fsevents: 2.3.3 1143 | dev: true 1144 | 1145 | /run-async@3.0.0: 1146 | resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} 1147 | engines: {node: '>=0.12.0'} 1148 | dev: false 1149 | 1150 | /rxjs@7.8.1: 1151 | resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} 1152 | dependencies: 1153 | tslib: 2.6.3 1154 | 1155 | /safe-buffer@5.2.1: 1156 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1157 | dev: false 1158 | 1159 | /safer-buffer@2.1.2: 1160 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1161 | dev: false 1162 | 1163 | /set-function-length@1.2.2: 1164 | resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} 1165 | engines: {node: '>= 0.4'} 1166 | dependencies: 1167 | define-data-property: 1.1.4 1168 | es-errors: 1.3.0 1169 | function-bind: 1.1.2 1170 | get-intrinsic: 1.2.4 1171 | gopd: 1.0.1 1172 | has-property-descriptors: 1.0.2 1173 | dev: false 1174 | 1175 | /shebang-command@2.0.0: 1176 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1177 | engines: {node: '>=8'} 1178 | dependencies: 1179 | shebang-regex: 3.0.0 1180 | dev: true 1181 | 1182 | /shebang-regex@3.0.0: 1183 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1184 | engines: {node: '>=8'} 1185 | dev: true 1186 | 1187 | /siginfo@2.0.0: 1188 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1189 | dev: true 1190 | 1191 | /signal-exit@3.0.7: 1192 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 1193 | dev: false 1194 | 1195 | /signal-exit@4.1.0: 1196 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1197 | engines: {node: '>=14'} 1198 | dev: true 1199 | 1200 | /source-map-js@1.2.0: 1201 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} 1202 | engines: {node: '>=0.10.0'} 1203 | dev: true 1204 | 1205 | /stackback@0.0.2: 1206 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1207 | dev: true 1208 | 1209 | /std-env@3.7.0: 1210 | resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} 1211 | dev: true 1212 | 1213 | /string-width@4.2.3: 1214 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1215 | engines: {node: '>=8'} 1216 | dependencies: 1217 | emoji-regex: 8.0.0 1218 | is-fullwidth-code-point: 3.0.0 1219 | strip-ansi: 6.0.1 1220 | dev: false 1221 | 1222 | /string_decoder@1.3.0: 1223 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 1224 | dependencies: 1225 | safe-buffer: 5.2.1 1226 | dev: false 1227 | 1228 | /strip-ansi@6.0.1: 1229 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1230 | engines: {node: '>=8'} 1231 | dependencies: 1232 | ansi-regex: 5.0.1 1233 | dev: false 1234 | 1235 | /strip-final-newline@3.0.0: 1236 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} 1237 | engines: {node: '>=12'} 1238 | dev: true 1239 | 1240 | /strip-literal@2.1.0: 1241 | resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} 1242 | dependencies: 1243 | js-tokens: 9.0.0 1244 | dev: true 1245 | 1246 | /supports-color@7.2.0: 1247 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1248 | engines: {node: '>=8'} 1249 | dependencies: 1250 | has-flag: 4.0.0 1251 | dev: false 1252 | 1253 | /thingies@1.21.0(tslib@2.6.3): 1254 | resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} 1255 | engines: {node: '>=10.18'} 1256 | peerDependencies: 1257 | tslib: ^2 1258 | dependencies: 1259 | tslib: 2.6.3 1260 | dev: false 1261 | 1262 | /tinybench@2.9.0: 1263 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1264 | dev: true 1265 | 1266 | /tinypool@0.8.4: 1267 | resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} 1268 | engines: {node: '>=14.0.0'} 1269 | dev: true 1270 | 1271 | /tinyspy@2.2.1: 1272 | resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} 1273 | engines: {node: '>=14.0.0'} 1274 | dev: true 1275 | 1276 | /tmp@0.0.33: 1277 | resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 1278 | engines: {node: '>=0.6.0'} 1279 | dependencies: 1280 | os-tmpdir: 1.0.2 1281 | dev: false 1282 | 1283 | /tree-dump@1.0.2(tslib@2.6.3): 1284 | resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} 1285 | engines: {node: '>=10.0'} 1286 | peerDependencies: 1287 | tslib: '2' 1288 | dependencies: 1289 | tslib: 2.6.3 1290 | dev: false 1291 | 1292 | /tslib@2.6.3: 1293 | resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} 1294 | 1295 | /type-detect@4.1.0: 1296 | resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} 1297 | engines: {node: '>=4'} 1298 | dev: true 1299 | 1300 | /type-fest@0.21.3: 1301 | resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} 1302 | engines: {node: '>=10'} 1303 | dev: false 1304 | 1305 | /typescript@5.4.2: 1306 | resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} 1307 | engines: {node: '>=14.17'} 1308 | hasBin: true 1309 | dev: true 1310 | 1311 | /ufo@1.5.4: 1312 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} 1313 | dev: true 1314 | 1315 | /undici-types@5.26.5: 1316 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 1317 | dev: true 1318 | 1319 | /util-deprecate@1.0.2: 1320 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1321 | dev: false 1322 | 1323 | /vite-node@1.6.0(@types/node@20.11.25): 1324 | resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} 1325 | engines: {node: ^18.0.0 || >=20.0.0} 1326 | hasBin: true 1327 | dependencies: 1328 | cac: 6.7.14 1329 | debug: 4.3.6 1330 | pathe: 1.1.2 1331 | picocolors: 1.0.1 1332 | vite: 5.4.0(@types/node@20.11.25) 1333 | transitivePeerDependencies: 1334 | - '@types/node' 1335 | - less 1336 | - lightningcss 1337 | - sass 1338 | - sass-embedded 1339 | - stylus 1340 | - sugarss 1341 | - supports-color 1342 | - terser 1343 | dev: true 1344 | 1345 | /vite@5.4.0(@types/node@20.11.25): 1346 | resolution: {integrity: sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==} 1347 | engines: {node: ^18.0.0 || >=20.0.0} 1348 | hasBin: true 1349 | peerDependencies: 1350 | '@types/node': ^18.0.0 || >=20.0.0 1351 | less: '*' 1352 | lightningcss: ^1.21.0 1353 | sass: '*' 1354 | sass-embedded: '*' 1355 | stylus: '*' 1356 | sugarss: '*' 1357 | terser: ^5.4.0 1358 | peerDependenciesMeta: 1359 | '@types/node': 1360 | optional: true 1361 | less: 1362 | optional: true 1363 | lightningcss: 1364 | optional: true 1365 | sass: 1366 | optional: true 1367 | sass-embedded: 1368 | optional: true 1369 | stylus: 1370 | optional: true 1371 | sugarss: 1372 | optional: true 1373 | terser: 1374 | optional: true 1375 | dependencies: 1376 | '@types/node': 20.11.25 1377 | esbuild: 0.21.5 1378 | postcss: 8.4.41 1379 | rollup: 4.20.0 1380 | optionalDependencies: 1381 | fsevents: 2.3.3 1382 | dev: true 1383 | 1384 | /vitest@1.6.0(@types/node@20.11.25): 1385 | resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} 1386 | engines: {node: ^18.0.0 || >=20.0.0} 1387 | hasBin: true 1388 | peerDependencies: 1389 | '@edge-runtime/vm': '*' 1390 | '@types/node': ^18.0.0 || >=20.0.0 1391 | '@vitest/browser': 1.6.0 1392 | '@vitest/ui': 1.6.0 1393 | happy-dom: '*' 1394 | jsdom: '*' 1395 | peerDependenciesMeta: 1396 | '@edge-runtime/vm': 1397 | optional: true 1398 | '@types/node': 1399 | optional: true 1400 | '@vitest/browser': 1401 | optional: true 1402 | '@vitest/ui': 1403 | optional: true 1404 | happy-dom: 1405 | optional: true 1406 | jsdom: 1407 | optional: true 1408 | dependencies: 1409 | '@types/node': 20.11.25 1410 | '@vitest/expect': 1.6.0 1411 | '@vitest/runner': 1.6.0 1412 | '@vitest/snapshot': 1.6.0 1413 | '@vitest/spy': 1.6.0 1414 | '@vitest/utils': 1.6.0 1415 | acorn-walk: 8.3.3 1416 | chai: 4.5.0 1417 | debug: 4.3.6 1418 | execa: 8.0.1 1419 | local-pkg: 0.5.0 1420 | magic-string: 0.30.11 1421 | pathe: 1.1.2 1422 | picocolors: 1.0.1 1423 | std-env: 3.7.0 1424 | strip-literal: 2.1.0 1425 | tinybench: 2.9.0 1426 | tinypool: 0.8.4 1427 | vite: 5.4.0(@types/node@20.11.25) 1428 | vite-node: 1.6.0(@types/node@20.11.25) 1429 | why-is-node-running: 2.3.0 1430 | transitivePeerDependencies: 1431 | - less 1432 | - lightningcss 1433 | - sass 1434 | - sass-embedded 1435 | - stylus 1436 | - sugarss 1437 | - supports-color 1438 | - terser 1439 | dev: true 1440 | 1441 | /wcwidth@1.0.1: 1442 | resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} 1443 | dependencies: 1444 | defaults: 1.0.4 1445 | dev: false 1446 | 1447 | /which@2.0.2: 1448 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1449 | engines: {node: '>= 8'} 1450 | hasBin: true 1451 | dependencies: 1452 | isexe: 2.0.0 1453 | dev: true 1454 | 1455 | /why-is-node-running@2.3.0: 1456 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1457 | engines: {node: '>=8'} 1458 | hasBin: true 1459 | dependencies: 1460 | siginfo: 2.0.0 1461 | stackback: 0.0.2 1462 | dev: true 1463 | 1464 | /wrap-ansi@6.2.0: 1465 | resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} 1466 | engines: {node: '>=8'} 1467 | dependencies: 1468 | ansi-styles: 4.3.0 1469 | string-width: 4.2.3 1470 | strip-ansi: 6.0.1 1471 | dev: false 1472 | 1473 | /yocto-queue@1.1.1: 1474 | resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} 1475 | engines: {node: '>=12.20'} 1476 | dev: true 1477 | -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export const FRAMEWORK_CHOICES = [ 2 | { 3 | name: "React (with Vite)", 4 | value: "react", 5 | }, 6 | { 7 | name: "Next.js", 8 | value: "nextjs", 9 | }, 10 | ] as const; 11 | export const BLOCKCHAIN_TOOLING_CHOICES = [ 12 | { 13 | name: "HardHat", 14 | value: "hardhat", 15 | }, 16 | { 17 | name: "Foundry", 18 | value: "foundry", 19 | }, 20 | { 21 | name: "None", 22 | value: "none", 23 | }, 24 | ] as const; 25 | 26 | export const PACAKGE_MANAGER_CHOICES = [ 27 | { 28 | name: "Yarn", 29 | value: "yarn", 30 | }, 31 | { 32 | name: "NPM", 33 | value: "npm", 34 | }, 35 | { 36 | name: "pnpm", 37 | value: "pnpm", 38 | }, 39 | ] as const; 40 | 41 | export const NPM_COMMAND = (projectName: string, path: string) => 42 | path 43 | ? `cd ${path} && npm init vite@latest . -- --template react-ts` 44 | : `npm init vite@latest ${projectName} -- --template react-ts`; 45 | 46 | export const YARN_COMMAND = (projectName: string, path: string) => 47 | path 48 | ? `cd ${path} && yarn create vite . --template react-ts` 49 | : `yarn create vite ${projectName} --template react-ts`; 50 | 51 | export const PNPM_COMMAND = (projectName: string, path: string) => 52 | path 53 | ? `cd ${path} && pnpm create vite . --template react-ts` 54 | : `pnpm create vite ${projectName} --template react-ts`; 55 | -------------------------------------------------------------------------------- /src/constants/templates.ts: -------------------------------------------------------------------------------- 1 | export const TEMPLATES = [ 2 | { 3 | name: "Next Web3 Starter", 4 | id: "next-web3-starter", 5 | repo_url: "https://github.com/Consensys/next-web3-starter.git", 6 | packageName: "@consensys/web3-starter", 7 | }, 8 | { 9 | name: "React Web3 Starter", 10 | id: "react-web3-starter", 11 | repo_url: "https://github.com/Consensys/react-web3-starter.git", 12 | packageName: "@consensys/react-web3-starter", 13 | }, 14 | { 15 | name: "React/Vite and foundry starter", 16 | id: "foundry-starter", 17 | repo_url: "https://github.com/cxalem/foundry-template", 18 | packageName: "@consensys/foundry-template", 19 | }, 20 | ] as const; 21 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { Command } from "commander"; 4 | import { createProject } from "./utils/index.js"; 5 | 6 | async function main() { 7 | const program = new Command() 8 | .name("create-web3-template") 9 | .description("Web3 starter template CLI tool.") 10 | .arguments("[project-name]") 11 | .action((args: string) => createProject(args)) 12 | .version("0.0.2"); 13 | program.parse(process.argv); 14 | } 15 | 16 | main().catch((error) => { 17 | console.error("An unexpected error occurred:", error); 18 | }); 19 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { exec } from "child_process"; 2 | import { promises as fs } from "fs"; 3 | import { 4 | BLOCKCHAIN_TOOLING_CHOICES, 5 | FRAMEWORK_CHOICES, 6 | PACAKGE_MANAGER_CHOICES, 7 | } from "../constants/index.js"; 8 | import { createReactApp } from "./vite.helpers.js"; 9 | import { createNextApp } from "./next.helpers.js"; 10 | import path from "path"; 11 | import util from "util"; 12 | import inquirer from "inquirer"; 13 | 14 | export const execAsync = util.promisify(exec); 15 | 16 | const promptForFramework = async (): Promise => { 17 | const frameworkChoice = FRAMEWORK_CHOICES.map((choice) => choice.name); 18 | const { framework }: { framework: string } = await inquirer.prompt([ 19 | { 20 | type: "list", 21 | name: "framework", 22 | message: "Please select the framework you want to use:", 23 | choices: frameworkChoice, 24 | }, 25 | ]); 26 | console.log(`Selected framework: ${framework}`); 27 | 28 | return framework; 29 | }; 30 | 31 | const promptForTooling = async (): Promise => { 32 | const toolingChoice = BLOCKCHAIN_TOOLING_CHOICES.map((choice) => choice.name); 33 | const { tooling }: { tooling: string } = await inquirer.prompt([ 34 | { 35 | type: "list", 36 | name: "tooling", 37 | message: "Would you like to use HardHat or Foundry?", 38 | choices: toolingChoice, 39 | }, 40 | ]); 41 | console.log(`Selected tooling: ${tooling}`); 42 | 43 | return tooling; 44 | }; 45 | 46 | const promptForPackageManager = async (): Promise => { 47 | const packageManagerChoice = PACAKGE_MANAGER_CHOICES.map( 48 | (choice) => choice.name 49 | ); 50 | const { packageManager }: { packageManager: string } = await inquirer.prompt([ 51 | { 52 | type: "list", 53 | name: "packageManager", 54 | message: "Please select the package manager you want to use:", 55 | choices: packageManagerChoice, 56 | }, 57 | ]); 58 | console.log(`Selected package manager: ${packageManager}`); 59 | 60 | return packageManager; 61 | }; 62 | 63 | const promptForProjectDetails = async (args: string): Promise => { 64 | if (!args) { 65 | const { projectName } = await inquirer.prompt([ 66 | { 67 | type: "input", 68 | name: "projectName", 69 | message: "Please specify a name for your project: ", 70 | validate: (input) => (input ? true : "Project name cannot be empty"), 71 | }, 72 | ]); 73 | console.log("Creating project with name:", projectName); 74 | return projectName; 75 | } 76 | return args; 77 | }; 78 | 79 | const promptForOptions = async (args: string) => { 80 | const projectName = await promptForProjectDetails(args); 81 | const framework = await promptForFramework(); 82 | const tooling = await promptForTooling(); 83 | const packageManager = await promptForPackageManager(); 84 | 85 | const options = { 86 | projectName: projectName, 87 | framework: FRAMEWORK_CHOICES.find((choice) => choice.name === framework) 88 | ?.value, 89 | blockchain_tooling: BLOCKCHAIN_TOOLING_CHOICES.find( 90 | (choice) => choice.name === tooling 91 | )?.value, 92 | packageManager: PACAKGE_MANAGER_CHOICES.find( 93 | (choice) => choice.name === packageManager 94 | )?.value!, 95 | }; 96 | 97 | return options; 98 | }; 99 | 100 | const initializeMonorepo = async (options: ProjectOptions) => { 101 | const { projectName, packageManager } = options; 102 | console.log("Initializing monorepo..."); 103 | 104 | if (packageManager === "pnpm") { 105 | await fs.writeFile( 106 | path.join(projectName, "pnpm-workspace.yaml"), 107 | `packages: 108 | - 'packages/*'` 109 | ); 110 | } 111 | 112 | await fs.writeFile(path.join(projectName, ".gitignore"), `node_modules`); 113 | await execAsync(`cd ${projectName} && npm init -y`); 114 | await execAsync(`cd ${projectName} && npm init -w ./packages/blockchain -y`); 115 | await execAsync(`cd ${projectName} && npm init -w ./packages/site -y`); 116 | 117 | await fs.rm(path.join(projectName, "packages", "blockchain", "package.json")); 118 | await fs.rm(path.join(projectName, "packages", "site", "package.json")); 119 | await fs.rm(path.join(projectName, "node_modules"), { recursive: true }); 120 | }; 121 | 122 | const createHardhatProject = async (options: ProjectOptions) => { 123 | const { projectName, framework } = options; 124 | await fs.mkdir(projectName); 125 | 126 | console.log("Creating a project with HardHat..."); 127 | 128 | await initializeMonorepo(options); 129 | await execAsync( 130 | `git clone https://github.com/cxalem/hardhat-template.git ${path.join( 131 | projectName, 132 | "packages", 133 | "blockchain" 134 | )}` 135 | ); 136 | 137 | if (framework === "nextjs") { 138 | await createNextApp(options, path.join(projectName, "packages", "site")); 139 | } else { 140 | await createReactApp(options, path.join(projectName, "packages", "site")); 141 | } 142 | }; 143 | 144 | const createFoundryProject = async (options: ProjectOptions) => { 145 | const { projectName, framework } = options; 146 | await fs.mkdir(projectName); 147 | 148 | console.log("Creating a project with Foundry..."); 149 | 150 | await initializeMonorepo(options); 151 | if (framework === "nextjs") { 152 | await createNextApp(options, path.join(projectName, "packages", "site")); 153 | } else { 154 | await createReactApp(options, path.join(projectName, "packages", "site")); 155 | } 156 | 157 | await execAsync(` 158 | cd ${projectName}/packages/blockchain && forge init . --no-commit 159 | `); 160 | }; 161 | 162 | export const pathOrProjectName = ( 163 | projectName: string, 164 | projectPath?: string 165 | ) => { 166 | return projectPath ? projectPath : projectName; 167 | }; 168 | 169 | export const updatePackageJsonDependencies = async ( 170 | dependencies: Record, 171 | projectPath: string 172 | ) => { 173 | const packageJsonPath = path.join(projectPath, "package.json"); 174 | const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8"); 175 | const packageJson = JSON.parse(packageJsonContent); 176 | 177 | packageJson.dependencies = { 178 | ...packageJson.dependencies, 179 | ...dependencies, 180 | }; 181 | 182 | const newPackageJsonContent = JSON.stringify(packageJson, null, 2); 183 | await fs.writeFile(packageJsonPath, newPackageJsonContent, "utf-8"); 184 | 185 | console.log("Dependencies added to package.json"); 186 | }; 187 | 188 | export const createWagmiConfigFile = async (projectPath: string) => { 189 | await fs.writeFile( 190 | path.join(projectPath, "wagmi.config.ts"), 191 | ` 192 | import { http, createConfig } from "wagmi"; 193 | import { lineaTestnet } from "wagmi/chains"; 194 | import { metaMask } from "wagmi/connectors"; 195 | 196 | export const config = createConfig({ 197 | chains: [lineaTestnet], 198 | connectors: [metaMask()], 199 | transports: { 200 | [lineaTestnet.id]: http(), 201 | }, 202 | }); 203 | ` 204 | ); 205 | }; 206 | 207 | export const usePackageManager = (packageManager: string) => { 208 | switch (packageManager) { 209 | case "npm": 210 | return "--use-npm"; 211 | case "yarn": 212 | return "--use-yarn"; 213 | case "pnpm": 214 | return "--use-pnpm"; 215 | default: 216 | return "--use-npm"; 217 | } 218 | }; 219 | 220 | export const createProject = async (args: string) => { 221 | const options = await promptForOptions(args); 222 | 223 | if (options.blockchain_tooling === "hardhat") { 224 | createHardhatProject(options); 225 | return; 226 | } 227 | 228 | if (options.blockchain_tooling === "foundry") { 229 | createFoundryProject(options); 230 | return; 231 | } 232 | 233 | switch (options.framework) { 234 | case "nextjs": 235 | await createNextApp(options); 236 | break; 237 | case "react": 238 | await createReactApp(options); 239 | break; 240 | default: 241 | break; 242 | } 243 | }; 244 | -------------------------------------------------------------------------------- /src/utils/next.helpers.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { promises as fs } from "fs"; 3 | import { 4 | createWagmiConfigFile, 5 | execAsync, 6 | pathOrProjectName, 7 | updatePackageJsonDependencies, 8 | usePackageManager, 9 | } from "./index.js"; 10 | 11 | export const createNextApp = async ( 12 | options: ProjectOptions, 13 | projectPath?: string 14 | ) => { 15 | console.log("Creating Next.js project..."); 16 | try { 17 | const { projectName, packageManager } = options; 18 | 19 | const command = `npx create-next-app ${pathOrProjectName( 20 | projectName, 21 | projectPath 22 | )} --ts --tailwind --eslint --app --src-dir --skip-install --import-alias "@/*" ${usePackageManager( 23 | packageManager 24 | )} --turbopack`; 25 | 26 | await execAsync(command); 27 | 28 | await updatePackageJsonDependencies( 29 | { 30 | "@consensys/connect-button": "^1.0.3", 31 | "@tanstack/react-query": "^5.51.23", 32 | viem: "2.x", 33 | wagmi: "^2.12.5", 34 | }, 35 | pathOrProjectName(projectName, projectPath) 36 | ); 37 | 38 | await updateLayoutFile(pathOrProjectName(projectName, projectPath)); 39 | await createProvider(pathOrProjectName(projectName, projectPath)); 40 | await createWagmiConfigFile( 41 | projectPath ? `${projectPath}/src` : `${projectName}/src` 42 | ); 43 | await updatePageFile(pathOrProjectName(projectName, projectPath)); 44 | 45 | console.log("Next.js project created successfully!"); 46 | } catch (error) { 47 | console.error("An unexpected error occurred:", error); 48 | } 49 | }; 50 | 51 | const updateLayoutFile = async (projectPath: string) => { 52 | const layoutFilePath = path.join(projectPath, "src", "app", "layout.tsx"); 53 | await fs.writeFile( 54 | layoutFilePath, 55 | ` 56 | "use client"; 57 | 58 | import { Inter } from "next/font/google"; 59 | import "./globals.css"; 60 | import Provider from "@/providers/WagmiProvider"; 61 | 62 | const inter = Inter({ subsets: ["latin"] }); 63 | 64 | export default function RootLayout({ 65 | children, 66 | }: Readonly<{ 67 | children: React.ReactNode; 68 | }>) { 69 | return ( 70 | 71 | 72 | {children} 73 | 74 | 75 | ); 76 | } 77 | 78 | ` 79 | ); 80 | }; 81 | 82 | const createProvider = async (projectPath: string) => { 83 | await fs.mkdir(path.join(projectPath, "src", "providers")); 84 | const providerFilePath = path.join( 85 | projectPath, 86 | "src", 87 | "providers", 88 | "WagmiProvider.tsx" 89 | ); 90 | await fs.writeFile( 91 | providerFilePath, 92 | ` 93 | "use client"; 94 | 95 | import { WagmiProvider } from "wagmi"; 96 | import { config } from "@/wagmi.config"; 97 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 98 | import { createPublicClient, http } from "viem"; 99 | import { linea } from "viem/chains"; 100 | 101 | export const client = createPublicClient({ 102 | chain: linea, 103 | transport: http(), 104 | }); 105 | 106 | interface WagmiProviderProps { 107 | children: React.ReactNode; 108 | } 109 | 110 | const Provider: React.FC = ({ children }) => { 111 | const queryClient = new QueryClient(); 112 | 113 | return ( 114 | 115 | {children} 116 | 117 | ); 118 | }; 119 | 120 | export default Provider; 121 | ` 122 | ); 123 | }; 124 | 125 | const updatePageFile = async (projectPath: string) => { 126 | const pageFilePath = path.join(projectPath, "src", "app", "page.tsx"); 127 | 128 | await fs.writeFile( 129 | pageFilePath, 130 | ` 131 | "use client"; 132 | 133 | import { ConnectButton } from "@consensys/connect-button"; 134 | import { client } from "@/providers/WagmiProvider"; 135 | import { Suspense, useEffect, useState } from "react"; 136 | import { useAccount } from "wagmi"; 137 | 138 | export default function Home() { 139 | const { isConnected, address } = useAccount(); 140 | const [blockNumber, setBlockNumber] = useState(null); 141 | 142 | useEffect(() => { 143 | client.getBlockNumber().then((block) => { 144 | setBlockNumber(block); 145 | }); 146 | }, []); 147 | 148 | return ( 149 |
150 | Loading...}> 151 |
152 | 162 | 163 |
164 | 165 |
166 | Web3 Starter template 167 | {isConnected && ( 168 | 169 | Connected to: {address} 170 | 171 | )} 172 | 173 |
174 | {!blockNumber ? ( 175 | "Loading block number..." 176 | ) : ( 177 |
Linea block number: {Number(blockNumber)}
178 | )} 179 |
180 |
181 |
182 |
183 | ); 184 | } 185 | ` 186 | ); 187 | }; 188 | -------------------------------------------------------------------------------- /src/utils/vite.helpers.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { promises as fs } from "fs"; 3 | import { NPM_COMMAND, PNPM_COMMAND, YARN_COMMAND } from "../constants/index.js"; 4 | import { 5 | createWagmiConfigFile, 6 | execAsync, 7 | updatePackageJsonDependencies, 8 | } from "./index.js"; 9 | 10 | export const createReactApp = async ( 11 | options: ProjectOptions, 12 | projectPath: string = "" 13 | ): Promise => { 14 | console.log("Creating React project..."); 15 | 16 | const { projectName, packageManager } = options; 17 | 18 | const commands: Record< 19 | string, 20 | (projectName: string, path: string) => string 21 | > = { 22 | npm: NPM_COMMAND, 23 | yarn: YARN_COMMAND, 24 | pnpm: PNPM_COMMAND, 25 | }; 26 | 27 | const command = commands[packageManager]; 28 | 29 | if (!command) { 30 | console.error(`Unsupported package manager: ${packageManager}`); 31 | return; 32 | } 33 | 34 | try { 35 | await execAsync(command(projectName, projectPath)); 36 | console.log("React project created successfully!"); 37 | await updatePackageJsonDependencies( 38 | { 39 | "@consensys/connect-button": "^1.0.3", 40 | "@tanstack/react-query": "^5.51.23", 41 | viem: "2.x", 42 | wagmi: "^2.12.5", 43 | postcss: "^8.4.41", 44 | tailwindcss: "^3.4.10", 45 | autoprefixer: "^10.4.20", 46 | }, 47 | projectPath ? projectPath : projectName 48 | ); 49 | await createWagmiConfigFile(projectPath ? projectPath : projectName); 50 | await updateMainFile(projectPath ? projectPath : projectName); 51 | await updateAppFile(projectPath ? projectPath : projectName); 52 | await createClientProvider(projectPath ? projectPath : projectName); 53 | await createTalwindConfig(projectPath ? projectPath : projectName); 54 | await updateIndexCss(projectPath ? projectPath : projectName); 55 | } catch (error) { 56 | console.error("An error occurred during project creation:", error); 57 | } 58 | }; 59 | 60 | const updateMainFile = async (projectPath: string) => { 61 | const mainFilePath = path.join(projectPath, "src", "main.tsx"); 62 | await fs.writeFile( 63 | mainFilePath, 64 | ` 65 | import React from "react"; 66 | import ReactDOM from "react-dom/client"; 67 | import App from "./App.tsx"; 68 | import "./index.css"; 69 | import { WagmiProvider } from "wagmi"; 70 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 71 | import { config } from "../wagmi.config.ts"; 72 | 73 | const queryClient = new QueryClient(); 74 | 75 | ReactDOM.createRoot(document.getElementById("root")!).render( 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ); 84 | ` 85 | ); 86 | }; 87 | 88 | const updateAppFile = async (projectPath: string) => { 89 | const appFilePath = path.join(projectPath, "src", "App.tsx"); 90 | await fs.writeFile( 91 | appFilePath, 92 | ` 93 | import { client } from "./providers/client"; 94 | import { useEffect, useState } from "react"; 95 | import { useAccount } from "wagmi"; 96 | import { ConnectButton } from "@consensys/connect-button"; 97 | 98 | export default function Home() { 99 | const { isConnected, address } = useAccount(); 100 | const [blockNumber, setBlockNumber] = useState(null); 101 | 102 | useEffect(() => { 103 | client.getBlockNumber().then((block) => { 104 | setBlockNumber(block); 105 | }); 106 | }, []); 107 | 108 | return ( 109 |
110 |
111 | 121 | 122 |
123 | 124 |
125 | Web3 Starter template 126 | {isConnected && ( 127 | 128 | Connected to: {address} 129 | 130 | )} 131 | 132 |
133 | {!blockNumber ? ( 134 | "Loading block number..." 135 | ) : ( 136 |
Linea block number: {Number(blockNumber)}
137 | )} 138 |
139 |
140 |
141 | ); 142 | } 143 | ` 144 | ); 145 | }; 146 | 147 | const createClientProvider = async (projectPath: string) => { 148 | await fs.mkdir(path.join(projectPath, "src", "providers")); 149 | const clientFilePath = path.join( 150 | projectPath, 151 | "src", 152 | "providers", 153 | "client.ts" 154 | ); 155 | await fs.writeFile( 156 | clientFilePath, 157 | ` 158 | import { createPublicClient, http } from "viem"; 159 | import { linea } from "viem/chains"; 160 | 161 | export const client = createPublicClient({ 162 | chain: linea, 163 | transport: http(), 164 | }); 165 | ` 166 | ); 167 | }; 168 | 169 | const createTalwindConfig = async (projectPath: string) => { 170 | const tailwindConfigPath = path.join(projectPath, "tailwind.config.js"); 171 | await execAsync(`cd ${projectPath} && npx tailwindcss init -p`); 172 | await fs.writeFile( 173 | tailwindConfigPath, 174 | ` 175 | /** @type {import('tailwindcss').Config} */ 176 | export default { 177 | content: [ 178 | "./index.html", 179 | "./src/**/*.{js,ts,jsx,tsx}", 180 | ], 181 | theme: { 182 | extend: {}, 183 | }, 184 | plugins: [], 185 | } 186 | ` 187 | ); 188 | }; 189 | 190 | const updateIndexCss = async (projectPath: string) => { 191 | const indexCssPath = path.join(projectPath, "src", "index.css"); 192 | await fs.writeFile( 193 | indexCssPath, 194 | ` 195 | @tailwind base; 196 | @tailwind components; 197 | @tailwind utilities; 198 | ` 199 | ); 200 | }; 201 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Node LTS", 4 | "_version": "20.1.0", 5 | "compilerOptions": { 6 | "lib": ["dom", "dom.iterable", "esnext"], 7 | "module": "node16", 8 | "target": "es5", 9 | "strict": true, 10 | "outDir": "dist", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true, 13 | "skipLibCheck": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "moduleResolution": "node16" 16 | }, 17 | "include": ["**/*.ts", "**/*.tsx", "types.d.ts", "src"] 18 | } 19 | -------------------------------------------------------------------------------- /types.d.ts: -------------------------------------------------------------------------------- 1 | type Template = { 2 | id: string; 3 | name: string; 4 | repo_url: string; 5 | packageName: string; 6 | }; 7 | 8 | type TemplateSelection = { 9 | title: string; 10 | }; 11 | 12 | type ProjectOptions = { 13 | projectName: string; 14 | framework: "react" | "nextjs" | undefined; 15 | blockchain_tooling: "hardhat" | "foundry" | "none" | undefined; 16 | packageManager: "yarn" | "npm" | "pnpm"; 17 | }; 18 | --------------------------------------------------------------------------------