@vezlo/assistant-server 2.1.0 → 2.2.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/Dockerfile +6 -4
- package/README.md +18 -10
- package/dist/knexfile.d.ts.map +1 -1
- package/dist/knexfile.js +38 -17
- package/dist/knexfile.js.map +1 -1
- package/dist/src/services/SetupService.d.ts +2 -0
- package/dist/src/services/SetupService.d.ts.map +1 -1
- package/dist/src/services/SetupService.js +60 -47
- package/dist/src/services/SetupService.js.map +1 -1
- package/knexfile.ts +44 -17
- package/package.json +4 -3
- package/scripts/entrypoint.sh +44 -4
- package/scripts/seed-default.js +0 -0
- package/scripts/setup.js +66 -12
package/Dockerfile
CHANGED
|
@@ -33,12 +33,14 @@ RUN adduser -S vezlo -u 1001
|
|
|
33
33
|
# Copy package files
|
|
34
34
|
COPY package*.json ./
|
|
35
35
|
|
|
36
|
-
# Install only production dependencies
|
|
37
|
-
RUN npm ci --only=production && npm
|
|
36
|
+
# Install only production dependencies (compiled migrations are used at runtime)
|
|
37
|
+
RUN npm ci --only=production && npm cache clean --force
|
|
38
38
|
|
|
39
|
-
# Copy built application
|
|
39
|
+
# Copy built application (dist) and compiled migrations/knexfile from builder
|
|
40
40
|
COPY --from=builder /app/dist ./dist
|
|
41
|
-
COPY --from=builder /app/src/migrations ./src/migrations
|
|
41
|
+
COPY --from=builder /app/dist/src/migrations ./src/migrations
|
|
42
|
+
# Copy knexfile (compiled JS + TS source for reference)
|
|
43
|
+
COPY --from=builder /app/dist/knexfile.js ./knexfile.js
|
|
42
44
|
COPY --from=builder /app/knexfile.ts ./knexfile.ts
|
|
43
45
|
COPY --from=builder /app/scripts ./scripts
|
|
44
46
|
|
package/README.md
CHANGED
|
@@ -189,15 +189,23 @@ npx vezlo-server
|
|
|
189
189
|
npm run build && npm start
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
### Docker
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
```
|
|
192
|
+
### Docker Setup
|
|
193
|
+
|
|
194
|
+
1. Copy the environment template and fill in your Supabase/OpenAI values:
|
|
195
|
+
```bash
|
|
196
|
+
cp env.example .env
|
|
197
|
+
# edit .env with your credentials before continuing
|
|
198
|
+
```
|
|
199
|
+
2. Build and start the stack:
|
|
200
|
+
```bash
|
|
201
|
+
docker-compose build
|
|
202
|
+
docker-compose up -d
|
|
203
|
+
```
|
|
204
|
+
The entrypoint runs migrations, seeds the default org/admin, and generates an API key automatically.
|
|
205
|
+
3. View container logs:
|
|
206
|
+
```bash
|
|
207
|
+
docker-compose logs -f vezlo-server
|
|
208
|
+
```
|
|
201
209
|
|
|
202
210
|
## ☁️ Vercel Deployment
|
|
203
211
|
|
|
@@ -700,4 +708,4 @@ This project is dual-licensed:
|
|
|
700
708
|
|
|
701
709
|
---
|
|
702
710
|
|
|
703
|
-
**Status**: ✅ Production Ready | **Version**: 2.1
|
|
711
|
+
**Status**: ✅ Production Ready | **Version**: 2.2.1 | **Node.js**: 20+ | **TypeScript**: 5+
|
package/dist/knexfile.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knexfile.d.ts","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"knexfile.d.ts","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AA8CjC,QAAA,MAAM,MAAM,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;CAgFzC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/knexfile.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
7
7
|
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
8
9
|
// Load environment variables
|
|
9
10
|
dotenv_1.default.config();
|
|
10
11
|
// Register ts-node for TypeScript support in migrations (works in all environments)
|
|
@@ -14,6 +15,30 @@ try {
|
|
|
14
15
|
catch (e) {
|
|
15
16
|
// ts-node not available, that's okay - migrations will use compiled JS
|
|
16
17
|
}
|
|
18
|
+
const projectRoot = fs.existsSync(path.join(__dirname, 'package.json'))
|
|
19
|
+
? __dirname
|
|
20
|
+
: path.join(__dirname, '..');
|
|
21
|
+
const srcMigrationsPath = path.join(projectRoot, 'src', 'migrations');
|
|
22
|
+
const distMigrationsPath = path.join(projectRoot, 'dist', 'src', 'migrations');
|
|
23
|
+
const tsMigrationProbe = path.join(srcMigrationsPath, '001_initial_schema.ts');
|
|
24
|
+
const jsMigrationProbe = path.join(distMigrationsPath, '001_initial_schema.js');
|
|
25
|
+
const hasTsMigrations = fs.existsSync(tsMigrationProbe);
|
|
26
|
+
const hasJsMigrations = fs.existsSync(jsMigrationProbe);
|
|
27
|
+
const resolvedMigrationsDirectory = hasTsMigrations
|
|
28
|
+
? srcMigrationsPath
|
|
29
|
+
: hasJsMigrations
|
|
30
|
+
? distMigrationsPath
|
|
31
|
+
: srcMigrationsPath;
|
|
32
|
+
const migrationExtension = hasTsMigrations ? 'ts' : (hasJsMigrations ? 'js' : 'ts');
|
|
33
|
+
const migrationLoadExtensions = migrationExtension === 'ts' ? ['.ts'] : ['.js'];
|
|
34
|
+
const supabaseMigrationsDirectory = fs.existsSync(distMigrationsPath)
|
|
35
|
+
? distMigrationsPath
|
|
36
|
+
: resolvedMigrationsDirectory;
|
|
37
|
+
const supabaseMigrationExtension = fs.existsSync(distMigrationsPath) ? 'js' : migrationExtension;
|
|
38
|
+
const supabaseSeedsDirectory = fs.existsSync(path.join(projectRoot, 'dist', 'src', 'seeds'))
|
|
39
|
+
? path.join(projectRoot, 'dist', 'src', 'seeds')
|
|
40
|
+
: path.join(projectRoot, 'src', 'seeds');
|
|
41
|
+
const supabaseSeedsAreJs = supabaseSeedsDirectory.endsWith(path.join('dist', 'src', 'seeds'));
|
|
17
42
|
const config = {
|
|
18
43
|
development: {
|
|
19
44
|
client: 'postgresql',
|
|
@@ -30,9 +55,10 @@ const config = {
|
|
|
30
55
|
max: 10
|
|
31
56
|
},
|
|
32
57
|
migrations: {
|
|
33
|
-
directory:
|
|
58
|
+
directory: resolvedMigrationsDirectory,
|
|
34
59
|
tableName: 'knex_migrations',
|
|
35
|
-
extension:
|
|
60
|
+
extension: migrationExtension,
|
|
61
|
+
loadExtensions: migrationLoadExtensions
|
|
36
62
|
},
|
|
37
63
|
seeds: {
|
|
38
64
|
directory: './src/seeds',
|
|
@@ -54,17 +80,18 @@ const config = {
|
|
|
54
80
|
max: 20
|
|
55
81
|
},
|
|
56
82
|
migrations: {
|
|
57
|
-
// Use
|
|
58
|
-
directory:
|
|
83
|
+
// Use resolved path (prefers TS during development, JS in packaged builds)
|
|
84
|
+
directory: resolvedMigrationsDirectory,
|
|
59
85
|
tableName: 'knex_migrations',
|
|
60
|
-
extension:
|
|
86
|
+
extension: migrationExtension,
|
|
87
|
+
loadExtensions: migrationLoadExtensions
|
|
61
88
|
},
|
|
62
89
|
seeds: {
|
|
63
90
|
directory: path.join(__dirname, 'src/seeds'),
|
|
64
91
|
extension: 'js'
|
|
65
92
|
}
|
|
66
93
|
},
|
|
67
|
-
//
|
|
94
|
+
// Supabase (used by Vercel) always targets compiled JS migrations
|
|
68
95
|
supabase: {
|
|
69
96
|
client: 'postgresql',
|
|
70
97
|
connection: process.env.SUPABASE_DB_URL || process.env.DATABASE_URL || {
|
|
@@ -80,20 +107,14 @@ const config = {
|
|
|
80
107
|
max: 10
|
|
81
108
|
},
|
|
82
109
|
migrations: {
|
|
83
|
-
|
|
84
|
-
// In development, use relative path
|
|
85
|
-
directory: process.env.NODE_ENV === 'production'
|
|
86
|
-
? path.join(__dirname, 'src/migrations')
|
|
87
|
-
: path.join(process.cwd(), 'src/migrations'),
|
|
110
|
+
directory: supabaseMigrationsDirectory,
|
|
88
111
|
tableName: 'knex_migrations',
|
|
89
|
-
extension:
|
|
90
|
-
loadExtensions:
|
|
112
|
+
extension: supabaseMigrationExtension,
|
|
113
|
+
loadExtensions: supabaseMigrationExtension === 'ts' ? ['.ts'] : ['.js']
|
|
91
114
|
},
|
|
92
115
|
seeds: {
|
|
93
|
-
directory:
|
|
94
|
-
|
|
95
|
-
: path.join(process.cwd(), 'src/seeds'),
|
|
96
|
-
extension: process.env.NODE_ENV === 'production' ? 'js' : 'ts'
|
|
116
|
+
directory: supabaseSeedsDirectory,
|
|
117
|
+
extension: supabaseSeedsAreJs ? 'js' : 'ts'
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
120
|
};
|
package/dist/knexfile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knexfile.js","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":";;;;;AACA,oDAA4B;AAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"knexfile.js","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SetupService.d.ts","sourceRoot":"","sources":["../../../src/services/SetupService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAIpC;;OAEG;IACH,MAAM,CAAC,qBAAqB;;;;;IAQ5B;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE;QAC/B,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"SetupService.d.ts","sourceRoot":"","sources":["../../../src/services/SetupService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAIpC;;OAEG;IACH,MAAM,CAAC,qBAAqB;;;;;IAQ5B;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE;QAC/B,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB;;;;;;;;;;;;;;;;;;IAUD;;;OAGG;IACG,sBAAsB,CAAC,OAAO,EAAE;QACpC,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB;;;;;;;;;;;;;;;;;;IA8GD,OAAO,CAAC,iBAAiB;YAIX,wBAAwB;IA4CtC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAc1C;;OAEG;IACG,cAAc;;;;;;;;;;;;;;;;;IAiDpB;;OAEG;IACG,kBAAkB;IAmBxB;;OAEG;IACG,kBAAkB;;;;;CA0EzB"}
|
|
@@ -59,9 +59,8 @@ class SetupService {
|
|
|
59
59
|
*/
|
|
60
60
|
async createDefaultData(options) {
|
|
61
61
|
const result = await this.getOrCreateDefaultData(options);
|
|
62
|
-
// Throw error if already exists (maintains CLI behavior)
|
|
63
62
|
if (result.alreadyExists) {
|
|
64
|
-
|
|
63
|
+
logger_1.default.info('Default data already exists; returning existing records');
|
|
65
64
|
}
|
|
66
65
|
return result;
|
|
67
66
|
}
|
|
@@ -73,51 +72,10 @@ class SetupService {
|
|
|
73
72
|
const { adminEmail, adminPassword, companyName } = options;
|
|
74
73
|
try {
|
|
75
74
|
logger_1.default.info('Checking for existing default company and admin user...');
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.
|
|
79
|
-
|
|
80
|
-
.eq('domain', 'default')
|
|
81
|
-
.single();
|
|
82
|
-
if (existingCompany) {
|
|
83
|
-
// Get the admin user and profile
|
|
84
|
-
const { data: profile } = await this.supabase
|
|
85
|
-
.from('vezlo_user_company_profiles')
|
|
86
|
-
.select('*, vezlo_users(*)')
|
|
87
|
-
.eq('company_id', existingCompany.id)
|
|
88
|
-
.eq('role', 'admin')
|
|
89
|
-
.single();
|
|
90
|
-
if (profile && profile.vezlo_users) {
|
|
91
|
-
const user = profile.vezlo_users;
|
|
92
|
-
logger_1.default.info('Default data already exists, returning existing data');
|
|
93
|
-
return {
|
|
94
|
-
success: true,
|
|
95
|
-
alreadyExists: true,
|
|
96
|
-
company: {
|
|
97
|
-
id: existingCompany.uuid,
|
|
98
|
-
name: existingCompany.name,
|
|
99
|
-
domain: existingCompany.domain
|
|
100
|
-
},
|
|
101
|
-
user: {
|
|
102
|
-
id: user.uuid,
|
|
103
|
-
email: user.email,
|
|
104
|
-
name: user.name
|
|
105
|
-
},
|
|
106
|
-
profile: {
|
|
107
|
-
id: profile.uuid,
|
|
108
|
-
role: profile.role
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Check if admin user already exists
|
|
114
|
-
const { data: existingUser } = await this.supabase
|
|
115
|
-
.from('vezlo_users')
|
|
116
|
-
.select('id')
|
|
117
|
-
.eq('email', adminEmail)
|
|
118
|
-
.single();
|
|
119
|
-
if (existingUser) {
|
|
120
|
-
throw new Error(`User with email ${adminEmail} already exists`);
|
|
75
|
+
const existingData = await this.fetchExistingDefaultData();
|
|
76
|
+
if (existingData) {
|
|
77
|
+
logger_1.default.info('Default data already exists, returning existing data');
|
|
78
|
+
return existingData;
|
|
121
79
|
}
|
|
122
80
|
logger_1.default.info('Creating default company and admin user...');
|
|
123
81
|
// Create default company
|
|
@@ -130,6 +88,13 @@ class SetupService {
|
|
|
130
88
|
.select()
|
|
131
89
|
.single();
|
|
132
90
|
if (companyError) {
|
|
91
|
+
if (this.isUniqueViolation(companyError)) {
|
|
92
|
+
const fallbackData = await this.fetchExistingDefaultData();
|
|
93
|
+
if (fallbackData) {
|
|
94
|
+
logger_1.default.info('Company already exists, reusing existing data');
|
|
95
|
+
return fallbackData;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
133
98
|
throw new Error(`Failed to create company: ${companyError.message}`);
|
|
134
99
|
}
|
|
135
100
|
logger_1.default.info(`✅ Company created: ${company.name} (${company.uuid})`);
|
|
@@ -146,6 +111,13 @@ class SetupService {
|
|
|
146
111
|
.select()
|
|
147
112
|
.single();
|
|
148
113
|
if (userError) {
|
|
114
|
+
if (this.isUniqueViolation(userError)) {
|
|
115
|
+
const fallbackData = await this.fetchExistingDefaultData();
|
|
116
|
+
if (fallbackData) {
|
|
117
|
+
logger_1.default.info('Admin user already exists, reusing existing data');
|
|
118
|
+
return fallbackData;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
149
121
|
throw new Error(`Failed to create user: ${userError.message}`);
|
|
150
122
|
}
|
|
151
123
|
logger_1.default.info(`✅ Admin user created: ${user.email} (${user.uuid})`);
|
|
@@ -190,6 +162,47 @@ class SetupService {
|
|
|
190
162
|
throw error;
|
|
191
163
|
}
|
|
192
164
|
}
|
|
165
|
+
isUniqueViolation(error) {
|
|
166
|
+
return error?.code === '23505' || error?.message?.toLowerCase().includes('duplicate key');
|
|
167
|
+
}
|
|
168
|
+
async fetchExistingDefaultData() {
|
|
169
|
+
const { data: existingCompany } = await this.supabase
|
|
170
|
+
.from('vezlo_companies')
|
|
171
|
+
.select('*')
|
|
172
|
+
.eq('domain', 'default')
|
|
173
|
+
.single();
|
|
174
|
+
if (!existingCompany) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const { data: profile } = await this.supabase
|
|
178
|
+
.from('vezlo_user_company_profiles')
|
|
179
|
+
.select('*, vezlo_users(*)')
|
|
180
|
+
.eq('company_id', existingCompany.id)
|
|
181
|
+
.eq('role', 'admin')
|
|
182
|
+
.single();
|
|
183
|
+
if (!profile || !profile.vezlo_users) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const user = profile.vezlo_users;
|
|
187
|
+
return {
|
|
188
|
+
success: true,
|
|
189
|
+
alreadyExists: true,
|
|
190
|
+
company: {
|
|
191
|
+
id: existingCompany.uuid,
|
|
192
|
+
name: existingCompany.name,
|
|
193
|
+
domain: existingCompany.domain
|
|
194
|
+
},
|
|
195
|
+
user: {
|
|
196
|
+
id: user.uuid,
|
|
197
|
+
email: user.email,
|
|
198
|
+
name: user.name
|
|
199
|
+
},
|
|
200
|
+
profile: {
|
|
201
|
+
id: profile.uuid,
|
|
202
|
+
role: profile.role
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
193
206
|
/**
|
|
194
207
|
* Check if setup is already completed
|
|
195
208
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SetupService.js","sourceRoot":"","sources":["../../../src/services/SetupService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,6CAAmD;AACnD,8DAAsC;AAEtC,MAAa,YAAY;IAGvB,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,qBAAqB;QAC1B,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,iBAAiB;YAChE,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,UAAU;YAC/D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO;SACtD,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,OAIvB;QACC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAE1D,
|
|
1
|
+
{"version":3,"file":"SetupService.js","sourceRoot":"","sources":["../../../src/services/SetupService.ts"],"names":[],"mappings":"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"}
|
package/knexfile.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
4
5
|
|
|
5
6
|
// Load environment variables
|
|
6
7
|
dotenv.config();
|
|
@@ -13,6 +14,36 @@ try {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
const projectRoot = fs.existsSync(path.join(__dirname, 'package.json'))
|
|
18
|
+
? __dirname
|
|
19
|
+
: path.join(__dirname, '..');
|
|
20
|
+
|
|
21
|
+
const srcMigrationsPath = path.join(projectRoot, 'src', 'migrations');
|
|
22
|
+
const distMigrationsPath = path.join(projectRoot, 'dist', 'src', 'migrations');
|
|
23
|
+
const tsMigrationProbe = path.join(srcMigrationsPath, '001_initial_schema.ts');
|
|
24
|
+
const jsMigrationProbe = path.join(distMigrationsPath, '001_initial_schema.js');
|
|
25
|
+
|
|
26
|
+
const hasTsMigrations = fs.existsSync(tsMigrationProbe);
|
|
27
|
+
const hasJsMigrations = fs.existsSync(jsMigrationProbe);
|
|
28
|
+
|
|
29
|
+
const resolvedMigrationsDirectory = hasTsMigrations
|
|
30
|
+
? srcMigrationsPath
|
|
31
|
+
: hasJsMigrations
|
|
32
|
+
? distMigrationsPath
|
|
33
|
+
: srcMigrationsPath;
|
|
34
|
+
|
|
35
|
+
const migrationExtension = hasTsMigrations ? 'ts' : (hasJsMigrations ? 'js' : 'ts');
|
|
36
|
+
const migrationLoadExtensions = migrationExtension === 'ts' ? ['.ts'] : ['.js'];
|
|
37
|
+
|
|
38
|
+
const supabaseMigrationsDirectory = fs.existsSync(distMigrationsPath)
|
|
39
|
+
? distMigrationsPath
|
|
40
|
+
: resolvedMigrationsDirectory;
|
|
41
|
+
const supabaseMigrationExtension = fs.existsSync(distMigrationsPath) ? 'js' : migrationExtension;
|
|
42
|
+
const supabaseSeedsDirectory = fs.existsSync(path.join(projectRoot, 'dist', 'src', 'seeds'))
|
|
43
|
+
? path.join(projectRoot, 'dist', 'src', 'seeds')
|
|
44
|
+
: path.join(projectRoot, 'src', 'seeds');
|
|
45
|
+
const supabaseSeedsAreJs = supabaseSeedsDirectory.endsWith(path.join('dist', 'src', 'seeds'));
|
|
46
|
+
|
|
16
47
|
const config: { [key: string]: Knex.Config } = {
|
|
17
48
|
development: {
|
|
18
49
|
client: 'postgresql',
|
|
@@ -29,9 +60,10 @@ const config: { [key: string]: Knex.Config } = {
|
|
|
29
60
|
max: 10
|
|
30
61
|
},
|
|
31
62
|
migrations: {
|
|
32
|
-
directory:
|
|
63
|
+
directory: resolvedMigrationsDirectory,
|
|
33
64
|
tableName: 'knex_migrations',
|
|
34
|
-
extension:
|
|
65
|
+
extension: migrationExtension,
|
|
66
|
+
loadExtensions: migrationLoadExtensions
|
|
35
67
|
},
|
|
36
68
|
seeds: {
|
|
37
69
|
directory: './src/seeds',
|
|
@@ -54,10 +86,11 @@ const config: { [key: string]: Knex.Config } = {
|
|
|
54
86
|
max: 20
|
|
55
87
|
},
|
|
56
88
|
migrations: {
|
|
57
|
-
// Use
|
|
58
|
-
directory:
|
|
89
|
+
// Use resolved path (prefers TS during development, JS in packaged builds)
|
|
90
|
+
directory: resolvedMigrationsDirectory,
|
|
59
91
|
tableName: 'knex_migrations',
|
|
60
|
-
extension:
|
|
92
|
+
extension: migrationExtension,
|
|
93
|
+
loadExtensions: migrationLoadExtensions
|
|
61
94
|
},
|
|
62
95
|
seeds: {
|
|
63
96
|
directory: path.join(__dirname, 'src/seeds'),
|
|
@@ -65,7 +98,7 @@ const config: { [key: string]: Knex.Config } = {
|
|
|
65
98
|
}
|
|
66
99
|
},
|
|
67
100
|
|
|
68
|
-
//
|
|
101
|
+
// Supabase (used by Vercel) always targets compiled JS migrations
|
|
69
102
|
supabase: {
|
|
70
103
|
client: 'postgresql',
|
|
71
104
|
connection: process.env.SUPABASE_DB_URL || process.env.DATABASE_URL || {
|
|
@@ -81,20 +114,14 @@ const config: { [key: string]: Knex.Config } = {
|
|
|
81
114
|
max: 10
|
|
82
115
|
},
|
|
83
116
|
migrations: {
|
|
84
|
-
|
|
85
|
-
// In development, use relative path
|
|
86
|
-
directory: process.env.NODE_ENV === 'production'
|
|
87
|
-
? path.join(__dirname, 'src/migrations')
|
|
88
|
-
: path.join(process.cwd(), 'src/migrations'),
|
|
117
|
+
directory: supabaseMigrationsDirectory,
|
|
89
118
|
tableName: 'knex_migrations',
|
|
90
|
-
extension:
|
|
91
|
-
loadExtensions:
|
|
119
|
+
extension: supabaseMigrationExtension,
|
|
120
|
+
loadExtensions: supabaseMigrationExtension === 'ts' ? ['.ts'] : ['.js']
|
|
92
121
|
},
|
|
93
122
|
seeds: {
|
|
94
|
-
directory:
|
|
95
|
-
|
|
96
|
-
: path.join(process.cwd(), 'src/seeds'),
|
|
97
|
-
extension: process.env.NODE_ENV === 'production' ? 'js' : 'ts'
|
|
123
|
+
directory: supabaseSeedsDirectory,
|
|
124
|
+
extension: supabaseSeedsAreJs ? 'js' : 'ts'
|
|
98
125
|
}
|
|
99
126
|
}
|
|
100
127
|
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vezlo/assistant-server",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Production-ready AI Assistant Server with vector search, conversation management, and real-time communication",
|
|
5
|
-
"main": "dist/server.js",
|
|
6
|
-
"types": "dist/server.d.ts",
|
|
5
|
+
"main": "dist/src/server.js",
|
|
6
|
+
"types": "dist/src/server.d.ts",
|
|
7
7
|
"bin": {
|
|
8
8
|
"vezlo-server": "./bin/vezlo-server.js",
|
|
9
9
|
"vezlo-setup": "./scripts/setup.js",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"@types/swagger-ui-express": "^4.1.6",
|
|
74
74
|
"@types/uuid": "^9.0.6",
|
|
75
75
|
"@vercel/node": "^3.0.0",
|
|
76
|
+
"ts-node": "^10.9.2",
|
|
76
77
|
"typescript": "^5.2.2"
|
|
77
78
|
},
|
|
78
79
|
"engines": {
|
package/scripts/entrypoint.sh
CHANGED
|
@@ -5,17 +5,57 @@
|
|
|
5
5
|
|
|
6
6
|
set -e
|
|
7
7
|
|
|
8
|
-
echo "
|
|
8
|
+
echo ""
|
|
9
|
+
echo "============================================"
|
|
10
|
+
echo "🚀 Starting Vezlo Server Initialization Flow"
|
|
11
|
+
echo "============================================"
|
|
12
|
+
echo ""
|
|
13
|
+
|
|
14
|
+
# Ensure production environment for migrations (uses compiled .js files)
|
|
15
|
+
export NODE_ENV=${NODE_ENV:-production}
|
|
9
16
|
|
|
10
17
|
# Wait for database to be ready (optional)
|
|
11
|
-
echo "Waiting for database connection..."
|
|
18
|
+
echo "🔌 Waiting for database connection..."
|
|
12
19
|
sleep 2
|
|
13
20
|
|
|
14
21
|
# Run migrations
|
|
15
|
-
echo "
|
|
22
|
+
echo ""
|
|
23
|
+
echo "--------------------------------------------"
|
|
24
|
+
echo "📦 Step 1: Running Database Migrations"
|
|
25
|
+
echo "--------------------------------------------"
|
|
16
26
|
npm run migrate:latest
|
|
17
27
|
|
|
28
|
+
# Give Supabase/DB cache time to refresh after migrations
|
|
29
|
+
echo "⏳ Allowing schema changes to propagate..."
|
|
30
|
+
sleep 5
|
|
31
|
+
|
|
32
|
+
# Seed default data (idempotent)
|
|
33
|
+
echo ""
|
|
34
|
+
echo "--------------------------------------------"
|
|
35
|
+
echo "🌱 Step 2: Seeding Default Data"
|
|
36
|
+
echo "--------------------------------------------"
|
|
37
|
+
if npm run seed-default; then
|
|
38
|
+
echo "🎉 Default data seed completed."
|
|
39
|
+
else
|
|
40
|
+
echo "⚠️ Seed step failed or data already exists. Continuing startup..."
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Generate API key (idempotent)
|
|
44
|
+
echo ""
|
|
45
|
+
echo "--------------------------------------------"
|
|
46
|
+
echo "🔑 Step 3: Generating Default API Key"
|
|
47
|
+
echo "--------------------------------------------"
|
|
48
|
+
if npm run generate-key; then
|
|
49
|
+
echo "🎯 API key generation step completed."
|
|
50
|
+
else
|
|
51
|
+
echo "⚠️ API key generation skipped or failed. Continuing startup..."
|
|
52
|
+
fi
|
|
53
|
+
|
|
18
54
|
# Start the application
|
|
19
|
-
echo "
|
|
55
|
+
echo ""
|
|
56
|
+
echo "============================================"
|
|
57
|
+
echo "✅ Initialization steps completed. Launching app..."
|
|
58
|
+
echo "============================================"
|
|
59
|
+
echo ""
|
|
20
60
|
exec "$@"
|
|
21
61
|
|
package/scripts/seed-default.js
CHANGED
|
File without changes
|
package/scripts/setup.js
CHANGED
|
@@ -9,6 +9,29 @@ const fs = require('fs');
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const readline = require('readline');
|
|
11
11
|
const { createClient } = require('@supabase/supabase-js');
|
|
12
|
+
const knexLib = require('knex');
|
|
13
|
+
const pkgRoot = path.join(__dirname, '..');
|
|
14
|
+
|
|
15
|
+
const migrationCandidates = [
|
|
16
|
+
path.join(pkgRoot, 'dist', 'src', 'migrations'),
|
|
17
|
+
path.join(pkgRoot, 'dist', 'migrations'),
|
|
18
|
+
path.join(pkgRoot, 'src', 'migrations'),
|
|
19
|
+
path.join(process.cwd(), 'dist', 'src', 'migrations'),
|
|
20
|
+
path.join(process.cwd(), 'src', 'migrations')
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const fallbackMigrationDir = path.join(pkgRoot, 'dist', 'src', 'migrations');
|
|
24
|
+
const migrationDirectory = migrationCandidates.find(dir => fs.existsSync(dir)) || fallbackMigrationDir;
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(migrationDirectory)) {
|
|
27
|
+
console.error(`❌ Migration directory not found. Expected one of:\n${migrationCandidates.concat(fallbackMigrationDir).join('\n')}`);
|
|
28
|
+
console.error('Run `npm run build` (or reinstall the package) to ensure compiled migrations exist.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const usingDistMigrations = migrationDirectory.includes(`${path.sep}dist${path.sep}`);
|
|
33
|
+
const migrationExtension = usingDistMigrations ? 'js' : 'ts';
|
|
34
|
+
const migrationLoadExtensions = migrationExtension === 'ts' ? ['.ts'] : ['.js'];
|
|
12
35
|
|
|
13
36
|
const rl = readline.createInterface({
|
|
14
37
|
input: process.stdin,
|
|
@@ -300,9 +323,13 @@ async function saveEnvFile(envPath, config) {
|
|
|
300
323
|
if (!config.MIGRATION_SECRET_KEY) {
|
|
301
324
|
config.MIGRATION_SECRET_KEY = crypto.randomBytes(32).toString('hex');
|
|
302
325
|
}
|
|
326
|
+
if (!config.JWT_SECRET) {
|
|
327
|
+
config.JWT_SECRET = crypto.randomBytes(32).toString('hex');
|
|
328
|
+
}
|
|
303
329
|
} catch (_) {
|
|
304
|
-
// Fallback simple
|
|
330
|
+
// Fallback simple values if crypto unavailable (very unlikely)
|
|
305
331
|
config.MIGRATION_SECRET_KEY = config.MIGRATION_SECRET_KEY || `msk_${Date.now()}`;
|
|
332
|
+
config.JWT_SECRET = config.JWT_SECRET || `jwt_${Date.now()}`;
|
|
306
333
|
}
|
|
307
334
|
const envContent = `# Vezlo Assistant Server Configuration
|
|
308
335
|
# Generated by setup wizard on ${new Date().toISOString()}
|
|
@@ -348,8 +375,16 @@ ASSISTANT_NAME=Vezlo Assistant
|
|
|
348
375
|
CHUNK_SIZE=1000
|
|
349
376
|
CHUNK_OVERLAP=200
|
|
350
377
|
|
|
378
|
+
# Chat History
|
|
379
|
+
CHAT_HISTORY_LENGTH=${config.CHAT_HISTORY_LENGTH || '2'}
|
|
380
|
+
|
|
351
381
|
# Migration Security
|
|
352
382
|
MIGRATION_SECRET_KEY=${config.MIGRATION_SECRET_KEY}
|
|
383
|
+
|
|
384
|
+
# Authentication / Defaults
|
|
385
|
+
JWT_SECRET=${config.JWT_SECRET}
|
|
386
|
+
DEFAULT_ADMIN_EMAIL=${config.DEFAULT_ADMIN_EMAIL || 'admin@vezlo.org'}
|
|
387
|
+
DEFAULT_ADMIN_PASSWORD=${config.DEFAULT_ADMIN_PASSWORD || 'admin123'}
|
|
353
388
|
`;
|
|
354
389
|
|
|
355
390
|
fs.writeFileSync(envPath, envContent, 'utf8');
|
|
@@ -459,15 +494,7 @@ async function setupMigrations(config, validationStatus) {
|
|
|
459
494
|
if (runMigrations.toLowerCase() === 'y') {
|
|
460
495
|
log('🔄 Running migrations...', 'yellow');
|
|
461
496
|
|
|
462
|
-
|
|
463
|
-
process.env.SUPABASE_DB_HOST = config.SUPABASE_DB_HOST;
|
|
464
|
-
process.env.SUPABASE_DB_PORT = config.SUPABASE_DB_PORT;
|
|
465
|
-
process.env.SUPABASE_DB_NAME = config.SUPABASE_DB_NAME;
|
|
466
|
-
process.env.SUPABASE_DB_USER = config.SUPABASE_DB_USER;
|
|
467
|
-
process.env.SUPABASE_DB_PASSWORD = config.SUPABASE_DB_PASSWORD;
|
|
468
|
-
|
|
469
|
-
const { execSync } = require('child_process');
|
|
470
|
-
execSync('npm run migrate:latest', { stdio: 'inherit' });
|
|
497
|
+
await runMigrationsWithConfig(config);
|
|
471
498
|
|
|
472
499
|
log('✅ Migrations completed successfully!', 'green');
|
|
473
500
|
return { migrations: 'success' };
|
|
@@ -491,8 +518,7 @@ async function setupMigrations(config, validationStatus) {
|
|
|
491
518
|
if (runPending.toLowerCase() === 'y') {
|
|
492
519
|
log('🔄 Checking for pending migrations...', 'yellow');
|
|
493
520
|
|
|
494
|
-
|
|
495
|
-
execSync('npm run migrate:latest', { stdio: 'inherit' });
|
|
521
|
+
await runMigrationsWithConfig(config);
|
|
496
522
|
|
|
497
523
|
log('✅ Migration check completed!', 'green');
|
|
498
524
|
await client.end();
|
|
@@ -531,6 +557,34 @@ main().catch(error => {
|
|
|
531
557
|
rl.close();
|
|
532
558
|
process.exit(1);
|
|
533
559
|
});
|
|
560
|
+
|
|
561
|
+
async function runMigrationsWithConfig(config) {
|
|
562
|
+
const knexInstance = knexLib({
|
|
563
|
+
client: 'postgresql',
|
|
564
|
+
connection: {
|
|
565
|
+
host: config.SUPABASE_DB_HOST,
|
|
566
|
+
port: parseInt(config.SUPABASE_DB_PORT),
|
|
567
|
+
database: config.SUPABASE_DB_NAME,
|
|
568
|
+
user: config.SUPABASE_DB_USER,
|
|
569
|
+
password: config.SUPABASE_DB_PASSWORD,
|
|
570
|
+
ssl: { rejectUnauthorized: false }
|
|
571
|
+
},
|
|
572
|
+
migrations: {
|
|
573
|
+
directory: migrationDirectory,
|
|
574
|
+
tableName: 'knex_migrations',
|
|
575
|
+
extension: migrationExtension,
|
|
576
|
+
loadExtensions: migrationLoadExtensions
|
|
577
|
+
},
|
|
578
|
+
pool: { min: 0, max: 10 }
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
await knexInstance.migrate.latest();
|
|
583
|
+
} finally {
|
|
584
|
+
await knexInstance.destroy();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
534
588
|
async function setupDefaultData(config) {
|
|
535
589
|
log('🔄 Setting up default company and admin user...', 'yellow');
|
|
536
590
|
|