Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli-component/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "once-ui-cli",
"version": "3.1.2",
"version": "3.1.3",
"description": "CLI tool for managing Once UI components",
"type": "module",
"bin": {
Expand Down
33 changes: 5 additions & 28 deletions cli-component/src/commands/init.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,21 @@
import inquirer from 'inquirer';
import { components } from '../utils/components.js';
import { installComponent } from '../utils/installer.js';
import { installSharedResources } from '../utils/installer.js';
import { success, info } from '../utils/logger.js';
import { createSpinner } from '../utils/spinner.js';
import gradient from 'gradient-string';
import boxen from 'boxen';

export async function init() {
const spinner = createSpinner('Preparing component list...');
const spinner = createSpinner('Preparing to install shared resources...');

try {
const answers = await inquirer.prompt([
{
type: 'checkbox',
name: 'components',
message: 'Select components to add:',
choices: components.map(c => ({
name: c,
value: c
})),
pageSize: 20,
loop: false
}
]);

if (answers.components.length === 0) {
info('No components selected');
return;
}

console.log(boxen(
gradient.morning('\n🚀 Adding selected components...\n'),
gradient.morning('\n📦 Installing shared resources...\n'),
{ padding: 1, borderStyle: 'round', borderColor: 'cyan' }
));

for (const component of answers.components) {
await installComponent(component);
}
await installSharedResources();

success('All components added successfully! 🎉');
success('All shared resources installed successfully! 🎉');
} catch (error) {
spinner.fail(`Initialization failed: ${error.message}`);
}
Expand Down
107 changes: 98 additions & 9 deletions cli-component/src/utils/installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,45 @@ async function detectProjectStructure() {
if (await fs.pathExists('./app')) {
return './once-ui/components';
}
// Check for Next.js pages directory structure
if (await fs.pathExists('./pages')) {
return './once-ui/components';
}
// Check for src directory structure
if (await fs.pathExists('./src')) {
return './src/once-ui/components';
if (await fs.pathExists('./src/app')) {
return './src/once-ui/components';
}
if (await fs.pathExists('./src/pages')) {
return './src/once-ui/components';
}
}
// Default to root components directory
return './once-ui/components';
}

async function detectAppStructure() {
// Check for Next.js app directory structure
if (await fs.pathExists('./app')) {
return './app';
}
// Check for Next.js pages directory structure
if (await fs.pathExists('./pages')) {
return './pages';
}
// Check for src directory structure
if (await fs.pathExists('./src')) {
if (await fs.pathExists('./src/app')) {
return './src/app';
}
if (await fs.pathExists('./src/pages')) {
return './src/pages';
}
}
// Default to app directory
return './app';
}

async function installFile(fileName, content, targetDir) {
if (content) {
await fs.writeFile(
Expand All @@ -28,6 +59,33 @@ async function installFile(fileName, content, targetDir) {
return false;
}

async function ensureLayoutImports() {
const appDir = await detectAppStructure();
const layoutPath = path.join(appDir, 'layout.css');

const imports = [
'@import "@/once-ui/styles/index.scss";',
'@import "@/once-ui/tokens/index.scss";'
];

try {
let content = '';
if (await fs.pathExists(layoutPath)) {
content = await fs.readFile(layoutPath, 'utf-8');
}

// Check if imports already exist
const hasImports = imports.every(imp => content.includes(imp));
if (!hasImports) {
// Add imports at the beginning of the file
const newContent = imports.join('\n') + '\n\n' + content;
await fs.writeFile(layoutPath, newContent);
}
} catch (err) {
console.error('Failed to update layout.css:', err.message);
}
}

export async function installComponent(componentName, targetDir = null) {
// Detect project structure if targetDir not provided
if (!targetDir) {
Expand Down Expand Up @@ -73,7 +131,14 @@ export async function installComponent(componentName, targetDir = null) {
await installComponent(dep, targetDir);
}
}
} catch (error) {
throw error;
}
}

// New function to install shared resources
export async function installSharedResources() {
try {
// Install styles and tokens
await installStylesAndTokens();

Expand All @@ -88,6 +153,9 @@ export async function installComponent(componentName, targetDir = null) {

// Install config.js file
await installConfigFile();

// Ensure layout.css has required imports
await ensureLayoutImports();
} catch (error) {
throw error;
}
Expand Down Expand Up @@ -153,23 +221,44 @@ async function fetchUseDebounceContent() {
}
}

async function installConfigFile() {
const resourcesDir = './once-ui/resources';
await fs.ensureDir(resourcesDir);
const configContent = await fetchConfigContent();
await installFile('config.js', configContent, resourcesDir);
}

async function fetchConfigContent() {
const GITHUB_CONFIG_URL = 'https://raw.githubusercontent.com/once-ui-system/nextjs-starter/main/src/once-ui/resources/config.js';
const GITHUB_CONFIG_URL = 'https://raw.githubusercontent.com/once-ui-system/nextjs-starter/main/src/app/resources/config.js';
try {
const response = await axios.get(GITHUB_CONFIG_URL);
return response.data;
} catch (err) {
console.error('Failed to fetch config file:', err.message);
return '';
}
}

async function installConfigFile() {
const appDir = await detectAppStructure();
const resourcesDir = path.join(appDir, 'resources');
const configPath = path.join(resourcesDir, 'config.js');

try {
await fs.ensureDir(resourcesDir);
console.log('Downloading config file...');
const configContent = await fetchConfigContent();

if (configContent) {
const exists = await fs.pathExists(configPath);
if (exists) {
console.log('✓ Config file already exists, updating...');
} else {
console.log('✓ Config file downloaded, installing...');
}
await installFile('config.js', configContent, resourcesDir);
console.log('✓ Config file installed');
} else {
console.error('Failed to install config file: No content received');
}
} catch (err) {
console.error('Failed to install config file:', err.message);
}
}

async function installStylesAndTokens() {
const stylesDir = './once-ui/styles';
const tokensDir = './once-ui/tokens';
Expand Down