create-sonicjs 2.0.0-beta.6 → 2.0.0-beta.8

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +129 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sonicjs",
3
- "version": "2.0.0-beta.6",
3
+ "version": "2.0.0-beta.8",
4
4
  "description": "Create a new SonicJS application with zero configuration",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -12,7 +12,7 @@ import validatePackageName from 'validate-npm-package-name'
12
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
13
13
 
14
14
  // Version
15
- const VERSION = '2.0.0-beta.6'
15
+ const VERSION = '2.0.0-beta.8'
16
16
 
17
17
  // Templates available
18
18
  const TEMPLATES = {
@@ -135,9 +135,17 @@ async function getProjectDetails(initialName) {
135
135
  })
136
136
  }
137
137
 
138
- // Admin email
138
+ // Seed admin user
139
139
  questions.push({
140
- type: 'text',
140
+ type: 'confirm',
141
+ name: 'seedAdmin',
142
+ message: 'Create admin user?',
143
+ initial: true
144
+ })
145
+
146
+ // Admin email (only if seeding)
147
+ questions.push({
148
+ type: (prev, values) => values.seedAdmin ? 'text' : null,
141
149
  name: 'adminEmail',
142
150
  message: 'Admin email:',
143
151
  validate: (value) => {
@@ -149,9 +157,9 @@ async function getProjectDetails(initialName) {
149
157
  }
150
158
  })
151
159
 
152
- // Admin password
160
+ // Admin password (only if seeding)
153
161
  questions.push({
154
- type: 'password',
162
+ type: (prev, values) => values.seedAdmin ? 'password' : null,
155
163
  name: 'adminPassword',
156
164
  message: 'Admin password:',
157
165
  validate: (value) => {
@@ -202,10 +210,12 @@ async function getProjectDetails(initialName) {
202
210
  template: flags.template || answers.template,
203
211
  databaseName: flags.databaseName || answers.databaseName || `${initialName || answers.projectName}-db`,
204
212
  bucketName: flags.bucketName || answers.bucketName || `${initialName || answers.projectName}-media`,
213
+ seedAdmin: answers.seedAdmin !== undefined ? answers.seedAdmin : true,
205
214
  adminEmail: answers.adminEmail,
206
215
  adminPassword: answers.adminPassword,
207
216
  includeExample: flags.skipExample ? false : (flags.includeExample ? true : (answers.includeExample !== undefined ? answers.includeExample : true)),
208
217
  createResources: flags.skipCloudflare ? false : answers.createResources,
218
+ runMigrations: true, // Always run migrations automatically
209
219
  initGit: flags.skipGit ? false : answers.initGit,
210
220
  skipInstall: flags.skipInstall
211
221
  }
@@ -221,6 +231,8 @@ async function createProject(answers, flags) {
221
231
  adminPassword,
222
232
  includeExample,
223
233
  createResources,
234
+ runMigrations,
235
+ seedAdmin,
224
236
  initGit,
225
237
  skipInstall
226
238
  } = answers
@@ -237,6 +249,7 @@ async function createProject(answers, flags) {
237
249
  projectName,
238
250
  databaseName,
239
251
  bucketName,
252
+ seedAdmin,
240
253
  adminEmail,
241
254
  adminPassword,
242
255
  includeExample
@@ -291,6 +304,45 @@ async function createProject(answers, flags) {
291
304
  spinner.succeed('Initialized git repository')
292
305
  }
293
306
 
307
+ // 6. Run migrations
308
+ if (runMigrations && !skipInstall && resourcesCreated) {
309
+ spinner.start('Running database migrations...')
310
+ try {
311
+ await runDatabaseMigrations(targetDir)
312
+ spinner.succeed('Database migrations completed')
313
+ answers.migrationsRan = true
314
+ } catch (error) {
315
+ spinner.warn('Failed to run migrations')
316
+ console.log(kleur.dim(` ${error.message}`))
317
+ console.log(kleur.dim(' You can run them manually with: npm run db:migrate:local'))
318
+ answers.migrationsRan = false
319
+ }
320
+ } else if (runMigrations && skipInstall) {
321
+ spinner.info('Skipping migrations - run after npm install')
322
+ answers.migrationsRan = false
323
+ } else if (runMigrations && !resourcesCreated) {
324
+ spinner.info('Skipping migrations - database not created yet')
325
+ answers.migrationsRan = false
326
+ }
327
+
328
+ // 7. Seed admin user
329
+ if (seedAdmin && !skipInstall && answers.migrationsRan) {
330
+ spinner.start('Seeding admin user...')
331
+ try {
332
+ await seedAdminUser(targetDir)
333
+ spinner.succeed('Admin user created')
334
+ answers.adminSeeded = true
335
+ } catch (error) {
336
+ spinner.warn('Failed to seed admin user')
337
+ console.log(kleur.dim(` ${error.message}`))
338
+ console.log(kleur.dim(' You can run it manually with: npm run seed'))
339
+ answers.adminSeeded = false
340
+ }
341
+ } else if (seedAdmin && !answers.migrationsRan) {
342
+ spinner.info('Skipping seed - migrations not completed')
343
+ answers.adminSeeded = false
344
+ }
345
+
294
346
  spinner.succeed(kleur.bold().green('✓ Project created successfully!'))
295
347
 
296
348
  } catch (error) {
@@ -351,11 +403,13 @@ async function copyTemplate(templateName, targetDir, options) {
351
403
  }
352
404
  }
353
405
 
354
- // Create admin seed script with provided credentials
355
- await createAdminSeedScript(targetDir, {
356
- email: options.adminEmail,
357
- password: options.adminPassword
358
- })
406
+ // Create admin seed script with provided credentials (only if creating admin user)
407
+ if (options.seedAdmin && options.adminEmail && options.adminPassword) {
408
+ await createAdminSeedScript(targetDir, {
409
+ email: options.adminEmail,
410
+ password: options.adminPassword
411
+ })
412
+ }
359
413
  }
360
414
 
361
415
  async function createAdminSeedScript(targetDir, { email, password }) {
@@ -623,8 +677,42 @@ async function initializeGit(targetDir) {
623
677
  }
624
678
  }
625
679
 
680
+ async function runDatabaseMigrations(targetDir) {
681
+ try {
682
+ const { stdout, stderr } = await execa('npm', ['run', 'db:migrate:local'], {
683
+ cwd: targetDir
684
+ })
685
+
686
+ // Check if migrations were successful
687
+ if (stderr && stderr.includes('error')) {
688
+ throw new Error(stderr)
689
+ }
690
+
691
+ return stdout
692
+ } catch (error) {
693
+ throw new Error(`Migration failed: ${error.message}`)
694
+ }
695
+ }
696
+
697
+ async function seedAdminUser(targetDir) {
698
+ try {
699
+ const { stdout, stderr } = await execa('npm', ['run', 'seed'], {
700
+ cwd: targetDir
701
+ })
702
+
703
+ // Check if seeding was successful
704
+ if (stderr && stderr.includes('error')) {
705
+ throw new Error(stderr)
706
+ }
707
+
708
+ return stdout
709
+ } catch (error) {
710
+ throw new Error(`Seeding failed: ${error.message}`)
711
+ }
712
+ }
713
+
626
714
  function printSuccessMessage(answers) {
627
- const { projectName, createResources, skipInstall, resourcesCreated, databaseIdSet } = answers
715
+ const { projectName, createResources, skipInstall, resourcesCreated, databaseIdSet, migrationsRan, adminSeeded } = answers
628
716
 
629
717
  console.log()
630
718
  console.log(kleur.bold().green('🎉 Success!'))
@@ -651,21 +739,40 @@ function printSuccessMessage(answers) {
651
739
  console.log(kleur.cyan(` wrangler r2 bucket create ${answers.bucketName}`))
652
740
  }
653
741
 
654
- console.log()
655
- console.log(kleur.bold('⚡ IMPORTANT - Run migrations and seed admin user:'))
656
- console.log(kleur.cyan(' npm run db:migrate:local'))
657
- console.log(kleur.cyan(' npm run seed'))
658
- console.log()
659
- console.log(kleur.dim(' Without migrations, you will get "no such table" errors!'))
742
+ // Only show migration/seed steps if they weren't completed (shouldn't normally happen)
743
+ const needsMigrations = !migrationsRan
744
+ const needsSeeding = seedAdmin && !adminSeeded
745
+
746
+ if (needsMigrations || needsSeeding) {
747
+ console.log()
748
+ console.log(kleur.bold('Complete setup:'))
749
+ if (needsMigrations) {
750
+ console.log(kleur.cyan(' npm run db:migrate:local'))
751
+ }
752
+ if (needsSeeding) {
753
+ console.log(kleur.cyan(' npm run seed'))
754
+ }
755
+ }
660
756
 
661
757
  console.log()
662
- console.log(kleur.bold('Start development:'))
758
+ if (migrationsRan && (!seedAdmin || adminSeeded)) {
759
+ console.log(kleur.bold().green('✓ Database is ready! Start development:'))
760
+ } else {
761
+ console.log(kleur.bold('Start development:'))
762
+ }
663
763
  console.log(kleur.cyan(' npm run dev'))
664
764
 
665
- console.log()
666
- console.log(kleur.bold('Login credentials:'))
667
- console.log(kleur.cyan(` Email: ${answers.adminEmail}`))
668
- console.log(kleur.dim(` Password: [as entered]`))
765
+ if (seedAdmin && answers.adminEmail) {
766
+ console.log()
767
+ console.log(kleur.bold('Login credentials:'))
768
+ console.log(kleur.cyan(` Email: ${answers.adminEmail}`))
769
+ console.log(kleur.dim(` Password: [as entered]`))
770
+ }
771
+
772
+ if (migrationsRan && (!seedAdmin || adminSeeded)) {
773
+ console.log()
774
+ console.log(kleur.green('✓ Everything is set up! Just run npm run dev and login.'))
775
+ }
669
776
 
670
777
  console.log()
671
778
  console.log(kleur.bold('Visit:'))