create-letswhim 2.0.4 → 2.0.5
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/index.js +58 -52
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import prompts from 'prompts';
|
|
|
8
8
|
// ==================== CONFIGURATION ====================
|
|
9
9
|
const CONFIG = {
|
|
10
10
|
repoUrl: "https://github.com/ripkiiii/letswhim-starter.git",
|
|
11
|
-
version: "2.0.
|
|
11
|
+
version: "2.0.5",
|
|
12
12
|
colors: {
|
|
13
13
|
primary: pc.cyan,
|
|
14
14
|
secondary: pc.blue,
|
|
@@ -69,7 +69,7 @@ const ASCII = {
|
|
|
69
69
|
` ${pc.cyan(' │• •│ ')}`,
|
|
70
70
|
` ${pc.cyan(' ╰─┬─╯ ')}`,
|
|
71
71
|
` ${pc.cyan(' _/')} ${pc.white('|')} ${pc.cyan('\\_ ')}`,
|
|
72
|
-
` ${pc.blue('~~')} ${pc.white('( )')} ${
|
|
72
|
+
` ${pc.blue('~~')} ${pc.white('( )')} ${pc.white('Catching waves...')}`,
|
|
73
73
|
` ${pc.blue('~~~~~')}${pc.white('/| |\\')}`,
|
|
74
74
|
`${pc.blue('~~~~~~~~~~~')}`,
|
|
75
75
|
`${pc.blue('~~~~~~~~~~~~~~~~~~~~~~')}`
|
|
@@ -81,7 +81,7 @@ const ASCII = {
|
|
|
81
81
|
` ${pc.cyan(' │• •│ 🏄')}`,
|
|
82
82
|
` ${pc.cyan(' ╰─┬─╯ ')}`,
|
|
83
83
|
` ${pc.cyan(' __/')}${pc.white('|')}${pc.cyan('\\__ ')}`,
|
|
84
|
-
` ${pc.blue('~~~')} ${pc.white('( )')} ${
|
|
84
|
+
` ${pc.blue('~~~')} ${pc.white('( )')} ${pc.white('Riding the wave!')}`,
|
|
85
85
|
`${pc.blue('~~~~~~')}${pc.white('/| |\\')}`,
|
|
86
86
|
`${pc.blue('~~~~~~~~~~~~')}`,
|
|
87
87
|
`${pc.blue('~~~~~~~~~~~~~~~~~~~~~~~')}`
|
|
@@ -93,7 +93,7 @@ const ASCII = {
|
|
|
93
93
|
` ${pc.cyan(' │• •│ 🌊')}`,
|
|
94
94
|
` ${pc.cyan(' ╰─┬─╯ ')}`,
|
|
95
95
|
` ${pc.cyan(' ___/')}${pc.white('|')}${pc.cyan('\\___')}`,
|
|
96
|
-
` ${pc.blue('~~~~')}${pc.white('( )')} ${
|
|
96
|
+
` ${pc.blue('~~~~')}${pc.white('( )')} ${pc.white('Big one coming!')}`,
|
|
97
97
|
`${pc.blue('~~~~~~~')}${pc.white('/| |\\')}`,
|
|
98
98
|
`${pc.blue('~~~~~~~~~~~~~~')}`,
|
|
99
99
|
`${pc.blue('~~~~~~~~~~~~~~~~~~~~~~~~')}`
|
|
@@ -103,13 +103,13 @@ const ASCII = {
|
|
|
103
103
|
// Success screen dengan efek 3D
|
|
104
104
|
successArt: [
|
|
105
105
|
`${pc.cyan('╔═══════════════════════════════════════╗')}`,
|
|
106
|
-
`${pc.cyan('║')} ${
|
|
106
|
+
`${pc.cyan('║')} ${pc.green('✨ PROJECT READY TO SURF! ✨')} ${pc.cyan('║')}`,
|
|
107
107
|
`${pc.cyan('╠═══════════════════════════════════════╣')}`,
|
|
108
108
|
` `,
|
|
109
109
|
` ${pc.cyan('\\')} ${pc.cyan('/')} `,
|
|
110
|
-
` ${pc.cyan('\\')} ${
|
|
111
|
-
` ${pc.cyan('\\')} ${
|
|
112
|
-
` ${pc.cyan('╲')}${
|
|
110
|
+
` ${pc.cyan('\\')} ${pc.white('O')} ${pc.cyan('/')} `,
|
|
111
|
+
` ${pc.cyan('\\')} ${pc.white('K')} ${pc.cyan('/')} `,
|
|
112
|
+
` ${pc.cyan('╲')}${pc.white('!')}${pc.cyan('╱')} `,
|
|
113
113
|
` ${pc.cyan('●')} `,
|
|
114
114
|
` ${pc.blue('/')} ${pc.white('|')} ${pc.blue('\\')} `,
|
|
115
115
|
` ${pc.blue('/')} ${pc.white('|')} ${pc.blue('\\')} `,
|
|
@@ -144,14 +144,14 @@ class AnimationEngine {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
for (let i = 0; i < empty; i++) {
|
|
147
|
-
bar +=
|
|
147
|
+
bar += pc.gray('░');
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
return bar;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
async typewriter(text, speed = 30) {
|
|
154
|
-
process.stdout.write(
|
|
154
|
+
process.stdout.write(pc.cyan('▸ ') + pc.gray(''));
|
|
155
155
|
for (let char of text) {
|
|
156
156
|
process.stdout.write(char);
|
|
157
157
|
await new Promise(resolve => setTimeout(resolve, speed));
|
|
@@ -174,8 +174,8 @@ class AnimationEngine {
|
|
|
174
174
|
this.clearLines(8);
|
|
175
175
|
|
|
176
176
|
// Show current step
|
|
177
|
-
const stepText =
|
|
178
|
-
console.log(`${
|
|
177
|
+
const stepText = pc.white(step.title);
|
|
178
|
+
console.log(`${pc.cyan('🛠️ ')} ${stepText}`);
|
|
179
179
|
|
|
180
180
|
// Show animation frame
|
|
181
181
|
const frameIndex = Math.floor(p / 10) % ASCII.walkingFrames.length;
|
|
@@ -183,18 +183,18 @@ class AnimationEngine {
|
|
|
183
183
|
|
|
184
184
|
// Show progress bar with percentage
|
|
185
185
|
const bar = this.createProgressBar(p, 50);
|
|
186
|
-
console.log(`\n${bar} ${
|
|
186
|
+
console.log(`\n${bar} ${pc.cyan(p.toFixed(0) + '%')}`);
|
|
187
187
|
|
|
188
188
|
// Show status message with spinner
|
|
189
189
|
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][Math.floor(Date.now() / 100) % 10];
|
|
190
|
-
console.log(`${
|
|
190
|
+
console.log(`${pc.cyan(spinner)} ${pc.gray(step.message)}`);
|
|
191
191
|
|
|
192
192
|
await new Promise(resolve => setTimeout(resolve, step.delay || 50));
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// Mark step as complete
|
|
196
196
|
this.clearLines(8);
|
|
197
|
-
console.log(`${
|
|
197
|
+
console.log(`${pc.green('✓')} ${pc.white(step.title)} ${pc.gray('(completed)')}`);
|
|
198
198
|
|
|
199
199
|
if (!isLast) {
|
|
200
200
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
@@ -205,7 +205,7 @@ class AnimationEngine {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
async surfingCelebration() {
|
|
208
|
-
console.log('\n' + ' '.repeat(20) +
|
|
208
|
+
console.log('\n' + ' '.repeat(20) + pc.green('🏄 SURF\'S UP! 🏄') + '\n');
|
|
209
209
|
|
|
210
210
|
for (let i = 0; i < 15; i++) {
|
|
211
211
|
this.clearLines(12);
|
|
@@ -215,7 +215,7 @@ class AnimationEngine {
|
|
|
215
215
|
// Tambahkan efek partikel
|
|
216
216
|
const particles = ['✨', '🌟', '💫', '⭐', '🌊'];
|
|
217
217
|
const particle = particles[Math.floor(Math.random() * particles.length)];
|
|
218
|
-
console.log(' '.repeat(30) +
|
|
218
|
+
console.log(' '.repeat(30) + pc.yellow(particle));
|
|
219
219
|
|
|
220
220
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
221
221
|
}
|
|
@@ -234,33 +234,39 @@ async function init() {
|
|
|
234
234
|
console.log('\x1B[2J\x1B[0f');
|
|
235
235
|
|
|
236
236
|
// Header dengan gradient
|
|
237
|
-
console.log(
|
|
237
|
+
console.log(pc.cyan(`
|
|
238
238
|
╔═══════════════════════════════════════════════╗
|
|
239
239
|
║ ║
|
|
240
|
-
║ ${
|
|
241
|
-
║ ${
|
|
240
|
+
║ ${pc.white('🌊 LETSWHIM CREATOR v' + CONFIG.version)} ║
|
|
241
|
+
║ ${pc.gray('The Ultralight Web Engine')} ║
|
|
242
242
|
║ ║
|
|
243
243
|
╚═══════════════════════════════════════════════╝
|
|
244
244
|
`));
|
|
245
245
|
|
|
246
246
|
console.log();
|
|
247
247
|
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
type: 'text',
|
|
251
|
-
name: 'projectName',
|
|
252
|
-
message: CONFIG.colors.primary('?') + ' ' + CONFIG.colors.highlight('Project name:'),
|
|
253
|
-
initial: process.argv[2] || 'my-whim-project',
|
|
254
|
-
validate: value => value.trim() === '' ? 'Project name cannot be empty' : true
|
|
255
|
-
});
|
|
248
|
+
// Support npm create letswhim@latest my-project langsung
|
|
249
|
+
let projectName = process.argv[2];
|
|
256
250
|
|
|
257
|
-
|
|
251
|
+
if (!projectName) {
|
|
252
|
+
const response = await prompts({
|
|
253
|
+
type: 'text',
|
|
254
|
+
name: 'projectName',
|
|
255
|
+
message: pc.cyan('?') + ' ' + pc.white('Project name:'),
|
|
256
|
+
initial: 'my-whim-project',
|
|
257
|
+
validate: value => value.trim() === '' ? 'Project name cannot be empty' : true
|
|
258
|
+
});
|
|
259
|
+
projectName = response.projectName?.trim();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Fallback jika masih kosong
|
|
263
|
+
projectName = projectName || 'my-whim-project';
|
|
258
264
|
const targetDir = path.join(process.cwd(), projectName);
|
|
259
265
|
|
|
260
266
|
// Check if directory exists
|
|
261
267
|
if (fs.existsSync(targetDir)) {
|
|
262
|
-
console.log(`\n${
|
|
263
|
-
console.log(
|
|
268
|
+
console.log(`\n${pc.red('✖')} Directory ${pc.cyan(projectName)} already exists.`);
|
|
269
|
+
console.log(pc.gray('Try a different name or remove the existing directory.'));
|
|
264
270
|
process.exit(1);
|
|
265
271
|
}
|
|
266
272
|
|
|
@@ -278,15 +284,15 @@ async function init() {
|
|
|
278
284
|
// Actual processing
|
|
279
285
|
try {
|
|
280
286
|
// Clone repository
|
|
281
|
-
process.stdout.write(`${
|
|
287
|
+
process.stdout.write(`${pc.cyan('⏳')} ${pc.gray('Cloning repository...')}`);
|
|
282
288
|
execSync(`git clone --depth 1 ${CONFIG.repoUrl} "${projectName}"`, { stdio: 'ignore' });
|
|
283
|
-
console.log(`\r${
|
|
289
|
+
console.log(`\r${pc.green('✓')} ${pc.white('Repository cloned')}`);
|
|
284
290
|
|
|
285
291
|
// Remove .git folder
|
|
286
292
|
const gitFolder = path.join(targetDir, '.git');
|
|
287
293
|
if (fs.existsSync(gitFolder)) {
|
|
288
294
|
fs.rmSync(gitFolder, { recursive: true, force: true });
|
|
289
|
-
console.log(`${
|
|
295
|
+
console.log(`${pc.green('✓')} ${pc.white('Git history cleared')}`);
|
|
290
296
|
}
|
|
291
297
|
|
|
292
298
|
// Remove unnecessary files
|
|
@@ -300,39 +306,39 @@ async function init() {
|
|
|
300
306
|
await animator.surfingCelebration();
|
|
301
307
|
|
|
302
308
|
// Success message
|
|
303
|
-
console.log(`\n${
|
|
309
|
+
console.log(`\n${pc.green('🎉 SUCCESS!')} ${pc.white('Project created successfully!')}\n`);
|
|
304
310
|
|
|
305
|
-
console.log(
|
|
306
|
-
console.log(` ${
|
|
311
|
+
console.log(pc.cyan('📁 Project location:'));
|
|
312
|
+
console.log(` ${pc.white(`./${projectName}`)}\n`);
|
|
307
313
|
|
|
308
|
-
console.log(
|
|
309
|
-
console.log(`${
|
|
310
|
-
console.log(`${
|
|
311
|
-
console.log(`${
|
|
314
|
+
console.log(pc.cyan('🚀 Next steps to start surfing:'));
|
|
315
|
+
console.log(`${pc.green(' cd')} ${pc.white(projectName)}`);
|
|
316
|
+
console.log(`${pc.green(' npm install')} ${pc.gray('# or pnpm install / yarn')}`);
|
|
317
|
+
console.log(`${pc.green(' npm run dev')} ${pc.gray('# Start development server')}\n`);
|
|
312
318
|
|
|
313
|
-
console.log(
|
|
314
|
-
console.log(` ${
|
|
319
|
+
console.log(pc.cyan('📚 Documentation:'));
|
|
320
|
+
console.log(` ${pc.gray('https://letswhim.pages.dev')}\n`);
|
|
315
321
|
|
|
316
|
-
console.log(
|
|
322
|
+
console.log(pc.gray('💡 Tip: Run ') + pc.white('npm run help') + pc.gray(' to see all available commands'));
|
|
317
323
|
|
|
318
324
|
// Fun ASCII footer
|
|
319
|
-
console.log(
|
|
325
|
+
console.log(pc.blue(`
|
|
320
326
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
321
327
|
H A P P Y S U R F I N G ! 🏄♂️
|
|
322
328
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
323
329
|
`));
|
|
324
330
|
|
|
325
331
|
} catch (error) {
|
|
326
|
-
console.log(`\n${
|
|
327
|
-
console.log(
|
|
332
|
+
console.log(`\n${pc.red('💥 WIPEOUT!')} Something went wrong:`);
|
|
333
|
+
console.log(pc.gray(error.message));
|
|
328
334
|
|
|
329
335
|
// Clean up on error
|
|
330
336
|
if (fs.existsSync(targetDir)) {
|
|
331
337
|
try {
|
|
332
338
|
fs.rmSync(targetDir, { recursive: true });
|
|
333
|
-
console.log(
|
|
339
|
+
console.log(pc.gray('\nCleaned up partial installation.'));
|
|
334
340
|
} catch (e) {
|
|
335
|
-
console.log(
|
|
341
|
+
console.log(pc.gray('\nCould not clean up directory.'));
|
|
336
342
|
}
|
|
337
343
|
}
|
|
338
344
|
|
|
@@ -342,13 +348,13 @@ async function init() {
|
|
|
342
348
|
|
|
343
349
|
// Handle Ctrl+C gracefully
|
|
344
350
|
process.on('SIGINT', () => {
|
|
345
|
-
console.log(`\n\n${
|
|
351
|
+
console.log(`\n\n${pc.gray('👋 Catch you on the next wave!')}\n`);
|
|
346
352
|
process.exit(0);
|
|
347
353
|
});
|
|
348
354
|
|
|
349
355
|
// Run the application
|
|
350
356
|
init().catch(error => {
|
|
351
|
-
console.error(`\n${
|
|
352
|
-
console.error(
|
|
357
|
+
console.error(`\n${pc.red('💥 UNEXPECTED WIPEOUT!')}`);
|
|
358
|
+
console.error(pc.gray(error.stack || error.message));
|
|
353
359
|
process.exit(1);
|
|
354
360
|
});
|