zerozeeker 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +161 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Zero-config CLI** for installing production-ready UI components into your React or Next.js projects.
|
|
4
4
|
|
|
5
|
-
**No setup required.
|
|
5
|
+
**No setup required. Just install and go.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/zerozeeker)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
// index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { execSync } from "child_process";
|
|
6
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
7
7
|
import { join, dirname } from "path";
|
|
8
|
+
import readline from "readline";
|
|
8
9
|
import ora from "ora";
|
|
9
10
|
import chalk from "chalk";
|
|
10
11
|
var REGISTRY_URL = "https://www.zerozeeker.com/r";
|
|
@@ -92,10 +93,163 @@ async function installRegistryDependencies(deps, projectRoot, installed = /* @__
|
|
|
92
93
|
return { files: allFiles, npmDeps: allNpmDeps };
|
|
93
94
|
}
|
|
94
95
|
var program = new Command();
|
|
95
|
-
program.name("zerozeeker").description("CLI for installing ZeroZeeker UI components - because life is too short for boring interfaces").version("2.
|
|
96
|
+
program.name("zerozeeker").description("CLI for installing ZeroZeeker UI components - because life is too short for boring interfaces").version("2.2.0");
|
|
97
|
+
program.command("init").description("Initialize ZeroZeeker in your project").action(async () => {
|
|
98
|
+
const spinner = ora("Checking project setup...").start();
|
|
99
|
+
try {
|
|
100
|
+
const projectRoot = findProjectRoot();
|
|
101
|
+
const checks = [];
|
|
102
|
+
const tsconfigPath = join(projectRoot, "tsconfig.json");
|
|
103
|
+
if (existsSync(tsconfigPath)) {
|
|
104
|
+
try {
|
|
105
|
+
const tsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
|
|
106
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
107
|
+
const hasComponentsAlias = paths["@/components/*"] || paths["@/components"];
|
|
108
|
+
const hasLibAlias = paths["@/lib/*"] || paths["@/lib"];
|
|
109
|
+
if (hasComponentsAlias && hasLibAlias) {
|
|
110
|
+
checks.push({ name: "TypeScript paths", passed: true });
|
|
111
|
+
} else {
|
|
112
|
+
checks.push({
|
|
113
|
+
name: "TypeScript paths",
|
|
114
|
+
passed: false,
|
|
115
|
+
message: "Missing @/components or @/lib path aliases"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
checks.push({ name: "TypeScript config", passed: false, message: "Invalid tsconfig.json" });
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
checks.push({ name: "TypeScript", passed: false, message: "tsconfig.json not found" });
|
|
123
|
+
}
|
|
124
|
+
const tailwindConfigs = [
|
|
125
|
+
"tailwind.config.ts",
|
|
126
|
+
"tailwind.config.js",
|
|
127
|
+
"tailwind.config.mjs",
|
|
128
|
+
"tailwind.config.cjs"
|
|
129
|
+
];
|
|
130
|
+
const hasTailwind = tailwindConfigs.some((config) => existsSync(join(projectRoot, config)));
|
|
131
|
+
if (hasTailwind) {
|
|
132
|
+
checks.push({ name: "Tailwind CSS", passed: true });
|
|
133
|
+
} else {
|
|
134
|
+
checks.push({ name: "Tailwind CSS", passed: false, message: "Config file not found" });
|
|
135
|
+
}
|
|
136
|
+
const packageJsonPath = join(projectRoot, "package.json");
|
|
137
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
138
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
139
|
+
const hasReact = deps.react;
|
|
140
|
+
const hasNext = deps.next;
|
|
141
|
+
if (hasReact || hasNext) {
|
|
142
|
+
checks.push({
|
|
143
|
+
name: hasNext ? "Next.js" : "React",
|
|
144
|
+
passed: true
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
checks.push({ name: "React/Next.js", passed: false, message: "Not found in dependencies" });
|
|
148
|
+
}
|
|
149
|
+
spinner.stop();
|
|
150
|
+
console.log(chalk.bold("\n\u{1F50D} Project Setup Check\n"));
|
|
151
|
+
let allPassed = true;
|
|
152
|
+
for (const check of checks) {
|
|
153
|
+
if (check.passed) {
|
|
154
|
+
console.log(chalk.green(` \u2713 ${check.name}`));
|
|
155
|
+
} else {
|
|
156
|
+
console.log(chalk.red(` \u2717 ${check.name}${check.message ? `: ${check.message}` : ""}`));
|
|
157
|
+
allPassed = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (allPassed) {
|
|
161
|
+
console.log(chalk.green("\n\u2728 Your project is ready for ZeroZeeker!\n"));
|
|
162
|
+
console.log(chalk.dim("Get started:"));
|
|
163
|
+
console.log(chalk.cyan(" npx zerozeeker add rainbow-button"));
|
|
164
|
+
console.log(chalk.dim("\nList all components:"));
|
|
165
|
+
console.log(chalk.cyan(" npx zerozeeker list\n"));
|
|
166
|
+
} else {
|
|
167
|
+
console.log(chalk.yellow("\n\u26A0\uFE0F Some setup issues detected\n"));
|
|
168
|
+
if (!checks.find((c) => c.name === "TypeScript")?.passed) {
|
|
169
|
+
console.log(chalk.dim("Install TypeScript:"));
|
|
170
|
+
console.log(chalk.white(" npm install -D typescript @types/node @types/react"));
|
|
171
|
+
console.log(chalk.dim("\nCreate tsconfig.json with path aliases:"));
|
|
172
|
+
console.log(chalk.white(" npx tsc --init"));
|
|
173
|
+
}
|
|
174
|
+
if (!checks.find((c) => c.name === "Tailwind CSS")?.passed) {
|
|
175
|
+
console.log(chalk.dim("\nInstall Tailwind CSS:"));
|
|
176
|
+
console.log(chalk.white(" npm install -D tailwindcss postcss autoprefixer"));
|
|
177
|
+
console.log(chalk.white(" npx tailwindcss init -p"));
|
|
178
|
+
}
|
|
179
|
+
console.log(chalk.dim("\nOr create a new Next.js project:"));
|
|
180
|
+
console.log(chalk.white(" npx create-next-app@latest --typescript --tailwind\n"));
|
|
181
|
+
async function askYesNo(question, defaultYes = false) {
|
|
182
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
183
|
+
return new Promise((resolve) => {
|
|
184
|
+
rl.question(`${question} (${defaultYes ? "Y/n" : "y/N"}): `, (answer) => {
|
|
185
|
+
rl.close();
|
|
186
|
+
const a = answer.trim().toLowerCase();
|
|
187
|
+
if (a === "") return resolve(defaultYes);
|
|
188
|
+
if (["y", "yes"].includes(a)) return resolve(true);
|
|
189
|
+
return resolve(false);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const needsTypeScript = !checks.find((c) => c.name === "TypeScript" || c.name === "TypeScript paths" || c.name === "TypeScript config")?.passed;
|
|
194
|
+
const tsPathsMissing = checks.find((c) => c.name === "TypeScript paths" && !c.passed) !== void 0;
|
|
195
|
+
const needsTailwind = !checks.find((c) => c.name === "Tailwind CSS")?.passed;
|
|
196
|
+
const doAuto = await askYesNo("Would you like ZeroZeeker to try to automatically fix these issues now?", true);
|
|
197
|
+
if (!doAuto) process.exit(1);
|
|
198
|
+
spinner.start();
|
|
199
|
+
try {
|
|
200
|
+
if (needsTypeScript) {
|
|
201
|
+
spinner.text = "Installing TypeScript and types...";
|
|
202
|
+
execSync("npm install -D typescript @types/node @types/react", { stdio: "inherit" });
|
|
203
|
+
}
|
|
204
|
+
const tsconfigPath2 = join(projectRoot, "tsconfig.json");
|
|
205
|
+
let tsconfig = {};
|
|
206
|
+
if (existsSync(tsconfigPath2)) {
|
|
207
|
+
try {
|
|
208
|
+
tsconfig = JSON.parse(readFileSync(tsconfigPath2, "utf-8"));
|
|
209
|
+
} catch {
|
|
210
|
+
tsconfig = {};
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
spinner.text = "Creating tsconfig.json...";
|
|
214
|
+
tsconfig = { compilerOptions: {} };
|
|
215
|
+
writeFileSync(tsconfigPath2, JSON.stringify(tsconfig, null, 2), "utf-8");
|
|
216
|
+
}
|
|
217
|
+
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
218
|
+
tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
|
|
219
|
+
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
220
|
+
tsconfig.compilerOptions.paths["@/components/*"] = ["components/*"];
|
|
221
|
+
tsconfig.compilerOptions.paths["@/lib/*"] = ["lib/*"];
|
|
222
|
+
writeFileSync(tsconfigPath2, JSON.stringify(tsconfig, null, 2), "utf-8");
|
|
223
|
+
if (needsTailwind) {
|
|
224
|
+
spinner.text = "Installing Tailwind CSS...";
|
|
225
|
+
execSync("npm install -D tailwindcss postcss autoprefixer", { stdio: "inherit" });
|
|
226
|
+
spinner.text = "Initializing Tailwind config...";
|
|
227
|
+
execSync("npx tailwindcss init -p", { stdio: "inherit" });
|
|
228
|
+
}
|
|
229
|
+
spinner.stop();
|
|
230
|
+
console.log(chalk.green("\n\u2705 Auto-fix complete. Re-run `npx zerozeeker init` to re-check, or proceed to install components."));
|
|
231
|
+
process.exit(0);
|
|
232
|
+
} catch (err) {
|
|
233
|
+
spinner.stop();
|
|
234
|
+
console.error(chalk.red("\n\u2717 Auto-fix failed. See errors above."));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
spinner.stop();
|
|
240
|
+
console.error(chalk.red("\n\u2717 Initialization failed\n"));
|
|
241
|
+
if (error instanceof Error && error.message.includes("package.json")) {
|
|
242
|
+
console.log(chalk.dim("Make sure you're in a React/Next.js project directory.\n"));
|
|
243
|
+
} else {
|
|
244
|
+
console.log(chalk.dim(`${error instanceof Error ? error.message : "Unknown error"}
|
|
245
|
+
`));
|
|
246
|
+
}
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
96
250
|
program.command("add <component>").description("Add a component from ZeroZeeker registry").action(async (component) => {
|
|
97
251
|
if (!COMPONENTS.includes(component)) {
|
|
98
|
-
console.error(chalk.red(`Component "${component}" does not exist in this dimension.`));
|
|
252
|
+
console.error(chalk.red(`[x] Component "${component}" does not exist in this dimension.`));
|
|
99
253
|
console.log(chalk.dim("\nHere are the components that actually exist:"));
|
|
100
254
|
COMPONENTS.filter((c) => c !== "index").forEach((c) => {
|
|
101
255
|
console.log(chalk.cyan(` - ${c}`));
|
|
@@ -128,7 +282,7 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
128
282
|
if (existsSync(fullPath)) {
|
|
129
283
|
spinner.stop();
|
|
130
284
|
console.warn(chalk.yellow(`
|
|
131
|
-
|
|
285
|
+
[!] File already exists: ${targetPath}`));
|
|
132
286
|
console.log(chalk.dim(" Skipping to avoid overwriting your changes."));
|
|
133
287
|
console.log(chalk.dim(` To force reinstall: delete the file and run the command again.
|
|
134
288
|
`));
|
|
@@ -146,7 +300,7 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
146
300
|
}
|
|
147
301
|
spinner.stop();
|
|
148
302
|
console.log(chalk.green(`
|
|
149
|
-
|
|
303
|
+
[+] Successfully installed ${component}`));
|
|
150
304
|
if (filesInstalled.length > 0) {
|
|
151
305
|
console.log(chalk.dim("\n Files added:"));
|
|
152
306
|
filesInstalled.forEach((f) => {
|
|
@@ -159,11 +313,11 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
159
313
|
console.log(chalk.cyan(` ${d}`));
|
|
160
314
|
});
|
|
161
315
|
}
|
|
162
|
-
console.log(chalk.dim("\n Now go make something beautiful
|
|
316
|
+
console.log(chalk.dim("\n Now go make something beautiful.\n"));
|
|
163
317
|
} catch (error) {
|
|
164
318
|
spinner.stop();
|
|
165
319
|
console.error(chalk.red(`
|
|
166
|
-
|
|
320
|
+
[x] Failed to install ${component}`));
|
|
167
321
|
if (error instanceof Error) {
|
|
168
322
|
if (error.message.includes("package.json")) {
|
|
169
323
|
console.log(chalk.dim("\n Make sure you're in a React/Next.js project directory."));
|