zerozeeker 2.2.0 → 2.2.2

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.
Files changed (2) hide show
  1. package/dist/index.js +147 -79
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { Command } from "commander";
5
5
  import { execSync } from "child_process";
6
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";
@@ -49,9 +50,21 @@ function installDependencies(deps) {
49
50
  encoding: "utf-8"
50
51
  });
51
52
  } catch {
52
- console.warn(chalk.yellow(` Warning: Failed to auto-install dependencies. Install manually: npm install ${deps.join(" ")}`));
53
+ console.warn(chalk.yellow(` [!] Failed to auto-install dependencies. Install manually: npm install ${deps.join(" ")}`));
53
54
  }
54
55
  }
56
+ async function askYesNo(question, defaultYes = false) {
57
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
58
+ return new Promise((resolve) => {
59
+ rl.question(`${question} (${defaultYes ? "Y/n" : "y/N"}): `, (answer) => {
60
+ rl.close();
61
+ const a = answer.trim().toLowerCase();
62
+ if (a === "") return resolve(defaultYes);
63
+ if (["y", "yes"].includes(a)) return resolve(true);
64
+ return resolve(false);
65
+ });
66
+ });
67
+ }
55
68
  async function installRegistryDependencies(deps, projectRoot, installed = /* @__PURE__ */ new Set()) {
56
69
  const allFiles = [];
57
70
  const allNpmDeps = [];
@@ -85,103 +98,166 @@ async function installRegistryDependencies(deps, projectRoot, installed = /* @__
85
98
  if (registry.dependencies) {
86
99
  allNpmDeps.push(...registry.dependencies);
87
100
  }
88
- } catch (error) {
89
- console.warn(chalk.yellow(` Warning: Could not install registry dependency "${dep}"`));
101
+ } catch {
102
+ console.warn(chalk.yellow(` [!] Could not install registry dependency "${dep}"`));
90
103
  }
91
104
  }
92
105
  return { files: allFiles, npmDeps: allNpmDeps };
93
106
  }
107
+ function checkTypeScriptConfig(projectRoot) {
108
+ const tsconfigPath = join(projectRoot, "tsconfig.json");
109
+ if (!existsSync(tsconfigPath)) {
110
+ return { name: "TypeScript", passed: false, message: "tsconfig.json not found" };
111
+ }
112
+ try {
113
+ const tsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
114
+ const paths = tsconfig.compilerOptions?.paths || {};
115
+ const hasComponentsAlias = paths["@/components/*"] || paths["@/components"];
116
+ const hasLibAlias = paths["@/lib/*"] || paths["@/lib"];
117
+ if (hasComponentsAlias && hasLibAlias) {
118
+ return { name: "TypeScript paths", passed: true };
119
+ }
120
+ return {
121
+ name: "TypeScript paths",
122
+ passed: false,
123
+ message: "Missing @/components or @/lib path aliases"
124
+ };
125
+ } catch {
126
+ return { name: "TypeScript config", passed: false, message: "Invalid tsconfig.json" };
127
+ }
128
+ }
129
+ function checkTailwindConfig(projectRoot) {
130
+ const tailwindConfigs = [
131
+ "tailwind.config.ts",
132
+ "tailwind.config.js",
133
+ "tailwind.config.mjs",
134
+ "tailwind.config.cjs"
135
+ ];
136
+ const hasTailwind = tailwindConfigs.some((config) => existsSync(join(projectRoot, config)));
137
+ return hasTailwind ? { name: "Tailwind CSS", passed: true } : { name: "Tailwind CSS", passed: false, message: "Config file not found" };
138
+ }
139
+ function checkFramework(projectRoot) {
140
+ const packageJsonPath = join(projectRoot, "package.json");
141
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
142
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
143
+ if (deps.next) {
144
+ return { name: "Next.js", passed: true };
145
+ }
146
+ if (deps.react) {
147
+ return { name: "React", passed: true };
148
+ }
149
+ return { name: "React/Next.js", passed: false, message: "Not found in dependencies" };
150
+ }
151
+ function displaySetupHelp(checks) {
152
+ const tsCheck = checks.find((c) => c.name === "TypeScript");
153
+ const tailwindCheck = checks.find((c) => c.name === "Tailwind CSS");
154
+ if (tsCheck && !tsCheck.passed) {
155
+ console.log(chalk.dim("Install TypeScript:"));
156
+ console.log(chalk.white(" npm install -D typescript @types/node @types/react"));
157
+ console.log(chalk.dim("\nCreate tsconfig.json with path aliases:"));
158
+ console.log(chalk.white(" npx tsc --init"));
159
+ }
160
+ if (tailwindCheck && !tailwindCheck.passed) {
161
+ console.log(chalk.dim("\nInstall Tailwind CSS:"));
162
+ console.log(chalk.white(" npm install -D tailwindcss postcss autoprefixer"));
163
+ console.log(chalk.white(" npx tailwindcss init -p"));
164
+ }
165
+ console.log(chalk.dim("\nOr create a new Next.js project:"));
166
+ console.log(chalk.white(" npx create-next-app@latest --typescript --tailwind\n"));
167
+ }
168
+ async function autoFixSetup(projectRoot, needsTypeScript, needsTailwind, spinner) {
169
+ if (needsTypeScript) {
170
+ spinner.text = "Installing TypeScript and types...";
171
+ execSync("npm install -D typescript @types/node @types/react", { stdio: "inherit" });
172
+ }
173
+ const tsconfigPath = join(projectRoot, "tsconfig.json");
174
+ let tsconfig = {};
175
+ if (existsSync(tsconfigPath)) {
176
+ try {
177
+ tsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
178
+ } catch {
179
+ tsconfig = {};
180
+ }
181
+ } else {
182
+ spinner.text = "Creating tsconfig.json...";
183
+ tsconfig = { compilerOptions: {} };
184
+ writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2), "utf-8");
185
+ }
186
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
187
+ tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
188
+ tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
189
+ tsconfig.compilerOptions.paths["@/components/*"] = ["components/*"];
190
+ tsconfig.compilerOptions.paths["@/lib/*"] = ["lib/*"];
191
+ writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2), "utf-8");
192
+ if (needsTailwind) {
193
+ spinner.text = "Installing Tailwind CSS...";
194
+ execSync("npm install -D tailwindcss postcss autoprefixer", { stdio: "inherit" });
195
+ spinner.text = "Initializing Tailwind config...";
196
+ execSync("npx tailwindcss init -p", { stdio: "inherit" });
197
+ }
198
+ }
199
+ var COMPONENT_DESCRIPTIONS = {
200
+ "rainbow-button": "Animated rainbow gradient border - for when one color just will not cut it",
201
+ "shimmer-button": "Moving border glow effect - subtle flex, maximum impact",
202
+ "magnetic-button": "Cursor-following magnetic effect - it literally chases your mouse",
203
+ "expand-button": "Expanding pill animation - small to big, just like your startup",
204
+ "flip-button": "3D flip card effect - because flat is boring",
205
+ "circle-reveal-button": "Icon to pill expansion - the element of surprise"
206
+ };
94
207
  var program = new Command();
95
208
  program.name("zerozeeker").description("CLI for installing ZeroZeeker UI components - because life is too short for boring interfaces").version("2.2.0");
96
209
  program.command("init").description("Initialize ZeroZeeker in your project").action(async () => {
97
210
  const spinner = ora("Checking project setup...").start();
98
211
  try {
99
212
  const projectRoot = findProjectRoot();
100
- const checks = [];
101
- const tsconfigPath = join(projectRoot, "tsconfig.json");
102
- if (existsSync(tsconfigPath)) {
103
- try {
104
- const tsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
105
- const paths = tsconfig.compilerOptions?.paths || {};
106
- const hasComponentsAlias = paths["@/components/*"] || paths["@/components"];
107
- const hasLibAlias = paths["@/lib/*"] || paths["@/lib"];
108
- if (hasComponentsAlias && hasLibAlias) {
109
- checks.push({ name: "TypeScript paths", passed: true });
110
- } else {
111
- checks.push({
112
- name: "TypeScript paths",
113
- passed: false,
114
- message: "Missing @/components or @/lib path aliases"
115
- });
116
- }
117
- } catch {
118
- checks.push({ name: "TypeScript config", passed: false, message: "Invalid tsconfig.json" });
119
- }
120
- } else {
121
- checks.push({ name: "TypeScript", passed: false, message: "tsconfig.json not found" });
122
- }
123
- const tailwindConfigs = [
124
- "tailwind.config.ts",
125
- "tailwind.config.js",
126
- "tailwind.config.mjs",
127
- "tailwind.config.cjs"
213
+ const checks = [
214
+ checkTypeScriptConfig(projectRoot),
215
+ checkTailwindConfig(projectRoot),
216
+ checkFramework(projectRoot)
128
217
  ];
129
- const hasTailwind = tailwindConfigs.some((config) => existsSync(join(projectRoot, config)));
130
- if (hasTailwind) {
131
- checks.push({ name: "Tailwind CSS", passed: true });
132
- } else {
133
- checks.push({ name: "Tailwind CSS", passed: false, message: "Config file not found" });
134
- }
135
- const packageJsonPath = join(projectRoot, "package.json");
136
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
137
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
138
- const hasReact = deps.react;
139
- const hasNext = deps.next;
140
- if (hasReact || hasNext) {
141
- checks.push({
142
- name: hasNext ? "Next.js" : "React",
143
- passed: true
144
- });
145
- } else {
146
- checks.push({ name: "React/Next.js", passed: false, message: "Not found in dependencies" });
147
- }
148
218
  spinner.stop();
149
- console.log(chalk.bold("\n\u{1F50D} Project Setup Check\n"));
219
+ console.log(chalk.bold("\n[*] Project Setup Check\n"));
150
220
  let allPassed = true;
151
221
  for (const check of checks) {
152
222
  if (check.passed) {
153
- console.log(chalk.green(` \u2713 ${check.name}`));
223
+ console.log(chalk.green(` [+] ${check.name}`));
154
224
  } else {
155
- console.log(chalk.red(` \u2717 ${check.name}${check.message ? `: ${check.message}` : ""}`));
225
+ console.log(chalk.red(` [x] ${check.name}${check.message ? `: ${check.message}` : ""}`));
156
226
  allPassed = false;
157
227
  }
158
228
  }
159
229
  if (allPassed) {
160
- console.log(chalk.green("\n\u2728 Your project is ready for ZeroZeeker!\n"));
230
+ console.log(chalk.green("\n[*] Your project is ready for ZeroZeeker!\n"));
161
231
  console.log(chalk.dim("Get started:"));
162
232
  console.log(chalk.cyan(" npx zerozeeker add rainbow-button"));
163
233
  console.log(chalk.dim("\nList all components:"));
164
234
  console.log(chalk.cyan(" npx zerozeeker list\n"));
165
- } else {
166
- console.log(chalk.yellow("\n\u26A0\uFE0F Some setup issues detected\n"));
167
- if (!checks.find((c) => c.name === "TypeScript")?.passed) {
168
- console.log(chalk.dim("Install TypeScript:"));
169
- console.log(chalk.white(" npm install -D typescript @types/node @types/react"));
170
- console.log(chalk.dim("\nCreate tsconfig.json with path aliases:"));
171
- console.log(chalk.white(" npx tsc --init"));
172
- }
173
- if (!checks.find((c) => c.name === "Tailwind CSS")?.passed) {
174
- console.log(chalk.dim("\nInstall Tailwind CSS:"));
175
- console.log(chalk.white(" npm install -D tailwindcss postcss autoprefixer"));
176
- console.log(chalk.white(" npx tailwindcss init -p"));
177
- }
178
- console.log(chalk.dim("\nOr create a new Next.js project:"));
179
- console.log(chalk.white(" npx create-next-app@latest --typescript --tailwind\n"));
235
+ return;
236
+ }
237
+ console.log(chalk.yellow("\n[!] Some setup issues detected\n"));
238
+ displaySetupHelp(checks);
239
+ const needsTypeScript = !checks.find(
240
+ (c) => c.name === "TypeScript" || c.name === "TypeScript paths" || c.name === "TypeScript config"
241
+ )?.passed;
242
+ const needsTailwind = !checks.find((c) => c.name === "Tailwind CSS")?.passed;
243
+ const doAuto = await askYesNo("Would you like ZeroZeeker to try to automatically fix these issues now?", true);
244
+ if (!doAuto) {
245
+ process.exit(1);
246
+ }
247
+ spinner.start();
248
+ try {
249
+ await autoFixSetup(projectRoot, needsTypeScript, needsTailwind, spinner);
250
+ spinner.stop();
251
+ console.log(chalk.green("\n[+] Auto-fix complete. Re-run `npx zerozeeker init` to re-check, or proceed to install components."));
252
+ process.exit(0);
253
+ } catch {
254
+ spinner.stop();
255
+ console.error(chalk.red("\n[x] Auto-fix failed. See errors above."));
180
256
  process.exit(1);
181
257
  }
182
258
  } catch (error) {
183
259
  spinner.stop();
184
- console.error(chalk.red("\n\u2717 Initialization failed\n"));
260
+ console.error(chalk.red("\n[x] Initialization failed\n"));
185
261
  if (error instanceof Error && error.message.includes("package.json")) {
186
262
  console.log(chalk.dim("Make sure you're in a React/Next.js project directory.\n"));
187
263
  } else {
@@ -279,17 +355,9 @@ program.command("add <component>").description("Add a component from ZeroZeeker
279
355
  program.command("list").description("List all available components").action(() => {
280
356
  console.log(chalk.bold("\nZeroZeeker UI Components\n"));
281
357
  console.log(chalk.dim("Modern, polished components that make users actually want to interact.\n"));
282
- const descriptions = {
283
- "rainbow-button": "Animated rainbow gradient border - for when one color just will not cut it",
284
- "shimmer-button": "Moving border glow effect - subtle flex, maximum impact",
285
- "magnetic-button": "Cursor-following magnetic effect - it literally chases your mouse",
286
- "expand-button": "Expanding pill animation - small to big, just like your startup",
287
- "flip-button": "3D flip card effect - because flat is boring",
288
- "circle-reveal-button": "Icon to pill expansion - the element of surprise"
289
- };
290
358
  COMPONENTS.filter((c) => c !== "index").forEach((component) => {
291
359
  console.log(chalk.cyan(` ${component}`));
292
- console.log(chalk.dim(` ${descriptions[component]}
360
+ console.log(chalk.dim(` ${COMPONENT_DESCRIPTIONS[component]}
293
361
  `));
294
362
  });
295
363
  console.log(chalk.dim("Install any component with: ") + chalk.white("npx zerozeeker add <component>"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zerozeeker",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "Zero-config CLI for installing ZeroZeeker UI components. No shadcn required.",
5
5
  "type": "module",
6
6
  "bin": {