@frontic/ui 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.
- package/README.md +119 -0
- package/dist/bin/frontic-ui.js +373 -0
- package/dist/bin/frontic-ui.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +372 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @frontic/ui
|
|
2
|
+
|
|
3
|
+
CLI for adding Frontic UI components to your Vue project.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Use directly with npx (recommended)
|
|
9
|
+
npx @frontic/ui init
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g @frontic/ui
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### init
|
|
18
|
+
|
|
19
|
+
Initialize Frontic UI in your Vue project:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @frontic/ui init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This will:
|
|
26
|
+
|
|
27
|
+
1. Run `shadcn-vue init` if needed
|
|
28
|
+
2. Configure the Frontic registry
|
|
29
|
+
3. Set up theme colors
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
|
|
33
|
+
- `--yes, -y` - Skip confirmation prompts
|
|
34
|
+
- `--defaults, -d` - Use default configuration
|
|
35
|
+
|
|
36
|
+
### add
|
|
37
|
+
|
|
38
|
+
Add components to your project:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Add single component
|
|
42
|
+
npx @frontic/ui add button
|
|
43
|
+
|
|
44
|
+
# Add multiple components
|
|
45
|
+
npx @frontic/ui add button dialog card
|
|
46
|
+
|
|
47
|
+
# Add all components
|
|
48
|
+
npx @frontic/ui add --all
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
|
|
53
|
+
- `--overwrite, -o` - Overwrite existing files
|
|
54
|
+
- `--all, -a` - Add all available components
|
|
55
|
+
- `--path, -p` - Custom installation path
|
|
56
|
+
|
|
57
|
+
### mcp init
|
|
58
|
+
|
|
59
|
+
Set up MCP (Model Context Protocol) for AI assistants:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx @frontic/ui mcp init
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This creates the MCP configuration for tools like Claude Code, Cursor, or VS Code.
|
|
66
|
+
|
|
67
|
+
Options:
|
|
68
|
+
|
|
69
|
+
- `--client, -c` - Target client (claude, cursor, vscode)
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
After running `init`, your `components.json` will include:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"registries": {
|
|
78
|
+
"frontic": {
|
|
79
|
+
"url": "https://registry.frontic.io/r"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Theme Colors
|
|
86
|
+
|
|
87
|
+
Frontic UI includes additional theme colors:
|
|
88
|
+
|
|
89
|
+
```css
|
|
90
|
+
bg-brand text-brand border-brand
|
|
91
|
+
bg-success text-success border-success
|
|
92
|
+
bg-warning text-warning border-warning
|
|
93
|
+
bg-info text-info border-info
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
These are configured during `init` and can be customized in your CSS.
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Install dependencies
|
|
102
|
+
pnpm install
|
|
103
|
+
|
|
104
|
+
# Build
|
|
105
|
+
pnpm build
|
|
106
|
+
|
|
107
|
+
# Run in development
|
|
108
|
+
pnpm dev
|
|
109
|
+
|
|
110
|
+
# Run tests
|
|
111
|
+
pnpm test
|
|
112
|
+
|
|
113
|
+
# Link globally for local testing
|
|
114
|
+
pnpm link --global
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/init.ts
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import ora from "ora";
|
|
9
|
+
import prompts from "prompts";
|
|
10
|
+
|
|
11
|
+
// src/utils/spawn-shadcn.ts
|
|
12
|
+
import { execa } from "execa";
|
|
13
|
+
async function spawnShadcn(args, options = {}) {
|
|
14
|
+
const { silent = false } = options;
|
|
15
|
+
try {
|
|
16
|
+
await execa("npx", ["shadcn-vue@latest", ...args], {
|
|
17
|
+
stdio: silent ? "pipe" : "inherit",
|
|
18
|
+
shell: true
|
|
19
|
+
});
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (!silent) {
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/utils/config.ts
|
|
28
|
+
import { readFile, writeFile, access } from "fs/promises";
|
|
29
|
+
import { join } from "path";
|
|
30
|
+
|
|
31
|
+
// src/utils/constants.ts
|
|
32
|
+
var FRONTIC_REGISTRY_URL = "https://registry.frontic.io/r";
|
|
33
|
+
var CONFIG_FILE = "components.json";
|
|
34
|
+
|
|
35
|
+
// src/utils/config.ts
|
|
36
|
+
async function configExists() {
|
|
37
|
+
try {
|
|
38
|
+
await access(join(process.cwd(), CONFIG_FILE));
|
|
39
|
+
return true;
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function readConfig() {
|
|
45
|
+
try {
|
|
46
|
+
const content = await readFile(join(process.cwd(), CONFIG_FILE), "utf-8");
|
|
47
|
+
return JSON.parse(content);
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function writeConfig(config) {
|
|
53
|
+
await writeFile(
|
|
54
|
+
join(process.cwd(), CONFIG_FILE),
|
|
55
|
+
JSON.stringify(config, null, 2)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
async function updateConfig(updates) {
|
|
59
|
+
const existing = await readConfig();
|
|
60
|
+
if (!existing) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"components.json not found. Run `npx @frontic/ui init` first."
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const merged = deepMerge(existing, updates);
|
|
66
|
+
await writeConfig(merged);
|
|
67
|
+
}
|
|
68
|
+
async function ensureFronticRegistry() {
|
|
69
|
+
const config = await readConfig();
|
|
70
|
+
if (!config) {
|
|
71
|
+
throw new Error("components.json not found");
|
|
72
|
+
}
|
|
73
|
+
if (config.registries?.frontic?.url === FRONTIC_REGISTRY_URL) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
await updateConfig({
|
|
77
|
+
registries: {
|
|
78
|
+
...config.registries,
|
|
79
|
+
frontic: {
|
|
80
|
+
url: FRONTIC_REGISTRY_URL
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function deepMerge(target, source) {
|
|
86
|
+
const result = { ...target };
|
|
87
|
+
for (const key in source) {
|
|
88
|
+
const sourceValue = source[key];
|
|
89
|
+
const targetValue = target[key];
|
|
90
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
91
|
+
result[key] = deepMerge(
|
|
92
|
+
targetValue,
|
|
93
|
+
sourceValue
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
result[key] = sourceValue;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/commands/init.ts
|
|
103
|
+
function registerInitCommand(program2) {
|
|
104
|
+
program2.command("init").description("Initialize Frontic UI in your Vue project").option("-y, --yes", "Skip confirmation prompts").option("-d, --defaults", "Use default configuration").action(async (options) => {
|
|
105
|
+
await init(options);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async function init(options) {
|
|
109
|
+
console.log();
|
|
110
|
+
console.log(chalk.bold("Frontic UI"));
|
|
111
|
+
console.log(chalk.dim("Initializing your project..."));
|
|
112
|
+
console.log();
|
|
113
|
+
const hasConfig = await configExists();
|
|
114
|
+
if (!hasConfig) {
|
|
115
|
+
console.log(chalk.blue("Running shadcn-vue init..."));
|
|
116
|
+
console.log();
|
|
117
|
+
const args = ["init"];
|
|
118
|
+
if (options.yes) args.push("--yes");
|
|
119
|
+
if (options.defaults) args.push("--defaults");
|
|
120
|
+
await spawnShadcn(args);
|
|
121
|
+
console.log();
|
|
122
|
+
}
|
|
123
|
+
let themeColors = getDefaultThemeColors();
|
|
124
|
+
if (!options.yes && !options.defaults) {
|
|
125
|
+
const response = await prompts([
|
|
126
|
+
{
|
|
127
|
+
type: "confirm",
|
|
128
|
+
name: "customizeColors",
|
|
129
|
+
message: "Would you like to customize theme colors?",
|
|
130
|
+
initial: false
|
|
131
|
+
}
|
|
132
|
+
]);
|
|
133
|
+
if (response.customizeColors) {
|
|
134
|
+
const colorResponse = await prompts([
|
|
135
|
+
{
|
|
136
|
+
type: "text",
|
|
137
|
+
name: "brand",
|
|
138
|
+
message: "Brand color (OKLCH)",
|
|
139
|
+
initial: themeColors.brand
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: "text",
|
|
143
|
+
name: "success",
|
|
144
|
+
message: "Success color (OKLCH)",
|
|
145
|
+
initial: themeColors.success
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: "text",
|
|
149
|
+
name: "warning",
|
|
150
|
+
message: "Warning color (OKLCH)",
|
|
151
|
+
initial: themeColors.warning
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: "text",
|
|
155
|
+
name: "info",
|
|
156
|
+
message: "Info color (OKLCH)",
|
|
157
|
+
initial: themeColors.info
|
|
158
|
+
}
|
|
159
|
+
]);
|
|
160
|
+
themeColors = {
|
|
161
|
+
brand: colorResponse.brand || themeColors.brand,
|
|
162
|
+
success: colorResponse.success || themeColors.success,
|
|
163
|
+
warning: colorResponse.warning || themeColors.warning,
|
|
164
|
+
info: colorResponse.info || themeColors.info
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const spinner = ora("Configuring Frontic registry...").start();
|
|
169
|
+
try {
|
|
170
|
+
await updateConfig({
|
|
171
|
+
registries: {
|
|
172
|
+
frontic: {
|
|
173
|
+
url: FRONTIC_REGISTRY_URL
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
spinner.succeed("Frontic registry configured");
|
|
178
|
+
} catch (error) {
|
|
179
|
+
spinner.fail("Failed to configure registry");
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
const themeSpinner = ora("Installing theme...").start();
|
|
183
|
+
try {
|
|
184
|
+
await spawnShadcn(["add", "theme", "--yes"], { silent: true });
|
|
185
|
+
themeSpinner.succeed("Theme installed");
|
|
186
|
+
} catch {
|
|
187
|
+
themeSpinner.warn("Theme installation skipped (may already exist)");
|
|
188
|
+
}
|
|
189
|
+
console.log();
|
|
190
|
+
console.log(chalk.green("\u2713 Frontic UI initialized successfully!"));
|
|
191
|
+
console.log();
|
|
192
|
+
console.log("Next steps:");
|
|
193
|
+
console.log(chalk.dim(" 1. Add components:"));
|
|
194
|
+
console.log(` ${chalk.cyan("npx @frontic/ui add button")}`);
|
|
195
|
+
console.log();
|
|
196
|
+
console.log(chalk.dim(" 2. Set up MCP for AI assistants (optional):"));
|
|
197
|
+
console.log(` ${chalk.cyan("npx @frontic/ui mcp init")}`);
|
|
198
|
+
console.log();
|
|
199
|
+
}
|
|
200
|
+
function getDefaultThemeColors() {
|
|
201
|
+
return {
|
|
202
|
+
brand: "oklch(58% 0.25 265)",
|
|
203
|
+
success: "oklch(55% 0.2 145)",
|
|
204
|
+
warning: "oklch(75% 0.18 85)",
|
|
205
|
+
info: "oklch(60% 0.2 230)"
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/commands/add.ts
|
|
210
|
+
import chalk2 from "chalk";
|
|
211
|
+
import ora2 from "ora";
|
|
212
|
+
function registerAddCommand(program2) {
|
|
213
|
+
program2.command("add").description("Add components to your project").argument("[components...]", "Components to add").option("-o, --overwrite", "Overwrite existing files").option("-a, --all", "Add all available components").option("-p, --path <path>", "Custom installation path").option("-y, --yes", "Skip confirmation prompts").action(async (components, options) => {
|
|
214
|
+
await add(components, options);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
async function add(components, options) {
|
|
218
|
+
if (!options.all && components.length === 0) {
|
|
219
|
+
console.log(chalk2.red("Error: Please specify components to add or use --all"));
|
|
220
|
+
console.log();
|
|
221
|
+
console.log("Usage:");
|
|
222
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add button")}`);
|
|
223
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add button dialog card")}`);
|
|
224
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add --all")}`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
const spinner = ora2("Checking configuration...").start();
|
|
228
|
+
try {
|
|
229
|
+
await ensureFronticRegistry();
|
|
230
|
+
spinner.succeed("Configuration verified");
|
|
231
|
+
} catch {
|
|
232
|
+
spinner.fail("Configuration error");
|
|
233
|
+
console.log();
|
|
234
|
+
console.log(chalk2.yellow("Run `npx @frontic/ui init` first to set up your project."));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
const args = ["add"];
|
|
238
|
+
if (options.all) {
|
|
239
|
+
args.push("--all");
|
|
240
|
+
} else {
|
|
241
|
+
args.push(...components);
|
|
242
|
+
}
|
|
243
|
+
if (options.overwrite) {
|
|
244
|
+
args.push("--overwrite");
|
|
245
|
+
}
|
|
246
|
+
if (options.path) {
|
|
247
|
+
args.push("--path", options.path);
|
|
248
|
+
}
|
|
249
|
+
if (options.yes) {
|
|
250
|
+
args.push("--yes");
|
|
251
|
+
}
|
|
252
|
+
console.log();
|
|
253
|
+
console.log(chalk2.blue("Adding components..."));
|
|
254
|
+
console.log();
|
|
255
|
+
await spawnShadcn(args);
|
|
256
|
+
console.log();
|
|
257
|
+
console.log(chalk2.green("\u2713 Components added successfully!"));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/commands/mcp.ts
|
|
261
|
+
import chalk3 from "chalk";
|
|
262
|
+
import ora3 from "ora";
|
|
263
|
+
import { writeFile as writeFile2, readFile as readFile2, mkdir } from "fs/promises";
|
|
264
|
+
import { existsSync } from "fs";
|
|
265
|
+
import { join as join2 } from "path";
|
|
266
|
+
import prompts2 from "prompts";
|
|
267
|
+
function registerMcpCommand(program2) {
|
|
268
|
+
const mcp = program2.command("mcp").description("MCP (Model Context Protocol) commands");
|
|
269
|
+
mcp.command("init").description("Set up MCP for AI assistants").option("-c, --client <client>", "Target client (claude, cursor, vscode)").action(async (options) => {
|
|
270
|
+
await initMcp(options);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async function initMcp(options) {
|
|
274
|
+
console.log();
|
|
275
|
+
console.log(chalk3.bold("Frontic UI - MCP Setup"));
|
|
276
|
+
console.log(chalk3.dim("Configure AI assistant integration"));
|
|
277
|
+
console.log();
|
|
278
|
+
let client = options.client;
|
|
279
|
+
if (!client) {
|
|
280
|
+
const response = await prompts2({
|
|
281
|
+
type: "select",
|
|
282
|
+
name: "client",
|
|
283
|
+
message: "Select your AI client:",
|
|
284
|
+
choices: [
|
|
285
|
+
{ title: "Claude Code", value: "claude" },
|
|
286
|
+
{ title: "Cursor", value: "cursor" },
|
|
287
|
+
{ title: "VS Code", value: "vscode" }
|
|
288
|
+
]
|
|
289
|
+
});
|
|
290
|
+
client = response.client;
|
|
291
|
+
if (!client) {
|
|
292
|
+
console.log(chalk3.yellow("Setup cancelled."));
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const spinner = ora3("Creating MCP configuration...").start();
|
|
297
|
+
try {
|
|
298
|
+
await createMcpConfig(client);
|
|
299
|
+
spinner.succeed("MCP configuration created");
|
|
300
|
+
} catch (error) {
|
|
301
|
+
spinner.fail("Failed to create MCP configuration");
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
console.log();
|
|
305
|
+
console.log(chalk3.green("\u2713 MCP configured successfully!"));
|
|
306
|
+
console.log();
|
|
307
|
+
console.log("Your AI assistant can now:");
|
|
308
|
+
console.log(chalk3.dim(" \u2022 Browse available Frontic UI components"));
|
|
309
|
+
console.log(chalk3.dim(" \u2022 Add components using natural language"));
|
|
310
|
+
console.log(chalk3.dim(' \u2022 Example: "Add a button component"'));
|
|
311
|
+
console.log();
|
|
312
|
+
}
|
|
313
|
+
async function createMcpConfig(client) {
|
|
314
|
+
const config = getMcpConfig();
|
|
315
|
+
const configPath = getMcpConfigPath(client);
|
|
316
|
+
const configDir = join2(process.cwd(), configPath.split("/").slice(0, -1).join("/"));
|
|
317
|
+
if (!existsSync(configDir)) {
|
|
318
|
+
await mkdir(configDir, { recursive: true });
|
|
319
|
+
}
|
|
320
|
+
const fullPath = join2(process.cwd(), configPath);
|
|
321
|
+
let existingConfig = {};
|
|
322
|
+
try {
|
|
323
|
+
const content = await readFile2(fullPath, "utf-8");
|
|
324
|
+
existingConfig = JSON.parse(content);
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
const mergedConfig = {
|
|
328
|
+
...existingConfig,
|
|
329
|
+
mcpServers: {
|
|
330
|
+
...existingConfig.mcpServers || {},
|
|
331
|
+
...config.mcpServers
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
await writeFile2(fullPath, JSON.stringify(mergedConfig, null, 2));
|
|
335
|
+
console.log(chalk3.dim(` Config written to: ${configPath}`));
|
|
336
|
+
}
|
|
337
|
+
function getMcpConfigPath(client) {
|
|
338
|
+
switch (client) {
|
|
339
|
+
case "claude":
|
|
340
|
+
return ".mcp.json";
|
|
341
|
+
case "cursor":
|
|
342
|
+
return ".cursor/mcp.json";
|
|
343
|
+
case "vscode":
|
|
344
|
+
return ".vscode/mcp.json";
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function getMcpConfig() {
|
|
348
|
+
return {
|
|
349
|
+
mcpServers: {
|
|
350
|
+
"frontic-ui": {
|
|
351
|
+
command: "npx",
|
|
352
|
+
args: ["shadcn-vue@latest", "mcp"],
|
|
353
|
+
env: {
|
|
354
|
+
SHADCN_REGISTRY_URL: FRONTIC_REGISTRY_URL
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/index.ts
|
|
362
|
+
var program = new Command();
|
|
363
|
+
program.name("frontic-ui").description("CLI for adding Frontic UI components to your Vue project").version("0.0.1");
|
|
364
|
+
registerInitCommand(program);
|
|
365
|
+
registerAddCommand(program);
|
|
366
|
+
registerMcpCommand(program);
|
|
367
|
+
function run() {
|
|
368
|
+
program.parse();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// bin/frontic-ui.ts
|
|
372
|
+
run();
|
|
373
|
+
//# sourceMappingURL=frontic-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/commands/init.ts","../../src/utils/spawn-shadcn.ts","../../src/utils/config.ts","../../src/utils/constants.ts","../../src/commands/add.ts","../../src/commands/mcp.ts","../../bin/frontic-ui.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerAddCommand } from \"./commands/add.js\";\nimport { registerMcpCommand } from \"./commands/mcp.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"frontic-ui\")\n .description(\"CLI for adding Frontic UI components to your Vue project\")\n .version(\"0.0.1\");\n\nregisterInitCommand(program);\nregisterAddCommand(program);\nregisterMcpCommand(program);\n\nexport function run() {\n program.parse();\n}\n\nexport { program };\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport prompts from \"prompts\";\nimport { spawnShadcn } from \"../utils/spawn-shadcn.js\";\nimport { updateConfig, configExists } from \"../utils/config.js\";\nimport { FRONTIC_REGISTRY_URL } from \"../utils/constants.js\";\n\ninterface InitOptions {\n yes?: boolean;\n defaults?: boolean;\n}\n\nexport function registerInitCommand(program: Command) {\n program\n .command(\"init\")\n .description(\"Initialize Frontic UI in your Vue project\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"-d, --defaults\", \"Use default configuration\")\n .action(async (options: InitOptions) => {\n await init(options);\n });\n}\n\nasync function init(options: InitOptions) {\n console.log();\n console.log(chalk.bold(\"Frontic UI\"));\n console.log(chalk.dim(\"Initializing your project...\"));\n console.log();\n\n const hasConfig = await configExists();\n\n // Run shadcn-vue init if no config exists\n if (!hasConfig) {\n console.log(chalk.blue(\"Running shadcn-vue init...\"));\n console.log();\n\n const args = [\"init\"];\n if (options.yes) args.push(\"--yes\");\n if (options.defaults) args.push(\"--defaults\");\n\n await spawnShadcn(args);\n console.log();\n }\n\n // Prompt for theme colors (unless skipped)\n let themeColors = getDefaultThemeColors();\n\n if (!options.yes && !options.defaults) {\n const response = await prompts([\n {\n type: \"confirm\",\n name: \"customizeColors\",\n message: \"Would you like to customize theme colors?\",\n initial: false,\n },\n ]);\n\n if (response.customizeColors) {\n const colorResponse = await prompts([\n {\n type: \"text\",\n name: \"brand\",\n message: \"Brand color (OKLCH)\",\n initial: themeColors.brand,\n },\n {\n type: \"text\",\n name: \"success\",\n message: \"Success color (OKLCH)\",\n initial: themeColors.success,\n },\n {\n type: \"text\",\n name: \"warning\",\n message: \"Warning color (OKLCH)\",\n initial: themeColors.warning,\n },\n {\n type: \"text\",\n name: \"info\",\n message: \"Info color (OKLCH)\",\n initial: themeColors.info,\n },\n ]);\n\n themeColors = {\n brand: colorResponse.brand || themeColors.brand,\n success: colorResponse.success || themeColors.success,\n warning: colorResponse.warning || themeColors.warning,\n info: colorResponse.info || themeColors.info,\n };\n }\n }\n\n // Update components.json with Frontic registry\n const spinner = ora(\"Configuring Frontic registry...\").start();\n\n try {\n await updateConfig({\n registries: {\n frontic: {\n url: FRONTIC_REGISTRY_URL,\n },\n },\n });\n spinner.succeed(\"Frontic registry configured\");\n } catch (error) {\n spinner.fail(\"Failed to configure registry\");\n throw error;\n }\n\n // Install theme\n const themeSpinner = ora(\"Installing theme...\").start();\n try {\n await spawnShadcn([\"add\", \"theme\", \"--yes\"], { silent: true });\n themeSpinner.succeed(\"Theme installed\");\n } catch {\n themeSpinner.warn(\"Theme installation skipped (may already exist)\");\n }\n\n console.log();\n console.log(chalk.green(\"✓ Frontic UI initialized successfully!\"));\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1. Add components:\"));\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button\")}`);\n console.log();\n console.log(chalk.dim(\" 2. Set up MCP for AI assistants (optional):\"));\n console.log(` ${chalk.cyan(\"npx @frontic/ui mcp init\")}`);\n console.log();\n}\n\nfunction getDefaultThemeColors() {\n return {\n brand: \"oklch(58% 0.25 265)\",\n success: \"oklch(55% 0.2 145)\",\n warning: \"oklch(75% 0.18 85)\",\n info: \"oklch(60% 0.2 230)\",\n };\n}\n","import { execa } from \"execa\";\n\ninterface SpawnOptions {\n silent?: boolean;\n}\n\nexport async function spawnShadcn(\n args: string[],\n options: SpawnOptions = {}\n): Promise<void> {\n const { silent = false } = options;\n\n try {\n await execa(\"npx\", [\"shadcn-vue@latest\", ...args], {\n stdio: silent ? \"pipe\" : \"inherit\",\n shell: true,\n });\n } catch (error) {\n if (!silent) {\n throw error;\n }\n // Silently ignore errors when silent mode is enabled\n }\n}\n","import { readFile, writeFile, access } from \"fs/promises\";\nimport { join } from \"path\";\nimport { CONFIG_FILE, FRONTIC_REGISTRY_URL } from \"./constants.js\";\n\nexport interface ComponentsConfig {\n $schema?: string;\n style?: string;\n typescript?: boolean;\n tailwind?: {\n css?: string;\n baseColor?: string;\n cssVariables?: boolean;\n };\n aliases?: {\n components?: string;\n utils?: string;\n ui?: string;\n lib?: string;\n composables?: string;\n };\n registries?: {\n [key: string]: {\n url: string;\n };\n };\n}\n\nexport async function configExists(): Promise<boolean> {\n try {\n await access(join(process.cwd(), CONFIG_FILE));\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readConfig(): Promise<ComponentsConfig | null> {\n try {\n const content = await readFile(join(process.cwd(), CONFIG_FILE), \"utf-8\");\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(config: ComponentsConfig): Promise<void> {\n await writeFile(\n join(process.cwd(), CONFIG_FILE),\n JSON.stringify(config, null, 2)\n );\n}\n\nexport async function updateConfig(\n updates: Partial<ComponentsConfig>\n): Promise<void> {\n const existing = await readConfig();\n\n if (!existing) {\n throw new Error(\n \"components.json not found. Run `npx @frontic/ui init` first.\"\n );\n }\n\n const merged = deepMerge(existing, updates);\n await writeConfig(merged);\n}\n\nexport async function ensureFronticRegistry(): Promise<void> {\n const config = await readConfig();\n\n if (!config) {\n throw new Error(\"components.json not found\");\n }\n\n // Check if Frontic registry is already configured\n if (config.registries?.frontic?.url === FRONTIC_REGISTRY_URL) {\n return;\n }\n\n // Add Frontic registry\n await updateConfig({\n registries: {\n ...config.registries,\n frontic: {\n url: FRONTIC_REGISTRY_URL,\n },\n },\n });\n}\n\nfunction deepMerge<T extends object>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === \"object\" &&\n !Array.isArray(targetValue)\n ) {\n (result as Record<string, unknown>)[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>\n );\n } else {\n (result as Record<string, unknown>)[key] = sourceValue;\n }\n }\n\n return result;\n}\n","export const FRONTIC_REGISTRY_URL = \"https://registry.frontic.io/r\";\n\nexport const CONFIG_FILE = \"components.json\";\n\nexport const DEFAULT_THEME_COLORS = {\n brand: \"oklch(58% 0.25 265)\",\n \"brand-foreground\": \"oklch(100% 0 0)\",\n success: \"oklch(55% 0.2 145)\",\n \"success-foreground\": \"oklch(100% 0 0)\",\n warning: \"oklch(75% 0.18 85)\",\n \"warning-foreground\": \"oklch(20% 0 0)\",\n info: \"oklch(60% 0.2 230)\",\n \"info-foreground\": \"oklch(100% 0 0)\",\n};\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { spawnShadcn } from \"../utils/spawn-shadcn.js\";\nimport { ensureFronticRegistry } from \"../utils/config.js\";\n\ninterface AddOptions {\n overwrite?: boolean;\n all?: boolean;\n path?: string;\n yes?: boolean;\n}\n\nexport function registerAddCommand(program: Command) {\n program\n .command(\"add\")\n .description(\"Add components to your project\")\n .argument(\"[components...]\", \"Components to add\")\n .option(\"-o, --overwrite\", \"Overwrite existing files\")\n .option(\"-a, --all\", \"Add all available components\")\n .option(\"-p, --path <path>\", \"Custom installation path\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .action(async (components: string[], options: AddOptions) => {\n await add(components, options);\n });\n}\n\nasync function add(components: string[], options: AddOptions) {\n // Validate input\n if (!options.all && components.length === 0) {\n console.log(chalk.red(\"Error: Please specify components to add or use --all\"));\n console.log();\n console.log(\"Usage:\");\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button\")}`);\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button dialog card\")}`);\n console.log(` ${chalk.cyan(\"npx @frontic/ui add --all\")}`);\n process.exit(1);\n }\n\n // Ensure Frontic registry is configured\n const spinner = ora(\"Checking configuration...\").start();\n try {\n await ensureFronticRegistry();\n spinner.succeed(\"Configuration verified\");\n } catch {\n spinner.fail(\"Configuration error\");\n console.log();\n console.log(chalk.yellow(\"Run `npx @frontic/ui init` first to set up your project.\"));\n process.exit(1);\n }\n\n // Build shadcn-vue arguments\n const args = [\"add\"];\n\n if (options.all) {\n args.push(\"--all\");\n } else {\n args.push(...components);\n }\n\n if (options.overwrite) {\n args.push(\"--overwrite\");\n }\n\n if (options.path) {\n args.push(\"--path\", options.path);\n }\n\n if (options.yes) {\n args.push(\"--yes\");\n }\n\n console.log();\n console.log(chalk.blue(\"Adding components...\"));\n console.log();\n\n // Run shadcn-vue add\n await spawnShadcn(args);\n\n console.log();\n console.log(chalk.green(\"✓ Components added successfully!\"));\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { writeFile, readFile, mkdir } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport prompts from \"prompts\";\nimport { FRONTIC_REGISTRY_URL } from \"../utils/constants.js\";\n\ntype McpClient = \"claude\" | \"cursor\" | \"vscode\";\n\ninterface McpInitOptions {\n client?: McpClient;\n}\n\nexport function registerMcpCommand(program: Command) {\n const mcp = program\n .command(\"mcp\")\n .description(\"MCP (Model Context Protocol) commands\");\n\n mcp\n .command(\"init\")\n .description(\"Set up MCP for AI assistants\")\n .option(\"-c, --client <client>\", \"Target client (claude, cursor, vscode)\")\n .action(async (options: McpInitOptions) => {\n await initMcp(options);\n });\n}\n\nasync function initMcp(options: McpInitOptions) {\n console.log();\n console.log(chalk.bold(\"Frontic UI - MCP Setup\"));\n console.log(chalk.dim(\"Configure AI assistant integration\"));\n console.log();\n\n let client = options.client as McpClient | undefined;\n\n // Prompt for client if not specified\n if (!client) {\n const response = await prompts({\n type: \"select\",\n name: \"client\",\n message: \"Select your AI client:\",\n choices: [\n { title: \"Claude Code\", value: \"claude\" },\n { title: \"Cursor\", value: \"cursor\" },\n { title: \"VS Code\", value: \"vscode\" },\n ],\n });\n\n client = response.client;\n\n if (!client) {\n console.log(chalk.yellow(\"Setup cancelled.\"));\n return;\n }\n }\n\n const spinner = ora(\"Creating MCP configuration...\").start();\n\n try {\n await createMcpConfig(client);\n spinner.succeed(\"MCP configuration created\");\n } catch (error) {\n spinner.fail(\"Failed to create MCP configuration\");\n throw error;\n }\n\n console.log();\n console.log(chalk.green(\"✓ MCP configured successfully!\"));\n console.log();\n console.log(\"Your AI assistant can now:\");\n console.log(chalk.dim(\" • Browse available Frontic UI components\"));\n console.log(chalk.dim(\" • Add components using natural language\"));\n console.log(chalk.dim(' • Example: \"Add a button component\"'));\n console.log();\n}\n\nasync function createMcpConfig(client: McpClient) {\n const config = getMcpConfig();\n const configPath = getMcpConfigPath(client);\n const configDir = join(process.cwd(), configPath.split(\"/\").slice(0, -1).join(\"/\"));\n\n // Create directory if needed\n if (!existsSync(configDir)) {\n await mkdir(configDir, { recursive: true });\n }\n\n const fullPath = join(process.cwd(), configPath);\n\n // Read existing config or create new\n let existingConfig: Record<string, unknown> = {};\n try {\n const content = await readFile(fullPath, \"utf-8\");\n existingConfig = JSON.parse(content);\n } catch {\n // File doesn't exist, use empty config\n }\n\n // Merge with existing config\n const mergedConfig = {\n ...existingConfig,\n mcpServers: {\n ...(existingConfig.mcpServers as Record<string, unknown> || {}),\n ...config.mcpServers,\n },\n };\n\n await writeFile(fullPath, JSON.stringify(mergedConfig, null, 2));\n\n console.log(chalk.dim(` Config written to: ${configPath}`));\n}\n\nfunction getMcpConfigPath(client: McpClient): string {\n switch (client) {\n case \"claude\":\n return \".mcp.json\";\n case \"cursor\":\n return \".cursor/mcp.json\";\n case \"vscode\":\n return \".vscode/mcp.json\";\n }\n}\n\nfunction getMcpConfig() {\n return {\n mcpServers: {\n \"frontic-ui\": {\n command: \"npx\",\n args: [\"shadcn-vue@latest\", \"mcp\"],\n env: {\n SHADCN_REGISTRY_URL: FRONTIC_REGISTRY_URL,\n },\n },\n },\n };\n}\n","#!/usr/bin/env node\nimport { run } from '../src/index.js'\n\nrun()\n"],"mappings":"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","names":["program","chalk","ora","program","chalk","ora","chalk","ora","writeFile","readFile","join","prompts","program","chalk","prompts","ora","join","readFile","writeFile"]}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
// src/commands/init.ts
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import ora from "ora";
|
|
7
|
+
import prompts from "prompts";
|
|
8
|
+
|
|
9
|
+
// src/utils/spawn-shadcn.ts
|
|
10
|
+
import { execa } from "execa";
|
|
11
|
+
async function spawnShadcn(args, options = {}) {
|
|
12
|
+
const { silent = false } = options;
|
|
13
|
+
try {
|
|
14
|
+
await execa("npx", ["shadcn-vue@latest", ...args], {
|
|
15
|
+
stdio: silent ? "pipe" : "inherit",
|
|
16
|
+
shell: true
|
|
17
|
+
});
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (!silent) {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/utils/config.ts
|
|
26
|
+
import { readFile, writeFile, access } from "fs/promises";
|
|
27
|
+
import { join } from "path";
|
|
28
|
+
|
|
29
|
+
// src/utils/constants.ts
|
|
30
|
+
var FRONTIC_REGISTRY_URL = "https://registry.frontic.io/r";
|
|
31
|
+
var CONFIG_FILE = "components.json";
|
|
32
|
+
|
|
33
|
+
// src/utils/config.ts
|
|
34
|
+
async function configExists() {
|
|
35
|
+
try {
|
|
36
|
+
await access(join(process.cwd(), CONFIG_FILE));
|
|
37
|
+
return true;
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function readConfig() {
|
|
43
|
+
try {
|
|
44
|
+
const content = await readFile(join(process.cwd(), CONFIG_FILE), "utf-8");
|
|
45
|
+
return JSON.parse(content);
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function writeConfig(config) {
|
|
51
|
+
await writeFile(
|
|
52
|
+
join(process.cwd(), CONFIG_FILE),
|
|
53
|
+
JSON.stringify(config, null, 2)
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
async function updateConfig(updates) {
|
|
57
|
+
const existing = await readConfig();
|
|
58
|
+
if (!existing) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"components.json not found. Run `npx @frontic/ui init` first."
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const merged = deepMerge(existing, updates);
|
|
64
|
+
await writeConfig(merged);
|
|
65
|
+
}
|
|
66
|
+
async function ensureFronticRegistry() {
|
|
67
|
+
const config = await readConfig();
|
|
68
|
+
if (!config) {
|
|
69
|
+
throw new Error("components.json not found");
|
|
70
|
+
}
|
|
71
|
+
if (config.registries?.frontic?.url === FRONTIC_REGISTRY_URL) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await updateConfig({
|
|
75
|
+
registries: {
|
|
76
|
+
...config.registries,
|
|
77
|
+
frontic: {
|
|
78
|
+
url: FRONTIC_REGISTRY_URL
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function deepMerge(target, source) {
|
|
84
|
+
const result = { ...target };
|
|
85
|
+
for (const key in source) {
|
|
86
|
+
const sourceValue = source[key];
|
|
87
|
+
const targetValue = target[key];
|
|
88
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
89
|
+
result[key] = deepMerge(
|
|
90
|
+
targetValue,
|
|
91
|
+
sourceValue
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
result[key] = sourceValue;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/commands/init.ts
|
|
101
|
+
function registerInitCommand(program2) {
|
|
102
|
+
program2.command("init").description("Initialize Frontic UI in your Vue project").option("-y, --yes", "Skip confirmation prompts").option("-d, --defaults", "Use default configuration").action(async (options) => {
|
|
103
|
+
await init(options);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function init(options) {
|
|
107
|
+
console.log();
|
|
108
|
+
console.log(chalk.bold("Frontic UI"));
|
|
109
|
+
console.log(chalk.dim("Initializing your project..."));
|
|
110
|
+
console.log();
|
|
111
|
+
const hasConfig = await configExists();
|
|
112
|
+
if (!hasConfig) {
|
|
113
|
+
console.log(chalk.blue("Running shadcn-vue init..."));
|
|
114
|
+
console.log();
|
|
115
|
+
const args = ["init"];
|
|
116
|
+
if (options.yes) args.push("--yes");
|
|
117
|
+
if (options.defaults) args.push("--defaults");
|
|
118
|
+
await spawnShadcn(args);
|
|
119
|
+
console.log();
|
|
120
|
+
}
|
|
121
|
+
let themeColors = getDefaultThemeColors();
|
|
122
|
+
if (!options.yes && !options.defaults) {
|
|
123
|
+
const response = await prompts([
|
|
124
|
+
{
|
|
125
|
+
type: "confirm",
|
|
126
|
+
name: "customizeColors",
|
|
127
|
+
message: "Would you like to customize theme colors?",
|
|
128
|
+
initial: false
|
|
129
|
+
}
|
|
130
|
+
]);
|
|
131
|
+
if (response.customizeColors) {
|
|
132
|
+
const colorResponse = await prompts([
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
name: "brand",
|
|
136
|
+
message: "Brand color (OKLCH)",
|
|
137
|
+
initial: themeColors.brand
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: "text",
|
|
141
|
+
name: "success",
|
|
142
|
+
message: "Success color (OKLCH)",
|
|
143
|
+
initial: themeColors.success
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: "text",
|
|
147
|
+
name: "warning",
|
|
148
|
+
message: "Warning color (OKLCH)",
|
|
149
|
+
initial: themeColors.warning
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: "text",
|
|
153
|
+
name: "info",
|
|
154
|
+
message: "Info color (OKLCH)",
|
|
155
|
+
initial: themeColors.info
|
|
156
|
+
}
|
|
157
|
+
]);
|
|
158
|
+
themeColors = {
|
|
159
|
+
brand: colorResponse.brand || themeColors.brand,
|
|
160
|
+
success: colorResponse.success || themeColors.success,
|
|
161
|
+
warning: colorResponse.warning || themeColors.warning,
|
|
162
|
+
info: colorResponse.info || themeColors.info
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const spinner = ora("Configuring Frontic registry...").start();
|
|
167
|
+
try {
|
|
168
|
+
await updateConfig({
|
|
169
|
+
registries: {
|
|
170
|
+
frontic: {
|
|
171
|
+
url: FRONTIC_REGISTRY_URL
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
spinner.succeed("Frontic registry configured");
|
|
176
|
+
} catch (error) {
|
|
177
|
+
spinner.fail("Failed to configure registry");
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
const themeSpinner = ora("Installing theme...").start();
|
|
181
|
+
try {
|
|
182
|
+
await spawnShadcn(["add", "theme", "--yes"], { silent: true });
|
|
183
|
+
themeSpinner.succeed("Theme installed");
|
|
184
|
+
} catch {
|
|
185
|
+
themeSpinner.warn("Theme installation skipped (may already exist)");
|
|
186
|
+
}
|
|
187
|
+
console.log();
|
|
188
|
+
console.log(chalk.green("\u2713 Frontic UI initialized successfully!"));
|
|
189
|
+
console.log();
|
|
190
|
+
console.log("Next steps:");
|
|
191
|
+
console.log(chalk.dim(" 1. Add components:"));
|
|
192
|
+
console.log(` ${chalk.cyan("npx @frontic/ui add button")}`);
|
|
193
|
+
console.log();
|
|
194
|
+
console.log(chalk.dim(" 2. Set up MCP for AI assistants (optional):"));
|
|
195
|
+
console.log(` ${chalk.cyan("npx @frontic/ui mcp init")}`);
|
|
196
|
+
console.log();
|
|
197
|
+
}
|
|
198
|
+
function getDefaultThemeColors() {
|
|
199
|
+
return {
|
|
200
|
+
brand: "oklch(58% 0.25 265)",
|
|
201
|
+
success: "oklch(55% 0.2 145)",
|
|
202
|
+
warning: "oklch(75% 0.18 85)",
|
|
203
|
+
info: "oklch(60% 0.2 230)"
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/commands/add.ts
|
|
208
|
+
import chalk2 from "chalk";
|
|
209
|
+
import ora2 from "ora";
|
|
210
|
+
function registerAddCommand(program2) {
|
|
211
|
+
program2.command("add").description("Add components to your project").argument("[components...]", "Components to add").option("-o, --overwrite", "Overwrite existing files").option("-a, --all", "Add all available components").option("-p, --path <path>", "Custom installation path").option("-y, --yes", "Skip confirmation prompts").action(async (components, options) => {
|
|
212
|
+
await add(components, options);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
async function add(components, options) {
|
|
216
|
+
if (!options.all && components.length === 0) {
|
|
217
|
+
console.log(chalk2.red("Error: Please specify components to add or use --all"));
|
|
218
|
+
console.log();
|
|
219
|
+
console.log("Usage:");
|
|
220
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add button")}`);
|
|
221
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add button dialog card")}`);
|
|
222
|
+
console.log(` ${chalk2.cyan("npx @frontic/ui add --all")}`);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
const spinner = ora2("Checking configuration...").start();
|
|
226
|
+
try {
|
|
227
|
+
await ensureFronticRegistry();
|
|
228
|
+
spinner.succeed("Configuration verified");
|
|
229
|
+
} catch {
|
|
230
|
+
spinner.fail("Configuration error");
|
|
231
|
+
console.log();
|
|
232
|
+
console.log(chalk2.yellow("Run `npx @frontic/ui init` first to set up your project."));
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
const args = ["add"];
|
|
236
|
+
if (options.all) {
|
|
237
|
+
args.push("--all");
|
|
238
|
+
} else {
|
|
239
|
+
args.push(...components);
|
|
240
|
+
}
|
|
241
|
+
if (options.overwrite) {
|
|
242
|
+
args.push("--overwrite");
|
|
243
|
+
}
|
|
244
|
+
if (options.path) {
|
|
245
|
+
args.push("--path", options.path);
|
|
246
|
+
}
|
|
247
|
+
if (options.yes) {
|
|
248
|
+
args.push("--yes");
|
|
249
|
+
}
|
|
250
|
+
console.log();
|
|
251
|
+
console.log(chalk2.blue("Adding components..."));
|
|
252
|
+
console.log();
|
|
253
|
+
await spawnShadcn(args);
|
|
254
|
+
console.log();
|
|
255
|
+
console.log(chalk2.green("\u2713 Components added successfully!"));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/commands/mcp.ts
|
|
259
|
+
import chalk3 from "chalk";
|
|
260
|
+
import ora3 from "ora";
|
|
261
|
+
import { writeFile as writeFile2, readFile as readFile2, mkdir } from "fs/promises";
|
|
262
|
+
import { existsSync } from "fs";
|
|
263
|
+
import { join as join2 } from "path";
|
|
264
|
+
import prompts2 from "prompts";
|
|
265
|
+
function registerMcpCommand(program2) {
|
|
266
|
+
const mcp = program2.command("mcp").description("MCP (Model Context Protocol) commands");
|
|
267
|
+
mcp.command("init").description("Set up MCP for AI assistants").option("-c, --client <client>", "Target client (claude, cursor, vscode)").action(async (options) => {
|
|
268
|
+
await initMcp(options);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
async function initMcp(options) {
|
|
272
|
+
console.log();
|
|
273
|
+
console.log(chalk3.bold("Frontic UI - MCP Setup"));
|
|
274
|
+
console.log(chalk3.dim("Configure AI assistant integration"));
|
|
275
|
+
console.log();
|
|
276
|
+
let client = options.client;
|
|
277
|
+
if (!client) {
|
|
278
|
+
const response = await prompts2({
|
|
279
|
+
type: "select",
|
|
280
|
+
name: "client",
|
|
281
|
+
message: "Select your AI client:",
|
|
282
|
+
choices: [
|
|
283
|
+
{ title: "Claude Code", value: "claude" },
|
|
284
|
+
{ title: "Cursor", value: "cursor" },
|
|
285
|
+
{ title: "VS Code", value: "vscode" }
|
|
286
|
+
]
|
|
287
|
+
});
|
|
288
|
+
client = response.client;
|
|
289
|
+
if (!client) {
|
|
290
|
+
console.log(chalk3.yellow("Setup cancelled."));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const spinner = ora3("Creating MCP configuration...").start();
|
|
295
|
+
try {
|
|
296
|
+
await createMcpConfig(client);
|
|
297
|
+
spinner.succeed("MCP configuration created");
|
|
298
|
+
} catch (error) {
|
|
299
|
+
spinner.fail("Failed to create MCP configuration");
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
console.log();
|
|
303
|
+
console.log(chalk3.green("\u2713 MCP configured successfully!"));
|
|
304
|
+
console.log();
|
|
305
|
+
console.log("Your AI assistant can now:");
|
|
306
|
+
console.log(chalk3.dim(" \u2022 Browse available Frontic UI components"));
|
|
307
|
+
console.log(chalk3.dim(" \u2022 Add components using natural language"));
|
|
308
|
+
console.log(chalk3.dim(' \u2022 Example: "Add a button component"'));
|
|
309
|
+
console.log();
|
|
310
|
+
}
|
|
311
|
+
async function createMcpConfig(client) {
|
|
312
|
+
const config = getMcpConfig();
|
|
313
|
+
const configPath = getMcpConfigPath(client);
|
|
314
|
+
const configDir = join2(process.cwd(), configPath.split("/").slice(0, -1).join("/"));
|
|
315
|
+
if (!existsSync(configDir)) {
|
|
316
|
+
await mkdir(configDir, { recursive: true });
|
|
317
|
+
}
|
|
318
|
+
const fullPath = join2(process.cwd(), configPath);
|
|
319
|
+
let existingConfig = {};
|
|
320
|
+
try {
|
|
321
|
+
const content = await readFile2(fullPath, "utf-8");
|
|
322
|
+
existingConfig = JSON.parse(content);
|
|
323
|
+
} catch {
|
|
324
|
+
}
|
|
325
|
+
const mergedConfig = {
|
|
326
|
+
...existingConfig,
|
|
327
|
+
mcpServers: {
|
|
328
|
+
...existingConfig.mcpServers || {},
|
|
329
|
+
...config.mcpServers
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
await writeFile2(fullPath, JSON.stringify(mergedConfig, null, 2));
|
|
333
|
+
console.log(chalk3.dim(` Config written to: ${configPath}`));
|
|
334
|
+
}
|
|
335
|
+
function getMcpConfigPath(client) {
|
|
336
|
+
switch (client) {
|
|
337
|
+
case "claude":
|
|
338
|
+
return ".mcp.json";
|
|
339
|
+
case "cursor":
|
|
340
|
+
return ".cursor/mcp.json";
|
|
341
|
+
case "vscode":
|
|
342
|
+
return ".vscode/mcp.json";
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function getMcpConfig() {
|
|
346
|
+
return {
|
|
347
|
+
mcpServers: {
|
|
348
|
+
"frontic-ui": {
|
|
349
|
+
command: "npx",
|
|
350
|
+
args: ["shadcn-vue@latest", "mcp"],
|
|
351
|
+
env: {
|
|
352
|
+
SHADCN_REGISTRY_URL: FRONTIC_REGISTRY_URL
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/index.ts
|
|
360
|
+
var program = new Command();
|
|
361
|
+
program.name("frontic-ui").description("CLI for adding Frontic UI components to your Vue project").version("0.0.1");
|
|
362
|
+
registerInitCommand(program);
|
|
363
|
+
registerAddCommand(program);
|
|
364
|
+
registerMcpCommand(program);
|
|
365
|
+
function run() {
|
|
366
|
+
program.parse();
|
|
367
|
+
}
|
|
368
|
+
export {
|
|
369
|
+
program,
|
|
370
|
+
run
|
|
371
|
+
};
|
|
372
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/spawn-shadcn.ts","../src/utils/config.ts","../src/utils/constants.ts","../src/commands/add.ts","../src/commands/mcp.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerAddCommand } from \"./commands/add.js\";\nimport { registerMcpCommand } from \"./commands/mcp.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"frontic-ui\")\n .description(\"CLI for adding Frontic UI components to your Vue project\")\n .version(\"0.0.1\");\n\nregisterInitCommand(program);\nregisterAddCommand(program);\nregisterMcpCommand(program);\n\nexport function run() {\n program.parse();\n}\n\nexport { program };\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport prompts from \"prompts\";\nimport { spawnShadcn } from \"../utils/spawn-shadcn.js\";\nimport { updateConfig, configExists } from \"../utils/config.js\";\nimport { FRONTIC_REGISTRY_URL } from \"../utils/constants.js\";\n\ninterface InitOptions {\n yes?: boolean;\n defaults?: boolean;\n}\n\nexport function registerInitCommand(program: Command) {\n program\n .command(\"init\")\n .description(\"Initialize Frontic UI in your Vue project\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"-d, --defaults\", \"Use default configuration\")\n .action(async (options: InitOptions) => {\n await init(options);\n });\n}\n\nasync function init(options: InitOptions) {\n console.log();\n console.log(chalk.bold(\"Frontic UI\"));\n console.log(chalk.dim(\"Initializing your project...\"));\n console.log();\n\n const hasConfig = await configExists();\n\n // Run shadcn-vue init if no config exists\n if (!hasConfig) {\n console.log(chalk.blue(\"Running shadcn-vue init...\"));\n console.log();\n\n const args = [\"init\"];\n if (options.yes) args.push(\"--yes\");\n if (options.defaults) args.push(\"--defaults\");\n\n await spawnShadcn(args);\n console.log();\n }\n\n // Prompt for theme colors (unless skipped)\n let themeColors = getDefaultThemeColors();\n\n if (!options.yes && !options.defaults) {\n const response = await prompts([\n {\n type: \"confirm\",\n name: \"customizeColors\",\n message: \"Would you like to customize theme colors?\",\n initial: false,\n },\n ]);\n\n if (response.customizeColors) {\n const colorResponse = await prompts([\n {\n type: \"text\",\n name: \"brand\",\n message: \"Brand color (OKLCH)\",\n initial: themeColors.brand,\n },\n {\n type: \"text\",\n name: \"success\",\n message: \"Success color (OKLCH)\",\n initial: themeColors.success,\n },\n {\n type: \"text\",\n name: \"warning\",\n message: \"Warning color (OKLCH)\",\n initial: themeColors.warning,\n },\n {\n type: \"text\",\n name: \"info\",\n message: \"Info color (OKLCH)\",\n initial: themeColors.info,\n },\n ]);\n\n themeColors = {\n brand: colorResponse.brand || themeColors.brand,\n success: colorResponse.success || themeColors.success,\n warning: colorResponse.warning || themeColors.warning,\n info: colorResponse.info || themeColors.info,\n };\n }\n }\n\n // Update components.json with Frontic registry\n const spinner = ora(\"Configuring Frontic registry...\").start();\n\n try {\n await updateConfig({\n registries: {\n frontic: {\n url: FRONTIC_REGISTRY_URL,\n },\n },\n });\n spinner.succeed(\"Frontic registry configured\");\n } catch (error) {\n spinner.fail(\"Failed to configure registry\");\n throw error;\n }\n\n // Install theme\n const themeSpinner = ora(\"Installing theme...\").start();\n try {\n await spawnShadcn([\"add\", \"theme\", \"--yes\"], { silent: true });\n themeSpinner.succeed(\"Theme installed\");\n } catch {\n themeSpinner.warn(\"Theme installation skipped (may already exist)\");\n }\n\n console.log();\n console.log(chalk.green(\"✓ Frontic UI initialized successfully!\"));\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1. Add components:\"));\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button\")}`);\n console.log();\n console.log(chalk.dim(\" 2. Set up MCP for AI assistants (optional):\"));\n console.log(` ${chalk.cyan(\"npx @frontic/ui mcp init\")}`);\n console.log();\n}\n\nfunction getDefaultThemeColors() {\n return {\n brand: \"oklch(58% 0.25 265)\",\n success: \"oklch(55% 0.2 145)\",\n warning: \"oklch(75% 0.18 85)\",\n info: \"oklch(60% 0.2 230)\",\n };\n}\n","import { execa } from \"execa\";\n\ninterface SpawnOptions {\n silent?: boolean;\n}\n\nexport async function spawnShadcn(\n args: string[],\n options: SpawnOptions = {}\n): Promise<void> {\n const { silent = false } = options;\n\n try {\n await execa(\"npx\", [\"shadcn-vue@latest\", ...args], {\n stdio: silent ? \"pipe\" : \"inherit\",\n shell: true,\n });\n } catch (error) {\n if (!silent) {\n throw error;\n }\n // Silently ignore errors when silent mode is enabled\n }\n}\n","import { readFile, writeFile, access } from \"fs/promises\";\nimport { join } from \"path\";\nimport { CONFIG_FILE, FRONTIC_REGISTRY_URL } from \"./constants.js\";\n\nexport interface ComponentsConfig {\n $schema?: string;\n style?: string;\n typescript?: boolean;\n tailwind?: {\n css?: string;\n baseColor?: string;\n cssVariables?: boolean;\n };\n aliases?: {\n components?: string;\n utils?: string;\n ui?: string;\n lib?: string;\n composables?: string;\n };\n registries?: {\n [key: string]: {\n url: string;\n };\n };\n}\n\nexport async function configExists(): Promise<boolean> {\n try {\n await access(join(process.cwd(), CONFIG_FILE));\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readConfig(): Promise<ComponentsConfig | null> {\n try {\n const content = await readFile(join(process.cwd(), CONFIG_FILE), \"utf-8\");\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(config: ComponentsConfig): Promise<void> {\n await writeFile(\n join(process.cwd(), CONFIG_FILE),\n JSON.stringify(config, null, 2)\n );\n}\n\nexport async function updateConfig(\n updates: Partial<ComponentsConfig>\n): Promise<void> {\n const existing = await readConfig();\n\n if (!existing) {\n throw new Error(\n \"components.json not found. Run `npx @frontic/ui init` first.\"\n );\n }\n\n const merged = deepMerge(existing, updates);\n await writeConfig(merged);\n}\n\nexport async function ensureFronticRegistry(): Promise<void> {\n const config = await readConfig();\n\n if (!config) {\n throw new Error(\"components.json not found\");\n }\n\n // Check if Frontic registry is already configured\n if (config.registries?.frontic?.url === FRONTIC_REGISTRY_URL) {\n return;\n }\n\n // Add Frontic registry\n await updateConfig({\n registries: {\n ...config.registries,\n frontic: {\n url: FRONTIC_REGISTRY_URL,\n },\n },\n });\n}\n\nfunction deepMerge<T extends object>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === \"object\" &&\n !Array.isArray(targetValue)\n ) {\n (result as Record<string, unknown>)[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>\n );\n } else {\n (result as Record<string, unknown>)[key] = sourceValue;\n }\n }\n\n return result;\n}\n","export const FRONTIC_REGISTRY_URL = \"https://registry.frontic.io/r\";\n\nexport const CONFIG_FILE = \"components.json\";\n\nexport const DEFAULT_THEME_COLORS = {\n brand: \"oklch(58% 0.25 265)\",\n \"brand-foreground\": \"oklch(100% 0 0)\",\n success: \"oklch(55% 0.2 145)\",\n \"success-foreground\": \"oklch(100% 0 0)\",\n warning: \"oklch(75% 0.18 85)\",\n \"warning-foreground\": \"oklch(20% 0 0)\",\n info: \"oklch(60% 0.2 230)\",\n \"info-foreground\": \"oklch(100% 0 0)\",\n};\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { spawnShadcn } from \"../utils/spawn-shadcn.js\";\nimport { ensureFronticRegistry } from \"../utils/config.js\";\n\ninterface AddOptions {\n overwrite?: boolean;\n all?: boolean;\n path?: string;\n yes?: boolean;\n}\n\nexport function registerAddCommand(program: Command) {\n program\n .command(\"add\")\n .description(\"Add components to your project\")\n .argument(\"[components...]\", \"Components to add\")\n .option(\"-o, --overwrite\", \"Overwrite existing files\")\n .option(\"-a, --all\", \"Add all available components\")\n .option(\"-p, --path <path>\", \"Custom installation path\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .action(async (components: string[], options: AddOptions) => {\n await add(components, options);\n });\n}\n\nasync function add(components: string[], options: AddOptions) {\n // Validate input\n if (!options.all && components.length === 0) {\n console.log(chalk.red(\"Error: Please specify components to add or use --all\"));\n console.log();\n console.log(\"Usage:\");\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button\")}`);\n console.log(` ${chalk.cyan(\"npx @frontic/ui add button dialog card\")}`);\n console.log(` ${chalk.cyan(\"npx @frontic/ui add --all\")}`);\n process.exit(1);\n }\n\n // Ensure Frontic registry is configured\n const spinner = ora(\"Checking configuration...\").start();\n try {\n await ensureFronticRegistry();\n spinner.succeed(\"Configuration verified\");\n } catch {\n spinner.fail(\"Configuration error\");\n console.log();\n console.log(chalk.yellow(\"Run `npx @frontic/ui init` first to set up your project.\"));\n process.exit(1);\n }\n\n // Build shadcn-vue arguments\n const args = [\"add\"];\n\n if (options.all) {\n args.push(\"--all\");\n } else {\n args.push(...components);\n }\n\n if (options.overwrite) {\n args.push(\"--overwrite\");\n }\n\n if (options.path) {\n args.push(\"--path\", options.path);\n }\n\n if (options.yes) {\n args.push(\"--yes\");\n }\n\n console.log();\n console.log(chalk.blue(\"Adding components...\"));\n console.log();\n\n // Run shadcn-vue add\n await spawnShadcn(args);\n\n console.log();\n console.log(chalk.green(\"✓ Components added successfully!\"));\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { writeFile, readFile, mkdir } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport prompts from \"prompts\";\nimport { FRONTIC_REGISTRY_URL } from \"../utils/constants.js\";\n\ntype McpClient = \"claude\" | \"cursor\" | \"vscode\";\n\ninterface McpInitOptions {\n client?: McpClient;\n}\n\nexport function registerMcpCommand(program: Command) {\n const mcp = program\n .command(\"mcp\")\n .description(\"MCP (Model Context Protocol) commands\");\n\n mcp\n .command(\"init\")\n .description(\"Set up MCP for AI assistants\")\n .option(\"-c, --client <client>\", \"Target client (claude, cursor, vscode)\")\n .action(async (options: McpInitOptions) => {\n await initMcp(options);\n });\n}\n\nasync function initMcp(options: McpInitOptions) {\n console.log();\n console.log(chalk.bold(\"Frontic UI - MCP Setup\"));\n console.log(chalk.dim(\"Configure AI assistant integration\"));\n console.log();\n\n let client = options.client as McpClient | undefined;\n\n // Prompt for client if not specified\n if (!client) {\n const response = await prompts({\n type: \"select\",\n name: \"client\",\n message: \"Select your AI client:\",\n choices: [\n { title: \"Claude Code\", value: \"claude\" },\n { title: \"Cursor\", value: \"cursor\" },\n { title: \"VS Code\", value: \"vscode\" },\n ],\n });\n\n client = response.client;\n\n if (!client) {\n console.log(chalk.yellow(\"Setup cancelled.\"));\n return;\n }\n }\n\n const spinner = ora(\"Creating MCP configuration...\").start();\n\n try {\n await createMcpConfig(client);\n spinner.succeed(\"MCP configuration created\");\n } catch (error) {\n spinner.fail(\"Failed to create MCP configuration\");\n throw error;\n }\n\n console.log();\n console.log(chalk.green(\"✓ MCP configured successfully!\"));\n console.log();\n console.log(\"Your AI assistant can now:\");\n console.log(chalk.dim(\" • Browse available Frontic UI components\"));\n console.log(chalk.dim(\" • Add components using natural language\"));\n console.log(chalk.dim(' • Example: \"Add a button component\"'));\n console.log();\n}\n\nasync function createMcpConfig(client: McpClient) {\n const config = getMcpConfig();\n const configPath = getMcpConfigPath(client);\n const configDir = join(process.cwd(), configPath.split(\"/\").slice(0, -1).join(\"/\"));\n\n // Create directory if needed\n if (!existsSync(configDir)) {\n await mkdir(configDir, { recursive: true });\n }\n\n const fullPath = join(process.cwd(), configPath);\n\n // Read existing config or create new\n let existingConfig: Record<string, unknown> = {};\n try {\n const content = await readFile(fullPath, \"utf-8\");\n existingConfig = JSON.parse(content);\n } catch {\n // File doesn't exist, use empty config\n }\n\n // Merge with existing config\n const mergedConfig = {\n ...existingConfig,\n mcpServers: {\n ...(existingConfig.mcpServers as Record<string, unknown> || {}),\n ...config.mcpServers,\n },\n };\n\n await writeFile(fullPath, JSON.stringify(mergedConfig, null, 2));\n\n console.log(chalk.dim(` Config written to: ${configPath}`));\n}\n\nfunction getMcpConfigPath(client: McpClient): string {\n switch (client) {\n case \"claude\":\n return \".mcp.json\";\n case \"cursor\":\n return \".cursor/mcp.json\";\n case \"vscode\":\n return \".vscode/mcp.json\";\n }\n}\n\nfunction getMcpConfig() {\n return {\n mcpServers: {\n \"frontic-ui\": {\n command: \"npx\",\n args: [\"shadcn-vue@latest\", \"mcp\"],\n env: {\n SHADCN_REGISTRY_URL: FRONTIC_REGISTRY_URL,\n },\n },\n },\n };\n}\n"],"mappings":"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","names":["program","chalk","ora","program","chalk","ora","chalk","ora","writeFile","readFile","join","prompts","program","chalk","prompts","ora","join","readFile","writeFile"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@frontic/ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "CLI for adding Frontic UI components to your Vue project",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"frontic-ui": "dist/bin/frontic-ui.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "tsup --watch",
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:unit": "vitest run tests/unit",
|
|
20
|
+
"test:integration": "vitest run tests/integration",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"clean": "rm -rf dist"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"chalk": "^5.3.0",
|
|
26
|
+
"commander": "^12.1.0",
|
|
27
|
+
"execa": "^9.5.1",
|
|
28
|
+
"ora": "^8.1.1",
|
|
29
|
+
"prompts": "^2.4.2"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/prompts": "^2.4.9",
|
|
33
|
+
"tsup": "^8.3.5",
|
|
34
|
+
"typescript": "^5.7.2",
|
|
35
|
+
"vitest": "^2.1.8"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/frontic/frontic-ui.git",
|
|
43
|
+
"directory": "packages/cli"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"vue",
|
|
47
|
+
"components",
|
|
48
|
+
"ui",
|
|
49
|
+
"shadcn",
|
|
50
|
+
"tailwind",
|
|
51
|
+
"cli"
|
|
52
|
+
],
|
|
53
|
+
"author": "Frontic",
|
|
54
|
+
"license": "MIT"
|
|
55
|
+
}
|