launchbase 1.2.1 → 1.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/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.2.1';
10
+ const VERSION = '1.2.2';
11
11
  const program = new Command();
12
12
 
13
13
  function findAvailablePort(startPort = 5432, maxAttempts = 100) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "launchbase",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Generate production-ready NestJS backends with authentication, multi-tenancy, billing, and deployment in minutes",
5
5
  "author": "LaunchBase",
6
6
  "keywords": [
@@ -14,6 +14,7 @@ export const api = axios.create({
14
14
  api.interceptors.request.use((config) => {
15
15
  const token = localStorage.getItem('accessToken')
16
16
  const orgId = localStorage.getItem('currentOrgId')
17
+ const projectId = localStorage.getItem('currentProjectId')
17
18
 
18
19
  if (token) {
19
20
  config.headers.Authorization = `Bearer ${token}`
@@ -21,6 +22,9 @@ api.interceptors.request.use((config) => {
21
22
  if (orgId) {
22
23
  config.headers['X-Org-Id'] = orgId
23
24
  }
25
+ if (projectId) {
26
+ config.headers['X-Project-Id'] = projectId
27
+ }
24
28
 
25
29
  return config
26
30
  })
@@ -35,23 +35,29 @@ export function AuthProvider({ children }: { children: ReactNode }) {
35
35
 
36
36
  const login = async (email: string, password: string) => {
37
37
  const res = await api.post('/api/auth/login', { email, password })
38
- const { accessToken, refreshToken, user, org } = res.data
38
+ const { accessToken, refreshToken, user, org, project } = res.data
39
39
  localStorage.setItem('accessToken', accessToken)
40
40
  localStorage.setItem('refreshToken', refreshToken)
41
41
  if (org) {
42
42
  localStorage.setItem('currentOrgId', org.id)
43
43
  }
44
+ if (project) {
45
+ localStorage.setItem('currentProjectId', project.id)
46
+ }
44
47
  setUser(user)
45
48
  }
46
49
 
47
50
  const signup = async (email: string, password: string, orgName: string) => {
48
51
  const res = await api.post('/api/auth/signup', { email, password, orgName })
49
- const { accessToken, refreshToken, user, org } = res.data
52
+ const { accessToken, refreshToken, user, org, project } = res.data
50
53
  localStorage.setItem('accessToken', accessToken)
51
54
  localStorage.setItem('refreshToken', refreshToken)
52
55
  if (org) {
53
56
  localStorage.setItem('currentOrgId', org.id)
54
57
  }
58
+ if (project) {
59
+ localStorage.setItem('currentProjectId', project.id)
60
+ }
55
61
  setUser(user)
56
62
  }
57
63
 
@@ -59,6 +65,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
59
65
  localStorage.removeItem('accessToken')
60
66
  localStorage.removeItem('refreshToken')
61
67
  localStorage.removeItem('currentOrgId')
68
+ localStorage.removeItem('currentProjectId')
62
69
  setUser(null)
63
70
  }
64
71
 
@@ -1,38 +1,11 @@
1
- import { PrismaClient, Role } from '@prisma/client';
2
- import * as bcrypt from 'bcrypt';
1
+ import { PrismaClient } from '@prisma/client';
3
2
 
4
3
  const prisma = new PrismaClient();
5
4
 
6
5
  async function main() {
7
- const email = 'admin@example.com';
8
- const password = 'password123';
9
-
10
- const existing = await prisma.user.findUnique({ where: { email } });
11
- if (existing) return;
12
-
13
- const saltRounds = Number(process.env.BCRYPT_SALT_ROUNDS ?? '10');
14
- const passwordHash = await bcrypt.hash(password, saltRounds);
15
-
16
- const user = await prisma.user.create({
17
- data: { email, passwordHash }
18
- });
19
-
20
- const org = await prisma.organization.create({
21
- data: { name: 'My Organization', slug: 'my-org' }
22
- });
23
-
24
- await prisma.organizationMember.create({
25
- data: { userId: user.id, organizationId: org.id, role: Role.OWNER }
26
- });
27
-
28
- await prisma.project.create({
29
- data: {
30
- organizationId: org.id,
31
- name: 'Default Project',
32
- slug: 'default-project',
33
- description: 'Default project created during setup'
34
- }
35
- });
6
+ // Production-ready seed - no demo data
7
+ // Users, organizations, and projects are created through the API
8
+ console.log('Database seeded (production mode - no demo data)');
36
9
  }
37
10
 
38
11
  main()
@@ -66,7 +66,7 @@ export class AuthService {
66
66
  const passwordHash = await this.hashPassword(dto.password);
67
67
 
68
68
  // Generate slug from org name
69
- const slug = dto.orgName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
69
+ const orgSlug = dto.orgName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
70
70
 
71
71
  const user = await this.prisma.user.create({
72
72
  data: {
@@ -79,7 +79,7 @@ export class AuthService {
79
79
  const org = await this.prisma.organization.create({
80
80
  data: {
81
81
  name: dto.orgName,
82
- slug,
82
+ slug: orgSlug,
83
83
  ownerId: user.id
84
84
  }
85
85
  });
@@ -92,11 +92,23 @@ export class AuthService {
92
92
  }
93
93
  });
94
94
 
95
+ // Create default project for the organization
96
+ const projectSlug = 'default-project';
97
+ const project = await this.prisma.project.create({
98
+ data: {
99
+ organizationId: org.id,
100
+ name: 'Default Project',
101
+ slug: projectSlug,
102
+ description: 'Default project created during signup'
103
+ }
104
+ });
105
+
95
106
  const tokens = await this.issueTokens(user);
96
107
 
97
108
  return {
98
109
  user: { id: user.id, email: user.email },
99
110
  org: { id: org.id, name: org.name, slug: org.slug },
111
+ project: { id: project.id, name: project.name, slug: project.slug },
100
112
  ...tokens
101
113
  };
102
114
  }
@@ -104,7 +116,15 @@ export class AuthService {
104
116
  async login(dto: LoginDto) {
105
117
  const user = await this.prisma.user.findUnique({
106
118
  where: { email: dto.email },
107
- include: { organizationMemberships: { include: { organization: true } } }
119
+ include: {
120
+ organizationMemberships: {
121
+ include: {
122
+ organization: {
123
+ include: { projects: { take: 1 } }
124
+ }
125
+ }
126
+ }
127
+ }
108
128
  });
109
129
  if (!user || !user.passwordHash) throw new UnauthorizedException('Invalid credentials');
110
130
 
@@ -113,12 +133,15 @@ export class AuthService {
113
133
 
114
134
  const tokens = await this.issueTokens({ id: user.id, email: user.email });
115
135
 
116
- // Get first org for the user
136
+ // Get first org and project for the user
117
137
  const firstMembership = user.organizationMemberships[0];
138
+ const firstOrg = firstMembership?.organization;
139
+ const firstProject = firstOrg?.projects[0];
118
140
 
119
141
  return {
120
142
  user: { id: user.id, email: user.email },
121
- org: firstMembership ? { id: firstMembership.organization.id, name: firstMembership.organization.name, slug: firstMembership.organization.slug } : null,
143
+ org: firstOrg ? { id: firstOrg.id, name: firstOrg.name, slug: firstOrg.slug } : null,
144
+ project: firstProject ? { id: firstProject.id, name: firstProject.name, slug: firstProject.slug } : null,
122
145
  ...tokens
123
146
  };
124
147
  }