materialme-cli 0.0.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.
@@ -0,0 +1 @@
1
+ export declare function addCommand(componentName?: string): Promise<void>;
@@ -0,0 +1,100 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import prompts from "prompts";
4
+ import { fetchRegistryIndex, fetchComponent, getRegistryDependencies } from "../registry/index.js";
5
+ const CONFIG_FILE = "components.json";
6
+ export async function addCommand(componentName) {
7
+ const projectRoot = process.cwd();
8
+ const configPath = path.join(projectRoot, CONFIG_FILE);
9
+ // Load config
10
+ if (!await fs.pathExists(configPath)) {
11
+ console.error("Error: components.json not found. Run 'materialme init' first.");
12
+ return;
13
+ }
14
+ const config = await fs.readJSON(configPath);
15
+ // Fetch registry index
16
+ let index;
17
+ try {
18
+ index = await fetchRegistryIndex(config.registry);
19
+ }
20
+ catch (error) {
21
+ console.error(error);
22
+ return;
23
+ }
24
+ // If no component specified, show available components
25
+ if (!componentName) {
26
+ const components = Object.keys(index);
27
+ if (components.length === 0) {
28
+ console.log("No components available in registry.");
29
+ return;
30
+ }
31
+ const response = await prompts({
32
+ type: "multiselect",
33
+ name: "components",
34
+ message: "Which components would you like to add?",
35
+ choices: components.map((name) => ({ title: name, value: name })),
36
+ });
37
+ if (!response.components || response.components.length === 0) {
38
+ return;
39
+ }
40
+ for (const name of response.components) {
41
+ await installComponent(name, index, config, projectRoot);
42
+ }
43
+ }
44
+ else {
45
+ await installComponent(componentName, index, config, projectRoot);
46
+ }
47
+ console.log("\n✓ Done!");
48
+ }
49
+ async function installComponent(name, index, config, projectRoot) {
50
+ const component = await fetchComponent(name, config.registry);
51
+ if (!component) {
52
+ console.error(`Component "${name}" not found in registry.`);
53
+ return;
54
+ }
55
+ console.log(`\nInstalling ${name}...`);
56
+ // Get all registry dependencies
57
+ const deps = getRegistryDependencies(component, index);
58
+ const allComponents = [component, ...deps];
59
+ // Install npm dependencies
60
+ if (component.dependencies && component.dependencies.length > 0) {
61
+ console.log(`Installing npm dependencies: ${component.dependencies.join(", ")}`);
62
+ const { execSync } = await import("child_process");
63
+ try {
64
+ execSync(`npm install ${component.dependencies.join(" ")}`, {
65
+ stdio: "inherit",
66
+ cwd: projectRoot,
67
+ });
68
+ }
69
+ catch (error) {
70
+ console.error("Failed to install dependencies");
71
+ }
72
+ }
73
+ // Create directories and write files
74
+ for (const comp of allComponents) {
75
+ for (const file of comp.files) {
76
+ const targetPath = path.join(projectRoot, file.path);
77
+ const targetDir = path.dirname(targetPath);
78
+ await fs.ensureDir(targetDir);
79
+ if (file.url) {
80
+ // Fetch from URL
81
+ try {
82
+ const response = await fetch(file.url);
83
+ const content = await response.text();
84
+ await fs.writeFile(targetPath, content);
85
+ console.log(` ✓ ${file.path}`);
86
+ }
87
+ catch (error) {
88
+ console.error(` ✗ Failed to fetch ${file.url}`);
89
+ }
90
+ }
91
+ else if (file.content) {
92
+ await fs.writeFile(targetPath, file.content);
93
+ console.log(` ✓ ${file.path}`);
94
+ }
95
+ else {
96
+ console.log(` ⚠ ${file.path} (no content)`);
97
+ }
98
+ }
99
+ }
100
+ }
@@ -0,0 +1 @@
1
+ export declare function initCommand(): Promise<void>;
@@ -0,0 +1,108 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import prompts from "prompts";
4
+ const DEFAULT_CONFIG = {
5
+ style: "default",
6
+ tailwind: {
7
+ config: "tailwind.config.js",
8
+ css: "src/app/globals.css",
9
+ baseColor: "slate",
10
+ },
11
+ aliases: {
12
+ utils: "@/lib/utils",
13
+ components: "@/components",
14
+ lib: "@/lib",
15
+ },
16
+ };
17
+ export async function initCommand() {
18
+ console.log("Initializing materialme components...\n");
19
+ const projectRoot = process.cwd();
20
+ // Check if package.json exists
21
+ const packageJsonPath = path.join(projectRoot, "package.json");
22
+ if (!await fs.pathExists(packageJsonPath)) {
23
+ console.error("Error: package.json not found. Run 'npm init' first.");
24
+ return;
25
+ }
26
+ // Ask for configuration options
27
+ const response = await prompts([
28
+ {
29
+ type: "select",
30
+ name: "style",
31
+ message: "Which style would you like to use?",
32
+ choices: [
33
+ { title: "Default", value: "default" },
34
+ { title: "New York", value: "new-york" },
35
+ ],
36
+ initial: 0,
37
+ },
38
+ {
39
+ type: "text",
40
+ name: "componentsDir",
41
+ message: "Components directory:",
42
+ initial: "components",
43
+ },
44
+ {
45
+ type: "text",
46
+ name: "utilsDir",
47
+ message: "Utils directory:",
48
+ initial: "lib",
49
+ },
50
+ {
51
+ type: "text",
52
+ name: "registryUrl",
53
+ message: "Registry URL (optional):",
54
+ initial: "",
55
+ },
56
+ ]);
57
+ const config = {
58
+ style: response.style || "default",
59
+ tailwind: DEFAULT_CONFIG.tailwind,
60
+ aliases: {
61
+ utils: `@/${response.utilsDir || "lib"}/utils`,
62
+ components: `@/${response.componentsDir || "components"}`,
63
+ lib: `@/${response.utilsDir || "lib"}`,
64
+ },
65
+ registry: response.registryUrl || undefined,
66
+ };
67
+ // Create components.json
68
+ const configPath = path.join(projectRoot, "components.json");
69
+ await fs.writeJSON(configPath, config, { spaces: 2 });
70
+ console.log(`✓ Created components.json`);
71
+ // Create component directories
72
+ const componentsPath = path.join(projectRoot, response.componentsDir || "components");
73
+ const utilsPath = path.join(projectRoot, response.utilsDir || "lib");
74
+ await fs.ensureDir(componentsPath);
75
+ console.log(`✓ Created components directory: ${componentsPath}`);
76
+ await fs.ensureDir(utilsPath);
77
+ console.log(`✓ Created utils directory: ${utilsPath}`);
78
+ // Create utils.ts if it doesn't exist
79
+ const utilsFilePath = path.join(utilsPath, "utils.ts");
80
+ if (!await fs.pathExists(utilsFilePath)) {
81
+ const utilsContent = `import { clsx, type ClassValue } from "clsx"
82
+ import { twMerge } from "tailwind-merge"
83
+
84
+ export function cn(...inputs: ClassValue[]) {
85
+ return twMerge(clsx(...inputs))
86
+ }
87
+ `;
88
+ await fs.writeFile(utilsFilePath, utilsContent);
89
+ console.log(`✓ Created utils.ts`);
90
+ }
91
+ // Install dependencies
92
+ console.log("\nInstalling dependencies...");
93
+ const { execSync } = await import("child_process");
94
+ try {
95
+ execSync("npm install -D tailwind-merge clsx class-variance-authority", {
96
+ stdio: "inherit",
97
+ cwd: projectRoot,
98
+ });
99
+ console.log("✓ Dependencies installed");
100
+ }
101
+ catch (error) {
102
+ console.error("Failed to install dependencies. Please install manually:");
103
+ console.error(" npm install -D tailwind-merge clsx class-variance-authority");
104
+ }
105
+ console.log("\n✓ Initialization complete!");
106
+ console.log("\nYou can now add components with:");
107
+ console.log(" npx materialme add <component-name>");
108
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import { initCommand } from "./commands/init.js";
3
+ import { addCommand } from "./commands/add.js";
4
+ const [, , cmd] = process.argv;
5
+ if (cmd === "init") {
6
+ initCommand();
7
+ }
8
+ else if (cmd === "add") {
9
+ addCommand();
10
+ }
11
+ else {
12
+ console.log("Usage: materialme <init|add>");
13
+ }
@@ -0,0 +1,4 @@
1
+ import { RegistryIndex, RegistryComponent } from "../types.js";
2
+ export declare function fetchRegistryIndex(registryUrl?: string): Promise<RegistryIndex>;
3
+ export declare function fetchComponent(name: string, registryUrl?: string): Promise<RegistryComponent | null>;
4
+ export declare function getRegistryDependencies(component: RegistryComponent, index: RegistryIndex): RegistryComponent[];
@@ -0,0 +1,36 @@
1
+ const DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/vladislavkors/materialme/main/registry.json";
2
+ export async function fetchRegistryIndex(registryUrl) {
3
+ const url = registryUrl || DEFAULT_REGISTRY_URL;
4
+ try {
5
+ const response = await fetch(url);
6
+ if (!response.ok) {
7
+ throw new Error(`Failed to fetch registry from ${url}: ${response.statusText}`);
8
+ }
9
+ const data = await response.json();
10
+ return data;
11
+ }
12
+ catch (error) {
13
+ if (error instanceof Error) {
14
+ throw new Error(`Could not fetch registry index: ${error.message}`);
15
+ }
16
+ throw new Error(`Could not fetch registry index`);
17
+ }
18
+ }
19
+ export async function fetchComponent(name, registryUrl) {
20
+ const index = await fetchRegistryIndex(registryUrl);
21
+ return index[name] || null;
22
+ }
23
+ export function getRegistryDependencies(component, index) {
24
+ const deps = [];
25
+ if (!component.registryDependencies) {
26
+ return deps;
27
+ }
28
+ for (const depName of component.registryDependencies) {
29
+ const dep = index[depName];
30
+ if (dep) {
31
+ deps.push(dep);
32
+ deps.push(...getRegistryDependencies(dep, index));
33
+ }
34
+ }
35
+ return deps;
36
+ }
@@ -0,0 +1,30 @@
1
+ export interface ComponentConfig {
2
+ style: "default" | "new-york";
3
+ tailwind: {
4
+ config: string;
5
+ css: string;
6
+ baseColor: string;
7
+ };
8
+ aliases: {
9
+ utils: string;
10
+ components: string;
11
+ lib: string;
12
+ };
13
+ registry?: string;
14
+ }
15
+ export interface RegistryComponent {
16
+ name: string;
17
+ type: "component" | "hook" | "util" | "style";
18
+ files: RegistryFile[];
19
+ dependencies?: string[];
20
+ registryDependencies?: string[];
21
+ }
22
+ export interface RegistryFile {
23
+ path: string;
24
+ type: "component" | "util" | "style";
25
+ content?: string;
26
+ url?: string;
27
+ }
28
+ export interface RegistryIndex {
29
+ [name: string]: RegistryComponent;
30
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "materialme-cli",
3
+ "version": "0.0.1",
4
+ "description": "Material Me CLI for adding components",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/vladislavkors/materialme.git"
9
+ },
10
+ "bin": {
11
+ "materialme": "dist/index.js"
12
+ },
13
+ "type": "module",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc"
19
+ },
20
+ "dependencies": {
21
+ "fs-extra": "^11.1.1",
22
+ "prompts": "^2.4.2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/fs-extra": "^11.0.4",
26
+ "@types/node": "^20.11.0",
27
+ "@types/prompts": "^2.4.9",
28
+ "typescript": "^5.3.3"
29
+ }
30
+ }