@tokiui/cli 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/dist/index.js +176 -33
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ var import_fs_extra2 = __toESM(require("fs-extra"));
33
33
  var import_prompts = __toESM(require("prompts"));
34
34
  var import_kleur = __toESM(require("kleur"));
35
35
  var import_ora = __toESM(require("ora"));
36
+ var import_execa = require("execa");
36
37
 
37
38
  // src/utils/config.ts
38
39
  var import_path = __toESM(require("path"));
@@ -55,51 +56,192 @@ function detectPackageManager(cwd) {
55
56
  }
56
57
 
57
58
  // src/commands/init.ts
59
+ var GLOBALS_CANDIDATES = [
60
+ "src/app/globals.css",
61
+ "src/styles/globals.css",
62
+ "src/index.css",
63
+ "app/globals.css",
64
+ "styles/globals.css",
65
+ "index.css"
66
+ ];
67
+ var POSTCSS_CANDIDATES = [
68
+ "postcss.config.mjs",
69
+ "postcss.config.js",
70
+ "postcss.config.cjs"
71
+ ];
72
+ function detectGlobalsCss(cwd) {
73
+ return GLOBALS_CANDIDATES.find((c) => import_fs_extra2.default.existsSync(import_path2.default.join(cwd, c)));
74
+ }
75
+ function detectPostcss(cwd) {
76
+ return POSTCSS_CANDIDATES.find((f) => import_fs_extra2.default.existsSync(import_path2.default.join(cwd, f)));
77
+ }
78
+ function hasTailwindV3(cwd) {
79
+ return import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "tailwind.config.ts")) || import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "tailwind.config.js"));
80
+ }
58
81
  var initCommand = new import_commander.Command("init").description("Initialize tokiui in your project").action(async () => {
59
82
  const cwd = process.cwd();
60
- console.log(import_kleur.default.bold("\nInitializing tokiui...\n"));
61
- const answers = await (0, import_prompts.default)([
62
- {
63
- type: "text",
64
- name: "componentsDir",
65
- message: "Where should components be installed?",
66
- initial: "src/components/ui"
67
- },
83
+ console.log(import_kleur.default.bold("\n tokiui \u2014 setup\n"));
84
+ const hasSrc = import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "src"));
85
+ const isNext = import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "next.config.ts")) || import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "next.config.js")) || import_fs_extra2.default.existsSync(import_path2.default.join(cwd, "next.config.mjs"));
86
+ const detectedGlobals = detectGlobalsCss(cwd);
87
+ if (hasTailwindV3(cwd)) {
88
+ console.log(
89
+ import_kleur.default.yellow(
90
+ " \u26A0 tailwind.config.ts detected \u2014 tokiui requires Tailwind CSS v4.\n Migrate first: https://tailwindcss.com/docs/upgrade-guide\n"
91
+ )
92
+ );
93
+ }
94
+ const answers = await (0, import_prompts.default)(
95
+ [
96
+ {
97
+ type: "text",
98
+ name: "componentsDir",
99
+ message: "Where should components be installed?",
100
+ initial: hasSrc ? "src/components/ui" : "components/ui"
101
+ },
102
+ {
103
+ type: "text",
104
+ name: "libDir",
105
+ message: "Where should utility files be placed?",
106
+ initial: hasSrc ? "src/lib" : "lib"
107
+ },
108
+ {
109
+ type: "text",
110
+ name: "globalsPath",
111
+ message: "Where is your global CSS file?",
112
+ initial: detectedGlobals ?? (hasSrc ? "src/app/globals.css" : "app/globals.css")
113
+ }
114
+ ],
68
115
  {
69
- type: "text",
70
- name: "libDir",
71
- message: "Where should utility files be placed?",
72
- initial: "src/lib"
116
+ onCancel() {
117
+ console.log(import_kleur.default.red("\n Aborted.\n"));
118
+ process.exit(0);
119
+ }
73
120
  }
74
- ]);
75
- if (!answers.componentsDir) {
76
- console.log(import_kleur.default.red("Aborted."));
77
- process.exit(0);
78
- }
79
- const spinner = (0, import_ora.default)("Setting up project...").start();
121
+ );
122
+ const pm = detectPackageManager(cwd);
123
+ const installCmd = pm === "npm" ? "install" : "add";
124
+ const libAlias = hasSrc ? "@/" + answers.libDir.replace(/^src\//, "") : "@/" + answers.libDir;
125
+ const spinner = (0, import_ora.default)();
126
+ spinner.start("Creating directories");
80
127
  await import_fs_extra2.default.ensureDir(import_path2.default.join(cwd, answers.componentsDir));
81
128
  await import_fs_extra2.default.ensureDir(import_path2.default.join(cwd, answers.libDir));
129
+ spinner.succeed("Directories ready");
130
+ spinner.start(`Installing packages with ${pm}`);
131
+ try {
132
+ await (0, import_execa.execa)(
133
+ pm,
134
+ [installCmd, "@tokiui/ui", "tailwindcss", "@tailwindcss/postcss", "clsx", "tailwind-merge"],
135
+ { cwd }
136
+ );
137
+ spinner.succeed("Packages installed");
138
+ } catch {
139
+ spinner.fail("Package install failed \u2014 run manually:");
140
+ console.log(
141
+ import_kleur.default.dim(
142
+ `
143
+ ${pm} ${installCmd} @tokiui/ui tailwindcss @tailwindcss/postcss clsx tailwind-merge
144
+ `
145
+ )
146
+ );
147
+ }
148
+ spinner.start("Writing utility functions");
82
149
  const cnPath = import_path2.default.join(cwd, answers.libDir, "utils.ts");
83
150
  if (!import_fs_extra2.default.existsSync(cnPath)) {
84
151
  await import_fs_extra2.default.writeFile(
85
152
  cnPath,
86
- `import { clsx, type ClassValue } from 'clsx'
87
- import { twMerge } from 'tailwind-merge'
88
-
89
- export function cn(...inputs: ClassValue[]) {
90
- return twMerge(clsx(inputs))
153
+ [
154
+ `import { clsx, type ClassValue } from 'clsx'`,
155
+ `import { twMerge } from 'tailwind-merge'`,
156
+ ``,
157
+ `export function cn(...inputs: ClassValue[]) {`,
158
+ ` return twMerge(clsx(inputs))`,
159
+ `}`
160
+ ].join("\n") + "\n"
161
+ );
162
+ spinner.succeed("utils.ts written");
163
+ } else {
164
+ spinner.succeed("utils.ts already exists \u2014 skipped");
165
+ }
166
+ spinner.start("Configuring PostCSS");
167
+ const existingPostcss = detectPostcss(cwd);
168
+ if (!existingPostcss) {
169
+ await import_fs_extra2.default.writeFile(
170
+ import_path2.default.join(cwd, "postcss.config.mjs"),
171
+ `export default {
172
+ plugins: {
173
+ '@tailwindcss/postcss': {},
174
+ },
91
175
  }
92
176
  `
93
177
  );
178
+ spinner.succeed("postcss.config.mjs created");
179
+ } else {
180
+ const content = await import_fs_extra2.default.readFile(import_path2.default.join(cwd, existingPostcss), "utf-8");
181
+ if (content.includes("@tailwindcss/postcss") || content.includes("tailwindcss")) {
182
+ spinner.succeed(`PostCSS already configured (${existingPostcss})`);
183
+ } else {
184
+ spinner.warn(
185
+ `${existingPostcss} exists but has no Tailwind plugin \u2014 add '@tailwindcss/postcss' manually`
186
+ );
187
+ }
188
+ }
189
+ spinner.start("Setting up global CSS");
190
+ const globalsAbsPath = import_path2.default.join(cwd, answers.globalsPath);
191
+ await import_fs_extra2.default.ensureDir(import_path2.default.dirname(globalsAbsPath));
192
+ let css = import_fs_extra2.default.existsSync(globalsAbsPath) ? await import_fs_extra2.default.readFile(globalsAbsPath, "utf-8") : "";
193
+ const prepend = [];
194
+ if (!css.includes('@import "tailwindcss"') && !css.includes("@import 'tailwindcss'")) {
195
+ prepend.push('@import "tailwindcss";');
196
+ }
197
+ if (!css.includes("@tokiui/ui/styles.css")) {
198
+ prepend.push('@import "@tokiui/ui/styles.css";');
199
+ }
200
+ if (prepend.length > 0) {
201
+ css = prepend.join("\n") + "\n\n" + css;
202
+ await import_fs_extra2.default.writeFile(globalsAbsPath, css);
203
+ spinner.succeed(`globals.css updated (${answers.globalsPath})`);
204
+ } else {
205
+ spinner.succeed("globals.css already configured");
206
+ }
207
+ spinner.start("Checking TypeScript path aliases");
208
+ const tsconfigPath = import_path2.default.join(cwd, "tsconfig.json");
209
+ if (import_fs_extra2.default.existsSync(tsconfigPath)) {
210
+ const tsconfig = await import_fs_extra2.default.readJson(tsconfigPath);
211
+ const co = tsconfig.compilerOptions ?? {};
212
+ const paths = co.paths ?? {};
213
+ if (!paths["@/*"]) {
214
+ tsconfig.compilerOptions = {
215
+ ...co,
216
+ baseUrl: ".",
217
+ paths: { ...paths, "@/*": [hasSrc ? "./src/*" : "./*"] }
218
+ };
219
+ await import_fs_extra2.default.writeJson(tsconfigPath, tsconfig, { spaces: 2 });
220
+ spinner.succeed(`tsconfig.json \u2014 added "@/*": ["${hasSrc ? "./src/*" : "./*"}"]`);
221
+ } else {
222
+ spinner.succeed("tsconfig.json already has @/* paths");
223
+ }
224
+ } else {
225
+ spinner.warn("No tsconfig.json found \u2014 skipping path alias setup");
94
226
  }
95
227
  writeConfig(cwd, {
96
228
  componentsDir: answers.componentsDir,
97
229
  libDir: answers.libDir,
230
+ libAlias,
98
231
  style: "default"
99
232
  });
100
- spinner.succeed("Project initialized");
101
- console.log(import_kleur.default.green("\n\u2713 tokiui initialized successfully"));
102
- console.log(import_kleur.default.dim("\nNext: run `npx tokiui add <component>` to add components\n"));
233
+ console.log(import_kleur.default.green("\n \u2713 tokiui initialized\n"));
234
+ console.log(` ${import_kleur.default.bold("Add your first component:")}
235
+ `);
236
+ console.log(` ${import_kleur.default.cyan("npx tokiui add button")}
237
+ `);
238
+ if (!isNext) {
239
+ console.log(
240
+ import_kleur.default.dim(
241
+ " Tip: make sure your framework imports globals.css so the\n Tailwind and tokiui styles are loaded.\n"
242
+ )
243
+ );
244
+ }
103
245
  });
104
246
 
105
247
  // src/commands/add.ts
@@ -109,7 +251,7 @@ var import_fs_extra3 = __toESM(require("fs-extra"));
109
251
  var import_prompts2 = __toESM(require("prompts"));
110
252
  var import_kleur2 = __toESM(require("kleur"));
111
253
  var import_ora2 = __toESM(require("ora"));
112
- var import_execa = require("execa");
254
+ var import_execa2 = require("execa");
113
255
 
114
256
  // src/utils/registry.ts
115
257
  var REGISTRY_BASE = "https://raw.githubusercontent.com/TopherGacad/tokiui/main/packages/registry";
@@ -146,6 +288,7 @@ var addCommand = new import_commander2.Command("add").description("Add a compone
146
288
  );
147
289
  process.exit(1);
148
290
  }
291
+ const libAlias = config.libAlias ?? `@/${config.libDir}`;
149
292
  let componentName = componentArg;
150
293
  if (!componentName) {
151
294
  const spinner = (0, import_ora2.default)("Fetching component list...").start();
@@ -166,24 +309,24 @@ var addCommand = new import_commander2.Command("add").description("Add a compone
166
309
  process.exit(0);
167
310
  }
168
311
  for (const name of answer.components) {
169
- await installComponent(name, cwd, config.componentsDir, config.libDir);
312
+ await installComponent(name, cwd, config.componentsDir, libAlias);
170
313
  }
171
314
  return;
172
315
  }
173
- await installComponent(componentName, cwd, config.componentsDir, config.libDir);
316
+ await installComponent(componentName, cwd, config.componentsDir, libAlias);
174
317
  });
175
- async function installComponent(name, cwd, componentsDir, libDir) {
318
+ async function installComponent(name, cwd, componentsDir, libAlias) {
176
319
  const spinner = (0, import_ora2.default)(`Adding ${name}...`).start();
177
320
  const meta = await fetchComponent(name).catch(() => {
178
321
  spinner.fail(`Component "${name}" not found`);
179
322
  process.exit(1);
180
323
  });
181
324
  for (const dep of meta.registryDependencies) {
182
- await installComponent(dep, cwd, componentsDir, libDir);
325
+ await installComponent(dep, cwd, componentsDir, libAlias);
183
326
  }
184
327
  for (const file of meta.files) {
185
328
  const source = await fetchComponentSource(name, file);
186
- const transformed = transformImports(source, `@/${libDir}`);
329
+ const transformed = transformImports(source, libAlias);
187
330
  const destPath = import_path3.default.join(cwd, componentsDir, import_path3.default.basename(file));
188
331
  if (import_fs_extra3.default.existsSync(destPath)) {
189
332
  spinner.stop();
@@ -205,7 +348,7 @@ async function installComponent(name, cwd, componentsDir, libDir) {
205
348
  if (meta.dependencies.length > 0) {
206
349
  const pm = detectPackageManager(cwd);
207
350
  const installCmd = pm === "npm" ? "install" : "add";
208
- await (0, import_execa.execa)(pm, [installCmd, ...meta.dependencies], { cwd });
351
+ await (0, import_execa2.execa)(pm, [installCmd, ...meta.dependencies], { cwd });
209
352
  }
210
353
  spinner.succeed(`Added ${import_kleur2.default.bold(name)}`);
211
354
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokiui/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI for adding tokiui components to your project",
5
5
  "license": "MIT",
6
6
  "author": "Topher Gacad",
@@ -24,6 +24,11 @@
24
24
  "files": [
25
25
  "dist"
26
26
  ],
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "dev": "tsup --watch",
30
+ "lint": "tsc --noEmit"
31
+ },
27
32
  "dependencies": {
28
33
  "commander": "^12.1.0",
29
34
  "execa": "^9.3.0",
@@ -38,10 +43,5 @@
38
43
  "@types/prompts": "^2.4.9",
39
44
  "tsup": "^8.2.4",
40
45
  "typescript": "^5.5.4"
41
- },
42
- "scripts": {
43
- "build": "tsup",
44
- "dev": "tsup --watch",
45
- "lint": "tsc --noEmit"
46
46
  }
47
- }
47
+ }