zerozeeker 2.0.0 → 2.2.0
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 +159 -12
- 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,7 +3,7 @@
|
|
|
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
8
|
import ora from "ora";
|
|
9
9
|
import chalk from "chalk";
|
|
@@ -52,11 +52,148 @@ function installDependencies(deps) {
|
|
|
52
52
|
console.warn(chalk.yellow(` Warning: Failed to auto-install dependencies. Install manually: npm install ${deps.join(" ")}`));
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
async function installRegistryDependencies(deps, projectRoot, installed = /* @__PURE__ */ new Set()) {
|
|
56
|
+
const allFiles = [];
|
|
57
|
+
const allNpmDeps = [];
|
|
58
|
+
for (const dep of deps) {
|
|
59
|
+
if (installed.has(dep)) continue;
|
|
60
|
+
installed.add(dep);
|
|
61
|
+
const url = `${REGISTRY_URL}/${dep}.json`;
|
|
62
|
+
try {
|
|
63
|
+
const registry = await fetchRegistry(url);
|
|
64
|
+
if (registry.registryDependencies && registry.registryDependencies.length > 0) {
|
|
65
|
+
const nested = await installRegistryDependencies(
|
|
66
|
+
registry.registryDependencies,
|
|
67
|
+
projectRoot,
|
|
68
|
+
installed
|
|
69
|
+
);
|
|
70
|
+
allFiles.push(...nested.files);
|
|
71
|
+
allNpmDeps.push(...nested.npmDeps);
|
|
72
|
+
}
|
|
73
|
+
if (registry.files && registry.files.length > 0) {
|
|
74
|
+
for (const file of registry.files) {
|
|
75
|
+
const targetPath = file.target || file.path;
|
|
76
|
+
const fullPath = join(projectRoot, targetPath);
|
|
77
|
+
if (existsSync(fullPath)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
ensureDir(fullPath);
|
|
81
|
+
writeFileSync(fullPath, file.content, "utf-8");
|
|
82
|
+
allFiles.push(targetPath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (registry.dependencies) {
|
|
86
|
+
allNpmDeps.push(...registry.dependencies);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.warn(chalk.yellow(` Warning: Could not install registry dependency "${dep}"`));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { files: allFiles, npmDeps: allNpmDeps };
|
|
93
|
+
}
|
|
55
94
|
var program = new Command();
|
|
56
|
-
program.name("zerozeeker").description("CLI for installing ZeroZeeker UI components - because life is too short for boring interfaces").version("2.
|
|
95
|
+
program.name("zerozeeker").description("CLI for installing ZeroZeeker UI components - because life is too short for boring interfaces").version("2.2.0");
|
|
96
|
+
program.command("init").description("Initialize ZeroZeeker in your project").action(async () => {
|
|
97
|
+
const spinner = ora("Checking project setup...").start();
|
|
98
|
+
try {
|
|
99
|
+
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"
|
|
128
|
+
];
|
|
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
|
+
spinner.stop();
|
|
149
|
+
console.log(chalk.bold("\n\u{1F50D} Project Setup Check\n"));
|
|
150
|
+
let allPassed = true;
|
|
151
|
+
for (const check of checks) {
|
|
152
|
+
if (check.passed) {
|
|
153
|
+
console.log(chalk.green(` \u2713 ${check.name}`));
|
|
154
|
+
} else {
|
|
155
|
+
console.log(chalk.red(` \u2717 ${check.name}${check.message ? `: ${check.message}` : ""}`));
|
|
156
|
+
allPassed = false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (allPassed) {
|
|
160
|
+
console.log(chalk.green("\n\u2728 Your project is ready for ZeroZeeker!\n"));
|
|
161
|
+
console.log(chalk.dim("Get started:"));
|
|
162
|
+
console.log(chalk.cyan(" npx zerozeeker add rainbow-button"));
|
|
163
|
+
console.log(chalk.dim("\nList all components:"));
|
|
164
|
+
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"));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
spinner.stop();
|
|
184
|
+
console.error(chalk.red("\n\u2717 Initialization failed\n"));
|
|
185
|
+
if (error instanceof Error && error.message.includes("package.json")) {
|
|
186
|
+
console.log(chalk.dim("Make sure you're in a React/Next.js project directory.\n"));
|
|
187
|
+
} else {
|
|
188
|
+
console.log(chalk.dim(`${error instanceof Error ? error.message : "Unknown error"}
|
|
189
|
+
`));
|
|
190
|
+
}
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
57
194
|
program.command("add <component>").description("Add a component from ZeroZeeker registry").action(async (component) => {
|
|
58
195
|
if (!COMPONENTS.includes(component)) {
|
|
59
|
-
console.error(chalk.red(`Component "${component}" does not exist in this dimension.`));
|
|
196
|
+
console.error(chalk.red(`[x] Component "${component}" does not exist in this dimension.`));
|
|
60
197
|
console.log(chalk.dim("\nHere are the components that actually exist:"));
|
|
61
198
|
COMPONENTS.filter((c) => c !== "index").forEach((c) => {
|
|
62
199
|
console.log(chalk.cyan(` - ${c}`));
|
|
@@ -71,7 +208,16 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
71
208
|
spinner.text = `Fetching ${chalk.cyan(component)} from registry...`;
|
|
72
209
|
const registry = await fetchRegistry(url);
|
|
73
210
|
const filesInstalled = [];
|
|
74
|
-
const
|
|
211
|
+
const allDependencies = [...registry.dependencies || []];
|
|
212
|
+
if (registry.registryDependencies && registry.registryDependencies.length > 0) {
|
|
213
|
+
spinner.text = `Installing registry dependencies...`;
|
|
214
|
+
const registryResult = await installRegistryDependencies(
|
|
215
|
+
registry.registryDependencies,
|
|
216
|
+
projectRoot
|
|
217
|
+
);
|
|
218
|
+
filesInstalled.push(...registryResult.files);
|
|
219
|
+
allDependencies.push(...registryResult.npmDeps);
|
|
220
|
+
}
|
|
75
221
|
if (registry.files && registry.files.length > 0) {
|
|
76
222
|
spinner.text = `Installing ${chalk.cyan(component)} files...`;
|
|
77
223
|
for (const file of registry.files) {
|
|
@@ -80,7 +226,7 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
80
226
|
if (existsSync(fullPath)) {
|
|
81
227
|
spinner.stop();
|
|
82
228
|
console.warn(chalk.yellow(`
|
|
83
|
-
|
|
229
|
+
[!] File already exists: ${targetPath}`));
|
|
84
230
|
console.log(chalk.dim(" Skipping to avoid overwriting your changes."));
|
|
85
231
|
console.log(chalk.dim(` To force reinstall: delete the file and run the command again.
|
|
86
232
|
`));
|
|
@@ -91,30 +237,31 @@ program.command("add <component>").description("Add a component from ZeroZeeker
|
|
|
91
237
|
filesInstalled.push(targetPath);
|
|
92
238
|
}
|
|
93
239
|
}
|
|
94
|
-
|
|
240
|
+
const uniqueDeps = [...new Set(allDependencies)];
|
|
241
|
+
if (uniqueDeps.length > 0) {
|
|
95
242
|
spinner.text = "Installing npm dependencies...";
|
|
96
|
-
installDependencies(
|
|
243
|
+
installDependencies(uniqueDeps);
|
|
97
244
|
}
|
|
98
245
|
spinner.stop();
|
|
99
246
|
console.log(chalk.green(`
|
|
100
|
-
|
|
247
|
+
[+] Successfully installed ${component}`));
|
|
101
248
|
if (filesInstalled.length > 0) {
|
|
102
249
|
console.log(chalk.dim("\n Files added:"));
|
|
103
250
|
filesInstalled.forEach((f) => {
|
|
104
251
|
console.log(chalk.cyan(` ${f}`));
|
|
105
252
|
});
|
|
106
253
|
}
|
|
107
|
-
if (
|
|
254
|
+
if (uniqueDeps.length > 0) {
|
|
108
255
|
console.log(chalk.dim("\n Dependencies installed:"));
|
|
109
|
-
|
|
256
|
+
uniqueDeps.forEach((d) => {
|
|
110
257
|
console.log(chalk.cyan(` ${d}`));
|
|
111
258
|
});
|
|
112
259
|
}
|
|
113
|
-
console.log(chalk.dim("\n Now go make something beautiful
|
|
260
|
+
console.log(chalk.dim("\n Now go make something beautiful.\n"));
|
|
114
261
|
} catch (error) {
|
|
115
262
|
spinner.stop();
|
|
116
263
|
console.error(chalk.red(`
|
|
117
|
-
|
|
264
|
+
[x] Failed to install ${component}`));
|
|
118
265
|
if (error instanceof Error) {
|
|
119
266
|
if (error.message.includes("package.json")) {
|
|
120
267
|
console.log(chalk.dim("\n Make sure you're in a React/Next.js project directory."));
|