@kinetixui/cli 0.11.0 → 0.13.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/dist/index.js +162 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import pc6 from "picocolors";
|
|
6
6
|
|
|
7
7
|
// src/commands/add.ts
|
|
8
8
|
import { existsSync as existsSync4 } from "fs";
|
|
@@ -19,6 +19,7 @@ import { existsSync } from "fs";
|
|
|
19
19
|
import { readFile, writeFile } from "fs/promises";
|
|
20
20
|
import path from "path";
|
|
21
21
|
var CONFIG_FILE = "kinetixui.json";
|
|
22
|
+
var DEFAULT_REGISTRY = "https://kinetixui.com/r";
|
|
22
23
|
var DEFAULT_CONFIG = {
|
|
23
24
|
$schema: "https://kinetixui.com/schema/config.json",
|
|
24
25
|
tailwind: { css: "app/globals.css" },
|
|
@@ -160,6 +161,17 @@ async function fetchRegistryItem(registryUrl, name) {
|
|
|
160
161
|
}
|
|
161
162
|
return await res.json();
|
|
162
163
|
}
|
|
164
|
+
async function fetchComponentSpec(registryUrl, name) {
|
|
165
|
+
const base = assertRegistryUrl(registryUrl).replace(/\/$/, "");
|
|
166
|
+
const specsBase = base.endsWith("/r") ? `${base.slice(0, -2)}/specs` : `${base}/specs`;
|
|
167
|
+
const url = `${specsBase}/${assertComponentName(name)}.json`;
|
|
168
|
+
const res = await fetch(url);
|
|
169
|
+
if (res.status === 404) return null;
|
|
170
|
+
if (!res.ok) {
|
|
171
|
+
throw new Error(`Could not load the component spec for "${name}" (${res.status} at ${url}).`);
|
|
172
|
+
}
|
|
173
|
+
return await res.json();
|
|
174
|
+
}
|
|
163
175
|
async function resolveTree(registryUrl, names) {
|
|
164
176
|
const resolved = /* @__PURE__ */ new Map();
|
|
165
177
|
const queue = [...names];
|
|
@@ -203,15 +215,88 @@ async function add(names, options) {
|
|
|
203
215
|
console.log(pc.green("Done."));
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
// src/commands/
|
|
218
|
+
// src/commands/doctor.ts
|
|
207
219
|
import { existsSync as existsSync5 } from "fs";
|
|
220
|
+
import { readdir } from "fs/promises";
|
|
208
221
|
import path5 from "path";
|
|
209
222
|
import pc2 from "picocolors";
|
|
223
|
+
var ICON = { pass: pc2.green("\u2714"), warn: pc2.yellow("!"), fail: pc2.red("\u2716") };
|
|
224
|
+
function report(level, message) {
|
|
225
|
+
console.log(ICON[level], message);
|
|
226
|
+
return level;
|
|
227
|
+
}
|
|
228
|
+
async function doctor() {
|
|
229
|
+
const cwd = process.cwd();
|
|
230
|
+
const levels = [];
|
|
231
|
+
let config = null;
|
|
232
|
+
if (!existsSync5(path5.join(cwd, CONFIG_FILE))) {
|
|
233
|
+
levels.push(report("fail", `No ${CONFIG_FILE} found \u2014 run "kinetixui init" first.`));
|
|
234
|
+
} else {
|
|
235
|
+
try {
|
|
236
|
+
config = await readConfig(cwd);
|
|
237
|
+
levels.push(report("pass", `${CONFIG_FILE} found and parses.`));
|
|
238
|
+
} catch {
|
|
239
|
+
levels.push(report("fail", `${CONFIG_FILE} exists but isn't valid JSON.`));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (config) {
|
|
243
|
+
for (const alias of ["components", "ui", "lib"]) {
|
|
244
|
+
const dir = resolveAliasDir(cwd, config, alias);
|
|
245
|
+
if (existsSync5(dir)) {
|
|
246
|
+
levels.push(report("pass", `"${alias}" alias resolves to ${path5.relative(cwd, dir) || "."}`));
|
|
247
|
+
} else {
|
|
248
|
+
levels.push(report("warn", `"${alias}" alias points to ${path5.relative(cwd, dir) || "."}, which doesn't exist yet.`));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const cssPath = path5.join(cwd, config.srcDir ? "src" : "", config.tailwind.css);
|
|
252
|
+
if (existsSync5(cssPath)) {
|
|
253
|
+
levels.push(report("pass", `Tailwind CSS file found at ${path5.relative(cwd, cssPath)}`));
|
|
254
|
+
} else {
|
|
255
|
+
levels.push(report("warn", `Tailwind CSS file not found at ${path5.relative(cwd, cssPath)} \u2014 the token contract has nowhere to land.`));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
let registryNames = null;
|
|
259
|
+
try {
|
|
260
|
+
const items = await fetchRegistryIndex(DEFAULT_REGISTRY);
|
|
261
|
+
registryNames = new Set(items.filter((item) => item.type === "registry:ui").map((item) => item.name));
|
|
262
|
+
levels.push(report("pass", `Registry reachable (${DEFAULT_REGISTRY}) \u2014 ${registryNames.size} component(s) listed.`));
|
|
263
|
+
} catch (err) {
|
|
264
|
+
levels.push(report("fail", `Registry unreachable at ${DEFAULT_REGISTRY}: ${err.message}`));
|
|
265
|
+
}
|
|
266
|
+
if (config && registryNames) {
|
|
267
|
+
const uiDir = resolveAliasDir(cwd, config, "ui");
|
|
268
|
+
if (existsSync5(uiDir)) {
|
|
269
|
+
const files = (await readdir(uiDir)).filter((f) => f.endsWith(".tsx"));
|
|
270
|
+
const unknown = files.filter((f) => !registryNames.has(f.replace(/\.tsx$/, "")));
|
|
271
|
+
if (unknown.length === 0) {
|
|
272
|
+
levels.push(report("pass", `Every .tsx file in ${path5.relative(cwd, uiDir)} matches a name in the registry.`));
|
|
273
|
+
} else {
|
|
274
|
+
levels.push(
|
|
275
|
+
report(
|
|
276
|
+
"warn",
|
|
277
|
+
`${unknown.length} file(s) in ${path5.relative(cwd, uiDir)} don't match any current registry name (hand-written, or removed from the registry since you added them): ${unknown.join(", ")}`
|
|
278
|
+
)
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const passed = levels.filter((l) => l === "pass").length;
|
|
284
|
+
const warned = levels.filter((l) => l === "warn").length;
|
|
285
|
+
const failed = levels.filter((l) => l === "fail").length;
|
|
286
|
+
console.log();
|
|
287
|
+
console.log(`${passed} passed, ${warned} warned, ${failed} failed`);
|
|
288
|
+
if (failed > 0) process.exitCode = 1;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/commands/init.ts
|
|
292
|
+
import { existsSync as existsSync6 } from "fs";
|
|
293
|
+
import path6 from "path";
|
|
294
|
+
import pc3 from "picocolors";
|
|
210
295
|
import prompts from "prompts";
|
|
211
296
|
async function init(options) {
|
|
212
297
|
const cwd = process.cwd();
|
|
213
|
-
const configPath =
|
|
214
|
-
if (
|
|
298
|
+
const configPath = path6.join(cwd, CONFIG_FILE);
|
|
299
|
+
if (existsSync6(configPath) && !options.yes) {
|
|
215
300
|
const { proceed } = await prompts({
|
|
216
301
|
type: "confirm",
|
|
217
302
|
name: "proceed",
|
|
@@ -223,7 +308,7 @@ async function init(options) {
|
|
|
223
308
|
return;
|
|
224
309
|
}
|
|
225
310
|
}
|
|
226
|
-
const srcDirDetected =
|
|
311
|
+
const srcDirDetected = existsSync6(path6.join(cwd, "src"));
|
|
227
312
|
const answers = options.yes ? {
|
|
228
313
|
srcDir: srcDirDetected,
|
|
229
314
|
css: DEFAULT_CONFIG.tailwind.css,
|
|
@@ -273,38 +358,80 @@ async function init(options) {
|
|
|
273
358
|
}
|
|
274
359
|
};
|
|
275
360
|
await writeConfig(cwd, config);
|
|
276
|
-
console.log(
|
|
361
|
+
console.log(pc3.green("\u2714"), `Created ${CONFIG_FILE}`);
|
|
277
362
|
const items = await resolveTree(options.registry, ["tokens"]);
|
|
278
363
|
const { written, skipped } = await writeItems(cwd, config, items.values(), false);
|
|
279
|
-
for (const file of written) console.log(
|
|
364
|
+
for (const file of written) console.log(pc3.green("\u2714"), `Wrote ${file}`);
|
|
280
365
|
for (const file of skipped) {
|
|
281
|
-
console.log(
|
|
366
|
+
console.log(pc3.yellow("!"), `${file} already exists \u2014 merge the token contract in by hand, or delete it and re-run init.`);
|
|
367
|
+
}
|
|
368
|
+
console.log();
|
|
369
|
+
console.log(`Next: ${pc3.cyan("npx @kinetixui/cli add button")}`);
|
|
370
|
+
console.log(`See everything: ${pc3.cyan("npx @kinetixui/cli list")}`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/commands/inspect.ts
|
|
374
|
+
import { existsSync as existsSync7 } from "fs";
|
|
375
|
+
import path7 from "path";
|
|
376
|
+
import pc4 from "picocolors";
|
|
377
|
+
async function inspect(name, options) {
|
|
378
|
+
const item = await fetchRegistryItem(options.registry, name);
|
|
379
|
+
console.log(`${pc4.bold(item.title ?? item.name)} ${pc4.dim(`(${item.name})`)}`);
|
|
380
|
+
if (item.description) console.log(item.description);
|
|
381
|
+
console.log();
|
|
382
|
+
console.log(`${pc4.dim("Type")} ${item.type}`);
|
|
383
|
+
const cwd = process.cwd();
|
|
384
|
+
const config = await readConfig(cwd);
|
|
385
|
+
if (config) {
|
|
386
|
+
const uiDir = resolveAliasDir(cwd, config, "ui");
|
|
387
|
+
const installed = item.files.some(
|
|
388
|
+
(file) => file.type === "registry:ui" && existsSync7(path7.join(uiDir, path7.basename(file.target)))
|
|
389
|
+
);
|
|
390
|
+
console.log(`${pc4.dim("Installed")} ${installed ? pc4.green("yes") : pc4.yellow("no")}`);
|
|
391
|
+
}
|
|
392
|
+
console.log(
|
|
393
|
+
`${pc4.dim("Depends on")} ${item.dependencies?.length ? item.dependencies.join(", ") : pc4.dim("(none)")}`
|
|
394
|
+
);
|
|
395
|
+
console.log(
|
|
396
|
+
`${pc4.dim("Registry")} ${item.registryDependencies?.length ? item.registryDependencies.join(", ") : pc4.dim("(none)")}`
|
|
397
|
+
);
|
|
398
|
+
console.log();
|
|
399
|
+
console.log(pc4.dim("Files:"));
|
|
400
|
+
for (const file of item.files) {
|
|
401
|
+
console.log(` ${file.path} ${pc4.dim("\u2192")} ${file.target}`);
|
|
402
|
+
}
|
|
403
|
+
const spec = await fetchComponentSpec(options.registry, name);
|
|
404
|
+
if (spec) {
|
|
405
|
+
console.log();
|
|
406
|
+
console.log(pc4.dim("Variants:"));
|
|
407
|
+
for (const [axis, options_] of Object.entries(spec.variants)) {
|
|
408
|
+
console.log(` ${pc4.dim(axis)} ${options_.join(", ")}`);
|
|
409
|
+
}
|
|
282
410
|
}
|
|
283
411
|
console.log();
|
|
284
|
-
console.log(`
|
|
285
|
-
console.log(`See everything: ${pc2.cyan("npx @kinetixui/cli list")}`);
|
|
412
|
+
console.log(`Add it: ${pc4.cyan(`npx @kinetixui/cli add ${item.name}`)}`);
|
|
286
413
|
}
|
|
287
414
|
|
|
288
415
|
// src/commands/list.ts
|
|
289
|
-
import
|
|
416
|
+
import pc5 from "picocolors";
|
|
290
417
|
async function list(options) {
|
|
291
418
|
const items = await fetchRegistryIndex(options.registry);
|
|
292
419
|
const components = items.filter((item) => item.type === "registry:ui").sort((a, b) => a.name.localeCompare(b.name));
|
|
293
420
|
console.log(`${components.length} component(s):`);
|
|
294
421
|
console.log();
|
|
295
422
|
for (const item of components) {
|
|
296
|
-
const description = item.description ?
|
|
297
|
-
console.log(` ${
|
|
423
|
+
const description = item.description ? pc5.dim(` \u2014 ${item.description}`) : "";
|
|
424
|
+
console.log(` ${pc5.cyan(item.name)}${description}`);
|
|
298
425
|
}
|
|
299
426
|
console.log();
|
|
300
|
-
console.log(`Add one: ${
|
|
301
|
-
console.log(`Add everything: ${
|
|
427
|
+
console.log(`Add one: ${pc5.cyan("npx @kinetixui/cli add <name>")}`);
|
|
428
|
+
console.log(`Add everything: ${pc5.cyan("npx @kinetixui/cli add --all")}`);
|
|
302
429
|
}
|
|
303
430
|
|
|
304
431
|
// package.json
|
|
305
432
|
var package_default = {
|
|
306
433
|
name: "@kinetixui/cli",
|
|
307
|
-
version: "0.
|
|
434
|
+
version: "0.13.0",
|
|
308
435
|
description: "Add KinetixUI components and tokens to your project.",
|
|
309
436
|
type: "module",
|
|
310
437
|
license: "MIT",
|
|
@@ -342,14 +469,13 @@ var package_default = {
|
|
|
342
469
|
};
|
|
343
470
|
|
|
344
471
|
// src/index.ts
|
|
345
|
-
var DEFAULT_REGISTRY = "https://kinetixui.com/r";
|
|
346
472
|
var program = new Command();
|
|
347
473
|
program.name("kinetixui").description("Add KinetixUI components and tokens to your project.").version(package_default.version);
|
|
348
474
|
program.command("init").description("Set up kinetixui.json and pull in the token contract.").option("-y, --yes", "skip prompts and use defaults", false).option("-r, --registry <url>", "registry base URL", DEFAULT_REGISTRY).action(async (opts) => {
|
|
349
475
|
try {
|
|
350
476
|
await init({ registry: opts.registry, yes: opts.yes });
|
|
351
477
|
} catch (err) {
|
|
352
|
-
console.error(
|
|
478
|
+
console.error(pc6.red("\u2716"), err.message);
|
|
353
479
|
process.exitCode = 1;
|
|
354
480
|
}
|
|
355
481
|
});
|
|
@@ -357,7 +483,7 @@ program.command("add").description("Add one or more components to your project."
|
|
|
357
483
|
try {
|
|
358
484
|
await add(components, { registry: opts.registry, overwrite: opts.overwrite, all: opts.all });
|
|
359
485
|
} catch (err) {
|
|
360
|
-
console.error(
|
|
486
|
+
console.error(pc6.red("\u2716"), err.message);
|
|
361
487
|
process.exitCode = 1;
|
|
362
488
|
}
|
|
363
489
|
});
|
|
@@ -365,7 +491,23 @@ program.command("list").description("List every component available in the regis
|
|
|
365
491
|
try {
|
|
366
492
|
await list({ registry: opts.registry });
|
|
367
493
|
} catch (err) {
|
|
368
|
-
console.error(
|
|
494
|
+
console.error(pc6.red("\u2716"), err.message);
|
|
495
|
+
process.exitCode = 1;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
program.command("inspect").description("Show everything the registry knows about one component.").argument("<name>", "component name, e.g. button").option("-r, --registry <url>", "registry base URL", DEFAULT_REGISTRY).action(async (name, opts) => {
|
|
499
|
+
try {
|
|
500
|
+
await inspect(name, { registry: opts.registry });
|
|
501
|
+
} catch (err) {
|
|
502
|
+
console.error(pc6.red("\u2716"), err.message);
|
|
503
|
+
process.exitCode = 1;
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
program.command("doctor").description("Check kinetixui.json, its aliases, and the registry connection.").action(async () => {
|
|
507
|
+
try {
|
|
508
|
+
await doctor();
|
|
509
|
+
} catch (err) {
|
|
510
|
+
console.error(pc6.red("\u2716"), err.message);
|
|
369
511
|
process.exitCode = 1;
|
|
370
512
|
}
|
|
371
513
|
});
|