launchbase 1.0.9 → 1.1.1

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/bin/launchbase.js CHANGED
@@ -7,7 +7,7 @@ const crypto = require('crypto');
7
7
  const fs = require('fs-extra');
8
8
  const { execSync, spawn } = require('child_process');
9
9
 
10
- const VERSION = '1.0.9';
10
+ const VERSION = '1.1.1';
11
11
  const program = new Command();
12
12
 
13
13
  function findAvailablePort(startPort = 5432, maxAttempts = 100) {
@@ -381,22 +381,26 @@ program
381
381
  }
382
382
 
383
383
  // Copy template files with filtering
384
+ console.log('📂 Copying template files...');
385
+ console.log(` Include frontend: ${options.template ? 'yes' : 'no'}`);
386
+
384
387
  await fs.copy(templateDir, targetDir, {
385
388
  filter: (src) => {
386
- const relativePath = path.relative(templateDir, src);
389
+ // Normalize path separators for cross-platform compatibility
390
+ const relativePath = path.relative(templateDir, src).replace(/\\/g, '/');
387
391
 
388
392
  // Skip node_modules, dist, etc.
389
393
  if (relativePath.includes('node_modules') || relativePath.includes('dist') || relativePath.includes('.next')) {
390
394
  return false;
391
395
  }
392
396
 
393
- // Skip frontend if not requested
394
- if (relativePath.startsWith('frontend') && !options.template) {
397
+ // Skip frontend if not requested (check with trailing slash to avoid partial matches)
398
+ if ((relativePath.startsWith('frontend/') || relativePath === 'frontend') && !options.template) {
395
399
  return false;
396
400
  }
397
401
 
398
402
  // Skip SDK if not requested
399
- if (relativePath.startsWith('sdk') && !options.sdk) {
403
+ if ((relativePath.startsWith('sdk/') || relativePath === 'sdk') && !options.sdk) {
400
404
  return false;
401
405
  }
402
406
 
@@ -422,20 +426,12 @@ program
422
426
  // Replace placeholders with dynamic ports
423
427
  const replacements = {
424
428
  '__APP_NAME__': appName,
429
+ '__DB_PORT__': dbPort.toString(),
425
430
  '"name": "launchbase-template"': `"name": "${appName}"`,
426
- '"PORT=3000"': `"PORT=${apiPort}"`,
427
- 'PORT=3000': `PORT=${apiPort}`,
428
- 'localhost:3000': `localhost:${apiPort}`,
429
- 'localhost:5173': `localhost:${frontendPort}`,
430
- 'localhost:5433': `localhost:${dbPort}`,
431
- 'localhost:5432': `localhost:${dbPort}`,
432
- '"5433:5432"': `"${dbPort}:5432"`,
433
- '"5432:5432"': `"${dbPort}:5432"`,
434
- '"3000:3000"': `"${apiPort}:3000"`,
435
431
  };
436
432
 
437
433
  // Update files with port replacements
438
- const filesToReplace = ['package.json', '.env.example', 'README.md', 'docker-compose.yml', '.env'];
434
+ const filesToReplace = ['package.json', '.env.example', 'README.md', 'docker-compose.yml'];
439
435
  for (const rel of filesToReplace) {
440
436
  const fp = path.join(targetDir, rel);
441
437
  if (await fs.pathExists(fp)) {
@@ -443,30 +439,31 @@ program
443
439
  }
444
440
  }
445
441
 
446
- // Generate .env with secrets
442
+ // Generate .env with secrets and correct ports
447
443
  const envExamplePath = path.join(targetDir, '.env.example');
448
444
  const envPath = path.join(targetDir, '.env');
449
445
 
450
446
  if (await fs.pathExists(envExamplePath)) {
451
447
  let env = await fs.readFile(envExamplePath, 'utf8');
448
+ // Replace app name
449
+ env = env.replace(/__APP_NAME__/g, appName);
450
+ // Replace secrets
452
451
  env = env.replace('JWT_ACCESS_SECRET=__CHANGE_ME__', `JWT_ACCESS_SECRET=${randomSecret(32)}`);
453
452
  env = env.replace('JWT_REFRESH_SECRET=__CHANGE_ME__', `JWT_REFRESH_SECRET=${randomSecret(32)}`);
454
- // Ensure ports are correct
453
+ // Replace ports
455
454
  env = env.replace(/PORT=\d+/, `PORT=${apiPort}`);
456
- env = env.replace(/localhost:\d+.*__APP_NAME__/g, `localhost:${dbPort}/${appName}`);
455
+ env = env.replace(/localhost:\d+\/__APP_NAME__/g, `localhost:${dbPort}/${appName}`);
456
+ env = env.replace(/localhost:5433/g, `localhost:${dbPort}`);
457
+ env = env.replace(/localhost:5432/g, `localhost:${dbPort}`);
458
+ env = env.replace(/localhost:3000/g, `localhost:${apiPort}`);
459
+ env = env.replace(/localhost:5173/g, `localhost:${frontendPort}`);
457
460
  await fs.writeFile(envPath, env, 'utf8');
458
461
  }
459
462
 
460
- // Update docker-compose.yml with correct ports
461
- const dockerComposePath = path.join(targetDir, 'docker-compose.yml');
462
- if (await fs.pathExists(dockerComposePath)) {
463
- let compose = await fs.readFile(dockerComposePath, 'utf8');
464
- compose = compose.replace(/"(\d+):5432"/, `"${dbPort}:5432"`);
465
- compose = compose.replace(/"(\d+):3000"/, `"${apiPort}:3000"`);
466
- await fs.writeFile(dockerComposePath, compose, 'utf8');
467
- }
468
-
469
463
  console.log('✅ Project files created\n');
464
+ console.log(` Database port: ${dbPort}`);
465
+ console.log(` API port: ${apiPort}`);
466
+ console.log(` Frontend port: ${frontendPort}\n`);
470
467
 
471
468
  // Install dependencies
472
469
  console.log('📦 Installing dependencies...\n');
@@ -590,20 +587,21 @@ program
590
587
  // Copy template files with filtering
591
588
  await fs.copy(templateDir, targetDir, {
592
589
  filter: (src) => {
593
- const relativePath = path.relative(templateDir, src);
590
+ // Normalize path separators for cross-platform compatibility
591
+ const relativePath = path.relative(templateDir, src).replace(/\\/g, '/');
594
592
 
595
593
  // Skip node_modules, dist, etc.
596
594
  if (relativePath.includes('node_modules') || relativePath.includes('dist') || relativePath.includes('.next')) {
597
595
  return false;
598
596
  }
599
597
 
600
- // Skip frontend if not requested
601
- if (relativePath.startsWith('frontend') && !options.template) {
598
+ // Skip frontend if not requested (check with trailing slash to avoid partial matches)
599
+ if ((relativePath.startsWith('frontend/') || relativePath === 'frontend') && !options.template) {
602
600
  return false;
603
601
  }
604
602
 
605
603
  // Skip SDK if not requested
606
- if (relativePath.startsWith('sdk') && !options.sdk) {
604
+ if ((relativePath.startsWith('sdk/') || relativePath === 'sdk') && !options.sdk) {
607
605
  return false;
608
606
  }
609
607
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "launchbase",
3
- "version": "1.0.9",
3
+ "version": "1.1.1",
4
4
  "description": "Generate production-ready NestJS backends with authentication, multi-tenancy, billing, and deployment in minutes",
5
5
  "author": "LaunchBase",
6
6
  "keywords": [
@@ -15,7 +15,7 @@ FRONTEND_URL=http://localhost:5173
15
15
  # Database
16
16
  # ===========================================
17
17
  # Local PostgreSQL (with Docker)
18
- DATABASE_URL=postgresql://postgres:postgres@localhost:5433/__APP_NAME__?schema=public
18
+ DATABASE_URL=postgresql://postgres:postgres@localhost:__DB_PORT__/__APP_NAME__?schema=public
19
19
  # SQLite (for simple local dev)
20
20
  # DATABASE_URL="file:./dev.db"
21
21
 
@@ -7,7 +7,7 @@ services:
7
7
  POSTGRES_PASSWORD: postgres
8
8
  POSTGRES_DB: launchbase
9
9
  ports:
10
- - "5433:5432"
10
+ - "__DB_PORT__:5432"
11
11
  volumes:
12
12
  - db_data:/var/lib/postgresql/data
13
13
  healthcheck:
@@ -16,18 +16,5 @@ services:
16
16
  timeout: 5s
17
17
  retries: 5
18
18
 
19
- api:
20
- build: .
21
- restart: unless-stopped
22
- env_file:
23
- - .env
24
- environment:
25
- DATABASE_URL: ${DATABASE_URL}
26
- ports:
27
- - "3000:3000"
28
- depends_on:
29
- db:
30
- condition: service_healthy
31
-
32
19
  volumes:
33
20
  db_data: