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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ripple",
3
- "version": "0.2.1",
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": "catalog:",
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": "catalog:"
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
+ }
@@ -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
- }