chore: added norns.json setup 80583bee
Steve · 2025-09-21 16:36 2 file(s) · +146 −13
README.md +2 −2
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
src/index.ts +144 −11
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