chore: added norns.json setup
80583bee
2 file(s) · +146 −13
| 40 | 40 | ||
| 41 | 41 | **CLI** |
|
| 42 | 42 | ||
| 43 | - | - [ ] Implement `components.json` initialization |
|
| 43 | + | - [x] Implement `norns.json` initialization |
|
| 44 | 44 | - [ ] Improve styles and UX of commands and help menus |
|
| 45 | 45 | ||
| 46 | 46 | **Components** |
|
| 47 | 47 | ||
| 48 | 48 | - [x] Connect Wallet |
|
| 49 | - | - [ ] Interact with Contract |
|
| 49 | + | - [x] Contract Call |
|
| 50 | 50 | - [ ] TX Toasts? |
|
| 51 | 51 | - [ ] Contract State and Functions |
|
| 52 | 52 |
| 5 | 5 | import { mkdir } from "node:fs/promises"; |
|
| 6 | 6 | import { existsSync } from "node:fs"; |
|
| 7 | 7 | import { join } from "node:path"; |
|
| 8 | + | import { createInterface } from "node:readline/promises"; |
|
| 8 | 9 | ||
| 9 | 10 | import { fileURLToPath } from "url"; |
|
| 10 | 11 | import { dirname } from "path"; |
|
| 11 | 12 | ||
| 12 | 13 | const __filename = fileURLToPath(import.meta.url); |
|
| 14 | + | ||
| 13 | 15 | const __dirname = dirname(__filename); |
|
| 14 | 16 | const COMPONENTS_DIR = join(__dirname, "components"); |
|
| 17 | + | const CONFIG_FILE = "norns.json"; |
|
| 18 | + | ||
| 19 | + | interface NornsConfig { |
|
| 20 | + | components: string; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | const DEFAULT_CONFIG: NornsConfig = { |
|
| 24 | + | components: "components", |
|
| 25 | + | }; |
|
| 26 | + | ||
| 27 | + | async function loadConfig(): Promise<NornsConfig | null> { |
|
| 28 | + | try { |
|
| 29 | + | if (!existsSync(CONFIG_FILE)) { |
|
| 30 | + | return null; |
|
| 31 | + | } |
|
| 32 | + | const configContent = await readFile(CONFIG_FILE, "utf8"); |
|
| 33 | + | return JSON.parse(configContent); |
|
| 34 | + | } catch (error) { |
|
| 35 | + | console.error(`❌ Failed to load ${CONFIG_FILE}:`, error); |
|
| 36 | + | return null; |
|
| 37 | + | } |
|
| 38 | + | } |
|
| 39 | + | ||
| 40 | + | async function saveConfig(config: NornsConfig): Promise<void> { |
|
| 41 | + | try { |
|
| 42 | + | await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), "utf8"); |
|
| 43 | + | } catch (error) { |
|
| 44 | + | console.error(`❌ Failed to save ${CONFIG_FILE}:`, error); |
|
| 45 | + | throw error; |
|
| 46 | + | } |
|
| 47 | + | } |
|
| 48 | + | ||
| 49 | + | async function promptUser( |
|
| 50 | + | question: string, |
|
| 51 | + | defaultValue?: string, |
|
| 52 | + | ): Promise<string> { |
|
| 53 | + | const rl = createInterface({ |
|
| 54 | + | input: process.stdin, |
|
| 55 | + | output: process.stdout, |
|
| 56 | + | }); |
|
| 57 | + | ||
| 58 | + | try { |
|
| 59 | + | const prompt = defaultValue |
|
| 60 | + | ? `${question} (${defaultValue}): ` |
|
| 61 | + | : `${question}: `; |
|
| 62 | + | ||
| 63 | + | const answer = await rl.question(prompt); |
|
| 64 | + | return answer.trim() || defaultValue || ""; |
|
| 65 | + | } finally { |
|
| 66 | + | rl.close(); |
|
| 67 | + | } |
|
| 68 | + | } |
|
| 15 | 69 | ||
| 16 | 70 | async function init() { |
|
| 17 | 71 | console.log("🧙 Initializing norns project..."); |
|
| 18 | 72 | ||
| 19 | - | const componentsDir = "components"; |
|
| 73 | + | // Check if components.json already exists |
|
| 74 | + | if (existsSync(CONFIG_FILE)) { |
|
| 75 | + | console.log(`📁 ${CONFIG_FILE} already exists`); |
|
| 76 | + | const overwrite = await promptUser( |
|
| 77 | + | "Would you like to overwrite it? (y/N)", |
|
| 78 | + | "n", |
|
| 79 | + | ); |
|
| 80 | + | if (overwrite.toLowerCase() !== "y" && overwrite.toLowerCase() !== "yes") { |
|
| 81 | + | console.log("⏹️ Initialization cancelled"); |
|
| 82 | + | return; |
|
| 83 | + | } |
|
| 84 | + | } |
|
| 85 | + | ||
| 86 | + | console.log("\n📋 Setting up your components configuration...\n"); |
|
| 87 | + | ||
| 88 | + | // Get component directory path |
|
| 89 | + | const componentsPath = await promptUser( |
|
| 90 | + | "Where would you like to install your components?", |
|
| 91 | + | DEFAULT_CONFIG.components, |
|
| 92 | + | ); |
|
| 93 | + | ||
| 94 | + | // Create the configuration |
|
| 95 | + | const config: NornsConfig = { |
|
| 96 | + | components: componentsPath, |
|
| 97 | + | }; |
|
| 20 | 98 | ||
| 21 | - | if (!existsSync(componentsDir)) { |
|
| 22 | - | await mkdir(componentsDir, { recursive: true }); |
|
| 23 | - | console.log(`✅ Created ${componentsDir} directory`); |
|
| 24 | - | } else { |
|
| 25 | - | console.log(`📁 ${componentsDir} directory already exists`); |
|
| 99 | + | // Create components directory if it doesn't exist |
|
| 100 | + | if (!existsSync(componentsPath)) { |
|
| 101 | + | await mkdir(componentsPath, { recursive: true }); |
|
| 102 | + | console.log(`✅ Created ${componentsPath} directory`); |
|
| 26 | 103 | } |
|
| 27 | 104 | ||
| 28 | - | console.log("🎉 norns project initialized! You can now add components with:"); |
|
| 105 | + | // Save the configuration |
|
| 106 | + | await saveConfig(config); |
|
| 107 | + | console.log(`✅ Created ${CONFIG_FILE}`); |
|
| 108 | + | ||
| 109 | + | console.log( |
|
| 110 | + | "\n🎉 norns project initialized! You can now add components with:", |
|
| 111 | + | ); |
|
| 29 | 112 | console.log(" npx norns@latest add <component-name>"); |
|
| 113 | + | console.log(`\n📁 Components will be installed to: ${componentsPath}`); |
|
| 30 | 114 | } |
|
| 31 | 115 | ||
| 32 | 116 | async function addComponent(componentName: string | undefined) { |
|
| 38 | 122 | ||
| 39 | 123 | console.log(`🔄 Adding component: ${componentName}`); |
|
| 40 | 124 | ||
| 41 | - | const componentsDir = "components"; |
|
| 125 | + | // Load configuration |
|
| 126 | + | let config = await loadConfig(); |
|
| 127 | + | ||
| 128 | + | // If no config exists, ask user to run init first or use defaults |
|
| 129 | + | if (!config) { |
|
| 130 | + | console.log("📋 No norns.json found."); |
|
| 131 | + | const shouldInit = await promptUser( |
|
| 132 | + | "Would you like to run 'norns init' first? (Y/n)", |
|
| 133 | + | "y", |
|
| 134 | + | ); |
|
| 135 | + | ||
| 136 | + | if ( |
|
| 137 | + | shouldInit.toLowerCase() === "y" || |
|
| 138 | + | shouldInit.toLowerCase() === "yes" || |
|
| 139 | + | shouldInit === "" |
|
| 140 | + | ) { |
|
| 141 | + | await init(); |
|
| 142 | + | config = await loadConfig(); |
|
| 143 | + | } else { |
|
| 144 | + | console.log("📁 Using default configuration..."); |
|
| 145 | + | config = DEFAULT_CONFIG; |
|
| 146 | + | } |
|
| 147 | + | } |
|
| 148 | + | ||
| 149 | + | if (!config) { |
|
| 150 | + | console.error("❌ Failed to initialize configuration"); |
|
| 151 | + | process.exit(1); |
|
| 152 | + | } |
|
| 153 | + | ||
| 154 | + | const componentsDir = config.components; |
|
| 155 | + | ||
| 156 | + | // Create components directory if it doesn't exist |
|
| 42 | 157 | if (!existsSync(componentsDir)) { |
|
| 43 | - | console.log("📁 Components directory doesn't exist. Creating it..."); |
|
| 158 | + | console.log( |
|
| 159 | + | `📁 Components directory doesn't exist. Creating ${componentsDir}...`, |
|
| 160 | + | ); |
|
| 44 | 161 | await mkdir(componentsDir, { recursive: true }); |
|
| 45 | 162 | } |
|
| 46 | 163 | ||
| 62 | 179 | ||
| 63 | 180 | console.log(`✅ Added ${componentName} to ${componentPath}`); |
|
| 64 | 181 | console.log(`📝 You can now use it in your HTML:`); |
|
| 65 | - | console.log(` <script src="./components/${componentName}.js"></script>`); |
|
| 182 | + | ||
| 183 | + | // Calculate relative path from project root |
|
| 184 | + | const relativePath = componentsDir.startsWith("./") |
|
| 185 | + | ? componentsDir |
|
| 186 | + | : `./${componentsDir}`; |
|
| 187 | + | console.log( |
|
| 188 | + | ` <script src="${relativePath}/${componentName}.js"></script>`, |
|
| 189 | + | ); |
|
| 66 | 190 | console.log(` <${componentName}></${componentName}>`); |
|
| 67 | 191 | } catch (error) { |
|
| 68 | 192 | console.error(`❌ Failed to add component: ${error}`); |
|
| 75 | 199 | 🧙 norns - Web Component Library CLI |
|
| 76 | 200 | ||
| 77 | 201 | Usage: |
|
| 78 | - | npx norns@latest init Initialize a new norns project |
|
| 202 | + | npx norns@latest init Initialize a new norns project with norns.json |
|
| 79 | 203 | npx norns@latest add <component-name> Add a component to your project |
|
| 80 | 204 | npx norns@latest --help Show this help message |
|
| 81 | 205 | ||
| 83 | 207 | npx norns@latest init |
|
| 84 | 208 | npx norns@latest add connect-wallet |
|
| 85 | 209 | ||
| 210 | + | The init command will: |
|
| 211 | + | - Create a norns.json configuration file |
|
| 212 | + | - Set up your preferred component installation directory |
|
| 213 | + | - Create necessary directories |
|
| 214 | + | ||
| 86 | 215 | Available Components: |
|
| 87 | 216 | - connect-wallet A Web3 wallet connection component |
|
| 88 | 217 | - contract-call A Web3 contract interaction component |
|
| 218 | + | ||
| 219 | + | Configuration: |
|
| 220 | + | The norns.json file controls where components are installed. |
|
| 221 | + | You can customize the installation directory during init or edit the file directly. |
|
| 89 | 222 | `); |
|
| 90 | 223 | } |
|
| 91 | 224 | ||