create-ripple 0.2.1 → 0.2.2
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/LICENSE +21 -21
- package/README.md +50 -50
- package/dist/index.js +151 -0
- package/package.json +16 -13
- package/src/commands/create.js +0 -151
- package/src/constants.js +0 -17
- package/src/index.js +0 -52
- package/src/lib/project-creator.js +0 -316
- package/src/lib/prompts.js +0 -164
- package/src/lib/templates.js +0 -104
- package/src/lib/validation.js +0 -155
- package/tests/integration/cli.test.js +0 -179
- package/tests/integration/project-creator.test.js +0 -271
- package/tests/unit/prompts.test.js +0 -240
- package/tests/unit/templates.test.js +0 -160
- package/tests/unit/validation.test.js +0 -192
- package/tsdown.config.js +0 -9
- package/vitest.config.js +0 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ripple",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Interactive CLI tool for creating Ripple applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,31 +21,34 @@
|
|
|
21
21
|
"url": "https://github.com/trueadm/ripple/issues"
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://ripplejs.com",
|
|
24
|
+
"files": [
|
|
25
|
+
"./dist/index.js"
|
|
26
|
+
],
|
|
24
27
|
"bin": {
|
|
25
28
|
"create-ripple": "./dist/index.js"
|
|
26
29
|
},
|
|
27
30
|
"engines": {
|
|
28
31
|
"node": ">=18.0.0"
|
|
29
32
|
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"build": "tsdown",
|
|
32
|
-
"test": "vitest run",
|
|
33
|
-
"test:watch": "vitest",
|
|
34
|
-
"test:coverage": "vitest run --coverage",
|
|
35
|
-
"test:ui": "vitest --ui",
|
|
36
|
-
"format": "prettier --write .",
|
|
37
|
-
"format:check": "prettier --check ."
|
|
38
|
-
},
|
|
39
33
|
"devDependencies": {
|
|
40
34
|
"@types/prompts": "^2.4.9",
|
|
41
35
|
"commander": "^12.1.0",
|
|
42
36
|
"degit": "^2.8.4",
|
|
43
|
-
"jsdom": "
|
|
37
|
+
"jsdom": "^26.1.0",
|
|
44
38
|
"kleur": "^4.1.5",
|
|
45
39
|
"ora": "^8.1.0",
|
|
46
40
|
"prettier": "^3.6.2",
|
|
47
41
|
"prompts": "^2.4.2",
|
|
48
42
|
"tsdown": "^0.15.4",
|
|
49
|
-
"vitest": "
|
|
43
|
+
"vitest": "^3.2.4"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsdown",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"test:coverage": "vitest run --coverage",
|
|
50
|
+
"test:ui": "vitest --ui",
|
|
51
|
+
"format": "prettier --write .",
|
|
52
|
+
"format:check": "prettier --check ."
|
|
50
53
|
}
|
|
51
|
-
}
|
|
54
|
+
}
|
package/src/commands/create.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { green, cyan, dim, red } from 'kleur/colors';
|
|
4
|
-
import { validateProjectName } from '../lib/validation.js';
|
|
5
|
-
import { validateTemplate, getTemplateNames } from '../lib/templates.js';
|
|
6
|
-
import {
|
|
7
|
-
promptProjectName,
|
|
8
|
-
promptTemplate,
|
|
9
|
-
promptOverwrite,
|
|
10
|
-
promptPackageManager,
|
|
11
|
-
promptGitInit,
|
|
12
|
-
promptStylingFramework
|
|
13
|
-
} from '../lib/prompts.js';
|
|
14
|
-
import { createProject } from '../lib/project-creator.js';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Create command handler
|
|
18
|
-
* @param {string} projectName - Project name (optional)
|
|
19
|
-
* @param {object} options - Command options
|
|
20
|
-
*/
|
|
21
|
-
export async function createCommand(projectName, options) {
|
|
22
|
-
console.log();
|
|
23
|
-
console.log(cyan('🌊 Welcome to Create Ripple App!'));
|
|
24
|
-
console.log(dim("Let's create a new Ripple application"));
|
|
25
|
-
console.log();
|
|
26
|
-
|
|
27
|
-
// Step 1: Get or validate project name
|
|
28
|
-
if (!projectName) {
|
|
29
|
-
projectName = await promptProjectName();
|
|
30
|
-
} else {
|
|
31
|
-
const validation = validateProjectName(projectName);
|
|
32
|
-
if (!validation.valid) {
|
|
33
|
-
console.error(red(`✖ ${validation.message}`));
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Step 2: Get template
|
|
39
|
-
let template = options.template;
|
|
40
|
-
if (!template) {
|
|
41
|
-
template = await promptTemplate();
|
|
42
|
-
} else {
|
|
43
|
-
// Validate template
|
|
44
|
-
if (!validateTemplate(template)) {
|
|
45
|
-
console.error(red(`✖ Template "${template}" not found`));
|
|
46
|
-
console.error(`Available templates: ${getTemplateNames().join(', ')}`);
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Step 3: Get package manager
|
|
52
|
-
let packageManager = options.packageManager || 'npm';
|
|
53
|
-
if (!options.packageManager && !options.yes) {
|
|
54
|
-
packageManager = await promptPackageManager();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Step 4: Check directory and handle conflicts
|
|
58
|
-
const projectPath = resolve(process.cwd(), projectName);
|
|
59
|
-
if (existsSync(projectPath) && !options.yes) {
|
|
60
|
-
const shouldOverwrite = await promptOverwrite(projectName);
|
|
61
|
-
if (!shouldOverwrite) {
|
|
62
|
-
console.log(red('✖ Operation cancelled'));
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Step 5: Git initialization preference
|
|
68
|
-
let gitInit = true;
|
|
69
|
-
if (!options.git && !options.yes) {
|
|
70
|
-
gitInit = await promptGitInit();
|
|
71
|
-
} else if (options.git === false) {
|
|
72
|
-
gitInit = false;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
let stylingFramework = 'vanilla';
|
|
76
|
-
if (!options.yes) {
|
|
77
|
-
stylingFramework = await promptStylingFramework();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Step 6: Create the project
|
|
81
|
-
console.log();
|
|
82
|
-
console.log(`Creating Ripple app in ${green(projectPath)}...`);
|
|
83
|
-
console.log();
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
await createProject({
|
|
87
|
-
projectName,
|
|
88
|
-
projectPath,
|
|
89
|
-
template,
|
|
90
|
-
packageManager,
|
|
91
|
-
typescript: true,
|
|
92
|
-
gitInit,
|
|
93
|
-
stylingFramework
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
showNextSteps(projectName, packageManager);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.error(red('✖ Failed to create project:'));
|
|
99
|
-
console.error(error.message);
|
|
100
|
-
process.exit(1);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Show next steps to the user
|
|
106
|
-
* @param {string} projectName - The created project name
|
|
107
|
-
* @param {string} packageManager - Package manager used
|
|
108
|
-
*/
|
|
109
|
-
function showNextSteps(projectName, packageManager) {
|
|
110
|
-
const installCommand = getInstallCommand(packageManager);
|
|
111
|
-
const devCommand = getDevCommand(packageManager);
|
|
112
|
-
|
|
113
|
-
console.log();
|
|
114
|
-
console.log(green('🎉 Success! Your Ripple app is ready to go.'));
|
|
115
|
-
console.log();
|
|
116
|
-
console.log('Next steps:');
|
|
117
|
-
console.log(` ${dim('cd')} ${projectName}`);
|
|
118
|
-
console.log(` ${dim(installCommand)}`);
|
|
119
|
-
console.log(` ${dim(devCommand)}`);
|
|
120
|
-
console.log();
|
|
121
|
-
console.log('Happy coding! 🌊');
|
|
122
|
-
console.log();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get install command for package manager
|
|
127
|
-
* @param {string} packageManager - Package manager name
|
|
128
|
-
* @returns {string} - Install command
|
|
129
|
-
*/
|
|
130
|
-
function getInstallCommand(packageManager) {
|
|
131
|
-
const commands = {
|
|
132
|
-
npm: 'npm install',
|
|
133
|
-
yarn: 'yarn install',
|
|
134
|
-
pnpm: 'pnpm install'
|
|
135
|
-
};
|
|
136
|
-
return commands[packageManager] || 'npm install';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get dev command for package manager
|
|
141
|
-
* @param {string} packageManager - Package manager name
|
|
142
|
-
* @returns {string} - Dev command
|
|
143
|
-
*/
|
|
144
|
-
function getDevCommand(packageManager) {
|
|
145
|
-
const commands = {
|
|
146
|
-
npm: 'npm run dev',
|
|
147
|
-
yarn: 'yarn dev',
|
|
148
|
-
pnpm: 'pnpm dev'
|
|
149
|
-
};
|
|
150
|
-
return commands[packageManager] || 'npm run dev';
|
|
151
|
-
}
|
package/src/constants.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Available templates configuration
|
|
3
|
-
*/
|
|
4
|
-
export const TEMPLATES = [
|
|
5
|
-
{
|
|
6
|
-
name: 'basic',
|
|
7
|
-
display: 'Basic Ripple App',
|
|
8
|
-
description: 'A minimal Ripple application with Vite and TypeScript'
|
|
9
|
-
}
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* GitHub repository configuration
|
|
14
|
-
*/
|
|
15
|
-
export const GITHUB_REPO = 'trueadm/ripple';
|
|
16
|
-
export const GITHUB_BRANCH = 'main'; // or whatever the default branch is
|
|
17
|
-
export const GITHUB_TEMPLATES_DIRECTORY = 'templates';
|
package/src/index.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { readFileSync } from 'node:fs';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { dirname, join } from 'node:path';
|
|
7
|
-
import { red } from 'kleur/colors';
|
|
8
|
-
import { createCommand } from './commands/create.js';
|
|
9
|
-
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = dirname(__filename);
|
|
12
|
-
|
|
13
|
-
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
14
|
-
const program = new Command();
|
|
15
|
-
|
|
16
|
-
program
|
|
17
|
-
.name('create-ripple')
|
|
18
|
-
.description('Interactive CLI tool for creating Ripple applications')
|
|
19
|
-
.version(packageJson.version)
|
|
20
|
-
.helpOption('-h, --help', 'Display help for command');
|
|
21
|
-
|
|
22
|
-
program
|
|
23
|
-
.argument('[project-name]', 'Name of the project to create')
|
|
24
|
-
.option('-t, --template <template>', 'Template to use (default: basic)')
|
|
25
|
-
.option('-p, --package-manager <pm>', 'Package manager to use (npm, yarn, pnpm)', 'npm')
|
|
26
|
-
.option('--no-git', 'Skip Git repository initialization')
|
|
27
|
-
.option('-y, --yes', 'Skip all prompts and use defaults')
|
|
28
|
-
.action(async (projectName, options) => {
|
|
29
|
-
try {
|
|
30
|
-
await createCommand(projectName, options);
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error(red('✖ Unexpected error:'));
|
|
33
|
-
console.error(error.message);
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// Handle unhandled promise rejections
|
|
39
|
-
process.on('unhandledRejection', (err) => {
|
|
40
|
-
console.error(red('✖ Unhandled error:'));
|
|
41
|
-
console.error(err);
|
|
42
|
-
process.exit(1);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Handle SIGINT (Ctrl+C)
|
|
46
|
-
process.on('SIGINT', () => {
|
|
47
|
-
console.log();
|
|
48
|
-
console.log(red('✖ Operation cancelled'));
|
|
49
|
-
process.exit(1);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
program.parse();
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import { join } from 'node:path';
|
|
2
|
-
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
3
|
-
import { execSync } from 'node:child_process';
|
|
4
|
-
import { green, dim } from 'kleur/colors';
|
|
5
|
-
import ora from 'ora';
|
|
6
|
-
|
|
7
|
-
import { downloadTemplate, getLocalTemplatePath, isLocalDevelopment } from './templates.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create a new Ripple project
|
|
11
|
-
* @param {object} options - Project creation options
|
|
12
|
-
* @param {string} options.projectName - Name of the project
|
|
13
|
-
* @param {string} options.projectPath - Absolute path where project will be created
|
|
14
|
-
* @param {string} options.template - Template to use
|
|
15
|
-
* @param {string} options.packageManager - Package manager to use
|
|
16
|
-
* @param {boolean} options.gitInit - Whether to initialize Git
|
|
17
|
-
* @param {string} options.stylingFramework - Styling framework to use
|
|
18
|
-
*/
|
|
19
|
-
export async function createProject({
|
|
20
|
-
projectName,
|
|
21
|
-
projectPath,
|
|
22
|
-
template,
|
|
23
|
-
packageManager = 'npm',
|
|
24
|
-
gitInit = true,
|
|
25
|
-
stylingFramework = 'vanilla'
|
|
26
|
-
}) {
|
|
27
|
-
console.log(dim(`Creating project: ${projectName}`));
|
|
28
|
-
console.log(dim(`Template: ${template}`));
|
|
29
|
-
console.log(dim(`Package manager: ${packageManager}`));
|
|
30
|
-
console.log();
|
|
31
|
-
|
|
32
|
-
let templatePath;
|
|
33
|
-
let isTemporary = false;
|
|
34
|
-
|
|
35
|
-
// Step 1: Get or download template
|
|
36
|
-
const spinner1 = ora('Preparing template...').start();
|
|
37
|
-
try {
|
|
38
|
-
if (isLocalDevelopment()) {
|
|
39
|
-
// Use local template for development
|
|
40
|
-
templatePath = getLocalTemplatePath(template);
|
|
41
|
-
if (!existsSync(templatePath)) {
|
|
42
|
-
throw new Error(`Local template "${template}" not found at ${templatePath}`);
|
|
43
|
-
}
|
|
44
|
-
spinner1.succeed('Local template located');
|
|
45
|
-
} else {
|
|
46
|
-
// Download template from GitHub
|
|
47
|
-
spinner1.text = 'Downloading template from GitHub...';
|
|
48
|
-
templatePath = await downloadTemplate(template);
|
|
49
|
-
isTemporary = true;
|
|
50
|
-
spinner1.succeed('Template downloaded');
|
|
51
|
-
}
|
|
52
|
-
} catch (error) {
|
|
53
|
-
spinner1.fail('Failed to prepare template');
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Step 2: Create project directory
|
|
58
|
-
const spinner2 = ora('Creating project directory...').start();
|
|
59
|
-
try {
|
|
60
|
-
mkdirSync(projectPath, { recursive: true });
|
|
61
|
-
spinner2.succeed('Project directory created');
|
|
62
|
-
} catch (error) {
|
|
63
|
-
spinner2.fail('Failed to create project directory');
|
|
64
|
-
if (isTemporary) {
|
|
65
|
-
rmSync(templatePath, { recursive: true, force: true });
|
|
66
|
-
}
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Step 3: Copy template files
|
|
71
|
-
const spinner3 = ora('Copying template files...').start();
|
|
72
|
-
try {
|
|
73
|
-
cpSync(templatePath, projectPath, {
|
|
74
|
-
recursive: true,
|
|
75
|
-
filter: (src) => {
|
|
76
|
-
// Skip node_modules and any lock files from template
|
|
77
|
-
const relativePath = src.replace(templatePath, '');
|
|
78
|
-
return (
|
|
79
|
-
!relativePath.includes('node_modules') &&
|
|
80
|
-
!relativePath.includes('package-lock.json') &&
|
|
81
|
-
!relativePath.includes('yarn.lock') &&
|
|
82
|
-
!relativePath.includes('pnpm-lock.yaml')
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
spinner3.succeed('Template files copied');
|
|
87
|
-
} catch (error) {
|
|
88
|
-
spinner3.fail('Failed to copy template files');
|
|
89
|
-
if (isTemporary) {
|
|
90
|
-
rmSync(templatePath, { recursive: true, force: true });
|
|
91
|
-
}
|
|
92
|
-
throw error;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Step 4: Update package.json
|
|
96
|
-
const spinner4 = ora('Configuring package.json...').start();
|
|
97
|
-
try {
|
|
98
|
-
updatePackageJson(projectPath, projectName, packageManager, stylingFramework);
|
|
99
|
-
spinner4.succeed('Package.json configured');
|
|
100
|
-
} catch (error) {
|
|
101
|
-
spinner4.fail('Failed to configure package.json');
|
|
102
|
-
if (isTemporary) {
|
|
103
|
-
rmSync(templatePath, { recursive: true, force: true });
|
|
104
|
-
}
|
|
105
|
-
throw error;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Step 5: Configure styling
|
|
109
|
-
const spinner5 = ora('Configuring styling framework...').start();
|
|
110
|
-
try {
|
|
111
|
-
configureStyling(projectPath, stylingFramework);
|
|
112
|
-
spinner5.succeed('Styling framework configured');
|
|
113
|
-
} catch (error) {
|
|
114
|
-
spinner5.fail('Failed to configure styling framework');
|
|
115
|
-
if (isTemporary) {
|
|
116
|
-
rmSync(templatePath, { recursive: true, force: true });
|
|
117
|
-
}
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// Step 6: Initialize Git (if requested)
|
|
124
|
-
if (gitInit) {
|
|
125
|
-
const spinner6 = ora('Initializing Git repository...').start();
|
|
126
|
-
try {
|
|
127
|
-
execSync('git init', { cwd: projectPath, stdio: 'ignore' });
|
|
128
|
-
spinner6.succeed('Git repository initialized');
|
|
129
|
-
} catch (error) {
|
|
130
|
-
spinner6.warn('Git initialization failed (optional)');
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Clean up temporary template directory
|
|
135
|
-
if (isTemporary) {
|
|
136
|
-
try {
|
|
137
|
-
rmSync(templatePath, { recursive: true, force: true });
|
|
138
|
-
} catch (error) {
|
|
139
|
-
// Ignore cleanup errors
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
console.log();
|
|
144
|
-
console.log(green('✓ Project created successfully!'));
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Update package.json with project-specific configurations
|
|
149
|
-
* @param {string} projectPath - Path to the project
|
|
150
|
-
* @param {string} projectName - Name of the project
|
|
151
|
-
* @param {string} packageManager - Package manager being used
|
|
152
|
-
* @param {string} stylingFramework - Styling framework being used
|
|
153
|
-
*/
|
|
154
|
-
function updatePackageJson(projectPath, projectName, packageManager, stylingFramework) {
|
|
155
|
-
const packageJsonPath = join(projectPath, 'package.json');
|
|
156
|
-
|
|
157
|
-
if (!existsSync(packageJsonPath)) {
|
|
158
|
-
throw new Error('package.json not found in template');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
162
|
-
|
|
163
|
-
// Update package name
|
|
164
|
-
packageJson.name = projectName;
|
|
165
|
-
|
|
166
|
-
// Remove version if it exists (since this is a new project)
|
|
167
|
-
if (packageJson.version === '0.0.0') {
|
|
168
|
-
packageJson.version = '1.0.0';
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Update description
|
|
172
|
-
packageJson.description = `A Ripple application created with create-ripple`;
|
|
173
|
-
|
|
174
|
-
// Add package manager field if not npm
|
|
175
|
-
if (packageManager !== 'npm') {
|
|
176
|
-
packageJson.packageManager = getPackageManagerVersion(packageManager);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Add styling dependencies
|
|
180
|
-
if (stylingFramework === 'tailwind') {
|
|
181
|
-
packageJson.devDependencies = {
|
|
182
|
-
...packageJson.devDependencies,
|
|
183
|
-
'tailwindcss': '^4.1.12',
|
|
184
|
-
'@tailwindcss/vite': '^4.1.12'
|
|
185
|
-
};
|
|
186
|
-
} else if (stylingFramework === 'bootstrap') {
|
|
187
|
-
packageJson.dependencies = {
|
|
188
|
-
...packageJson.dependencies,
|
|
189
|
-
'bootstrap': '^5.3.0'
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Ensure we're using the latest versions
|
|
194
|
-
updateDependencyVersions(packageJson);
|
|
195
|
-
|
|
196
|
-
// Update scripts based on package manager
|
|
197
|
-
updateScripts(packageJson, packageManager);
|
|
198
|
-
|
|
199
|
-
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function configureStyling(projectPath, stylingFramework) {
|
|
203
|
-
if (stylingFramework === 'tailwind') {
|
|
204
|
-
const tailwindConfig = `import type { Config } from 'tailwindcss';
|
|
205
|
-
export default {
|
|
206
|
-
content: [
|
|
207
|
-
"./index.html",
|
|
208
|
-
"./src/**/*.{ts,ripple}",
|
|
209
|
-
],
|
|
210
|
-
theme: {
|
|
211
|
-
extend: {},
|
|
212
|
-
},
|
|
213
|
-
plugins: []
|
|
214
|
-
} satisfies Config
|
|
215
|
-
`;
|
|
216
|
-
writeFileSync(join(projectPath, 'tailwind.config.ts'), tailwindConfig);
|
|
217
|
-
const mainCss = `@import "tailwindcss";
|
|
218
|
-
@config "./tailwind.config.ts";`;
|
|
219
|
-
writeFileSync(join(projectPath, 'src', 'index.css'), mainCss);
|
|
220
|
-
|
|
221
|
-
const mainTs = readFileSync(join(projectPath, 'src', 'index.ts'), 'utf-8');
|
|
222
|
-
const newMainTs = "import './index.css';\n" + mainTs;
|
|
223
|
-
writeFileSync(join(projectPath, 'src', 'index.ts'), newMainTs);
|
|
224
|
-
|
|
225
|
-
if (existsSync(join(projectPath, 'vite.config.js'))) {
|
|
226
|
-
rmSync(join(projectPath, 'vite.config.js'));
|
|
227
|
-
}
|
|
228
|
-
const viteConfig = `import { defineConfig } from 'vite';
|
|
229
|
-
import { ripple } from 'vite-plugin-ripple';
|
|
230
|
-
import tailwindcss from '@tailwindcss/vite';
|
|
231
|
-
|
|
232
|
-
export default defineConfig({
|
|
233
|
-
plugins: [ripple(), tailwindcss()],
|
|
234
|
-
server: {
|
|
235
|
-
port: 3000
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
`;
|
|
239
|
-
writeFileSync(join(projectPath, 'vite.config.js'), viteConfig);
|
|
240
|
-
|
|
241
|
-
} else if (stylingFramework === 'bootstrap') {
|
|
242
|
-
const mainTs = readFileSync(join(projectPath, 'src', 'index.ts'), 'utf-8');
|
|
243
|
-
const newMainTs = "import 'bootstrap/dist/css/bootstrap.min.css';\n" + mainTs;
|
|
244
|
-
writeFileSync(join(projectPath, 'src', 'index.ts'), newMainTs);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Update dependency versions to latest
|
|
250
|
-
* @param {object} packageJson - Package.json object
|
|
251
|
-
*/
|
|
252
|
-
function updateDependencyVersions(packageJson) {
|
|
253
|
-
// Use the latest versions for Ripple packages
|
|
254
|
-
const latestVersions = {
|
|
255
|
-
ripple: '^0.2.35',
|
|
256
|
-
'vite-plugin-ripple': '^0.2.29',
|
|
257
|
-
'prettier-plugin-ripple': '^0.2.29'
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
// Update dependencies
|
|
261
|
-
if (packageJson.dependencies) {
|
|
262
|
-
for (const [pkg, version] of Object.entries(latestVersions)) {
|
|
263
|
-
if (packageJson.dependencies[pkg]) {
|
|
264
|
-
packageJson.dependencies[pkg] = version;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Update devDependencies
|
|
270
|
-
if (packageJson.devDependencies) {
|
|
271
|
-
for (const [pkg, version] of Object.entries(latestVersions)) {
|
|
272
|
-
if (packageJson.devDependencies[pkg]) {
|
|
273
|
-
packageJson.devDependencies[pkg] = version;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Update scripts based on package manager
|
|
281
|
-
* @param {object} packageJson - Package.json object
|
|
282
|
-
* @param {string} packageManager - Package manager being used
|
|
283
|
-
*/
|
|
284
|
-
function updateScripts(packageJson, packageManager) {
|
|
285
|
-
if (!packageJson.scripts) return;
|
|
286
|
-
|
|
287
|
-
// Add package manager specific scripts
|
|
288
|
-
const pmCommands = {
|
|
289
|
-
npm: 'npm run',
|
|
290
|
-
yarn: 'yarn',
|
|
291
|
-
pnpm: 'pnpm'
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const pm = pmCommands[packageManager] || 'npm run';
|
|
295
|
-
|
|
296
|
-
// Update format scripts to use the correct package manager
|
|
297
|
-
if (packageJson.scripts.format) {
|
|
298
|
-
packageJson.scripts.format = 'prettier --write .';
|
|
299
|
-
}
|
|
300
|
-
if (packageJson.scripts['format:check']) {
|
|
301
|
-
packageJson.scripts['format:check'] = 'prettier --check .';
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Get package manager version string
|
|
307
|
-
* @param {string} packageManager - Package manager name
|
|
308
|
-
* @returns {string} - Package manager with version
|
|
309
|
-
*/
|
|
310
|
-
function getPackageManagerVersion(packageManager) {
|
|
311
|
-
const versions = {
|
|
312
|
-
yarn: 'yarn@4.0.0',
|
|
313
|
-
pnpm: 'pnpm@9.0.0'
|
|
314
|
-
};
|
|
315
|
-
return versions[packageManager] || packageManager;
|
|
316
|
-
}
|