@vezlo/assistant-server 1.4.0 → 2.0.0

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 (107) hide show
  1. package/README.md +56 -4
  2. package/database-schema.sql +193 -33
  3. package/dist/knexfile.d.ts.map +1 -1
  4. package/dist/knexfile.js +17 -8
  5. package/dist/knexfile.js.map +1 -1
  6. package/dist/src/config/database.d.ts.map +1 -1
  7. package/dist/src/config/database.js +9 -1
  8. package/dist/src/config/database.js.map +1 -1
  9. package/dist/src/config/knex.d.ts.map +1 -1
  10. package/dist/src/config/knex.js +22 -2
  11. package/dist/src/config/knex.js.map +1 -1
  12. package/dist/src/config/swagger.d.ts.map +1 -1
  13. package/dist/src/config/swagger.js +18 -71
  14. package/dist/src/config/swagger.js.map +1 -1
  15. package/dist/src/controllers/ApiKeyController.d.ts +17 -0
  16. package/dist/src/controllers/ApiKeyController.d.ts.map +1 -0
  17. package/dist/src/controllers/ApiKeyController.js +84 -0
  18. package/dist/src/controllers/ApiKeyController.js.map +1 -0
  19. package/dist/src/controllers/AuthController.d.ts +14 -0
  20. package/dist/src/controllers/AuthController.d.ts.map +1 -0
  21. package/dist/src/controllers/AuthController.js +212 -0
  22. package/dist/src/controllers/AuthController.js.map +1 -0
  23. package/dist/src/controllers/ChatController.d.ts +8 -5
  24. package/dist/src/controllers/ChatController.d.ts.map +1 -1
  25. package/dist/src/controllers/ChatController.js +139 -31
  26. package/dist/src/controllers/ChatController.js.map +1 -1
  27. package/dist/src/controllers/KnowledgeController.d.ts +5 -4
  28. package/dist/src/controllers/KnowledgeController.d.ts.map +1 -1
  29. package/dist/src/controllers/KnowledgeController.js +54 -16
  30. package/dist/src/controllers/KnowledgeController.js.map +1 -1
  31. package/dist/src/middleware/auth.d.ts +51 -0
  32. package/dist/src/middleware/auth.d.ts.map +1 -0
  33. package/dist/src/middleware/auth.js +232 -0
  34. package/dist/src/middleware/auth.js.map +1 -0
  35. package/dist/src/middleware/errorHandler.d.ts.map +1 -1
  36. package/dist/src/middleware/errorHandler.js +13 -19
  37. package/dist/src/middleware/errorHandler.js.map +1 -1
  38. package/dist/src/migrations/001_initial_schema.d.ts.map +1 -1
  39. package/dist/src/migrations/001_initial_schema.js +39 -64
  40. package/dist/src/migrations/001_initial_schema.js.map +1 -1
  41. package/dist/src/migrations/002_multitenancy_schema.d.ts +4 -0
  42. package/dist/src/migrations/002_multitenancy_schema.d.ts.map +1 -0
  43. package/dist/src/migrations/002_multitenancy_schema.js +119 -0
  44. package/dist/src/migrations/002_multitenancy_schema.js.map +1 -0
  45. package/dist/src/schemas/AuthSchemas.d.ts +89 -0
  46. package/dist/src/schemas/AuthSchemas.d.ts.map +1 -0
  47. package/dist/src/schemas/AuthSchemas.js +63 -0
  48. package/dist/src/schemas/AuthSchemas.js.map +1 -0
  49. package/dist/src/schemas/CommonSchemas.d.ts +62 -0
  50. package/dist/src/schemas/CommonSchemas.d.ts.map +1 -0
  51. package/dist/src/schemas/CommonSchemas.js +65 -0
  52. package/dist/src/schemas/CommonSchemas.js.map +1 -0
  53. package/dist/src/schemas/ConversationSchemas.d.ts +64 -27
  54. package/dist/src/schemas/ConversationSchemas.d.ts.map +1 -1
  55. package/dist/src/schemas/ConversationSchemas.js +28 -9
  56. package/dist/src/schemas/ConversationSchemas.js.map +1 -1
  57. package/dist/src/schemas/FeedbackSchemas.d.ts +43 -5
  58. package/dist/src/schemas/FeedbackSchemas.d.ts.map +1 -1
  59. package/dist/src/schemas/FeedbackSchemas.js +20 -2
  60. package/dist/src/schemas/FeedbackSchemas.js.map +1 -1
  61. package/dist/src/schemas/KnowledgeSchemas.d.ts +114 -35
  62. package/dist/src/schemas/KnowledgeSchemas.d.ts.map +1 -1
  63. package/dist/src/schemas/KnowledgeSchemas.js +58 -16
  64. package/dist/src/schemas/KnowledgeSchemas.js.map +1 -1
  65. package/dist/src/schemas/MessageSchemas.d.ts +57 -8
  66. package/dist/src/schemas/MessageSchemas.d.ts.map +1 -1
  67. package/dist/src/schemas/MessageSchemas.js +22 -3
  68. package/dist/src/schemas/MessageSchemas.js.map +1 -1
  69. package/dist/src/schemas/index.d.ts +410 -68
  70. package/dist/src/schemas/index.d.ts.map +1 -1
  71. package/dist/src/schemas/index.js +8 -2
  72. package/dist/src/schemas/index.js.map +1 -1
  73. package/dist/src/server.js +1047 -613
  74. package/dist/src/server.js.map +1 -1
  75. package/dist/src/services/AIService.d.ts +1 -1
  76. package/dist/src/services/AIService.d.ts.map +1 -1
  77. package/dist/src/services/AIService.js +6 -2
  78. package/dist/src/services/AIService.js.map +1 -1
  79. package/dist/src/services/ApiKeyService.d.ts +38 -0
  80. package/dist/src/services/ApiKeyService.d.ts.map +1 -0
  81. package/dist/src/services/ApiKeyService.js +123 -0
  82. package/dist/src/services/ApiKeyService.js.map +1 -0
  83. package/dist/src/services/KnowledgeBaseService.d.ts +2 -2
  84. package/dist/src/services/KnowledgeBaseService.d.ts.map +1 -1
  85. package/dist/src/services/KnowledgeBaseService.js +9 -2
  86. package/dist/src/services/KnowledgeBaseService.js.map +1 -1
  87. package/dist/src/services/MigrationService.d.ts +1 -1
  88. package/dist/src/services/MigrationService.d.ts.map +1 -1
  89. package/dist/src/services/MigrationService.js +4 -8
  90. package/dist/src/services/MigrationService.js.map +1 -1
  91. package/dist/src/services/SetupService.d.ts +102 -0
  92. package/dist/src/services/SetupService.d.ts.map +1 -0
  93. package/dist/src/services/SetupService.js +343 -0
  94. package/dist/src/services/SetupService.js.map +1 -0
  95. package/dist/src/storage/ConversationRepository.d.ts.map +1 -1
  96. package/dist/src/storage/ConversationRepository.js +42 -8
  97. package/dist/src/storage/ConversationRepository.js.map +1 -1
  98. package/dist/src/storage/MessageRepository.d.ts.map +1 -1
  99. package/dist/src/storage/MessageRepository.js +23 -27
  100. package/dist/src/storage/MessageRepository.js.map +1 -1
  101. package/env.example +5 -0
  102. package/knexfile.ts +17 -8
  103. package/package.json +10 -2
  104. package/scripts/generate-key.js +124 -0
  105. package/scripts/seed-default.js +72 -0
  106. package/scripts/setup.js +148 -13
  107. package/scripts/validate-db.js +22 -6
package/knexfile.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
2
  import dotenv from 'dotenv';
3
+ const path = require('path');
3
4
 
4
5
  // Load environment variables
5
6
  dotenv.config();
@@ -53,13 +54,14 @@ const config: { [key: string]: Knex.Config } = {
53
54
  max: 20
54
55
  },
55
56
  migrations: {
56
- directory: './src/migrations',
57
+ // Use absolute path based on __dirname (knexfile.js location in dist/)
58
+ directory: path.join(__dirname, 'src/migrations'),
57
59
  tableName: 'knex_migrations',
58
- extension: 'ts'
60
+ extension: 'js'
59
61
  },
60
62
  seeds: {
61
- directory: './src/seeds',
62
- extension: 'ts'
63
+ directory: path.join(__dirname, 'src/seeds'),
64
+ extension: 'js'
63
65
  }
64
66
  },
65
67
 
@@ -79,13 +81,20 @@ const config: { [key: string]: Knex.Config } = {
79
81
  max: 10
80
82
  },
81
83
  migrations: {
82
- directory: './src/migrations',
84
+ // In production (Vercel), knexfile.js is in dist/, so use absolute path
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'),
83
89
  tableName: 'knex_migrations',
84
- extension: 'ts'
90
+ extension: process.env.NODE_ENV === 'production' ? 'js' : 'ts',
91
+ loadExtensions: process.env.NODE_ENV === 'production' ? ['.js'] : ['.ts']
85
92
  },
86
93
  seeds: {
87
- directory: './src/seeds',
88
- extension: 'ts'
94
+ directory: process.env.NODE_ENV === 'production'
95
+ ? path.join(__dirname, 'src/seeds')
96
+ : path.join(process.cwd(), 'src/seeds'),
97
+ extension: process.env.NODE_ENV === 'production' ? 'js' : 'ts'
89
98
  }
90
99
  }
91
100
  };
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@vezlo/assistant-server",
3
- "version": "1.4.0",
3
+ "version": "2.0.0",
4
4
  "description": "Production-ready AI Assistant Server with vector search, conversation management, and real-time communication",
5
5
  "main": "dist/server.js",
6
6
  "types": "dist/server.d.ts",
7
7
  "bin": {
8
8
  "vezlo-server": "./bin/vezlo-server.js",
9
9
  "vezlo-setup": "./scripts/setup.js",
10
- "vezlo-validate": "./scripts/validate-db.js"
10
+ "vezlo-validate": "./scripts/validate-db.js",
11
+ "vezlo-seed-default": "./scripts/seed-default.js",
12
+ "vezlo-generate-key": "./scripts/generate-key.js"
11
13
  },
12
14
  "files": [
13
15
  "dist/",
@@ -27,6 +29,8 @@
27
29
  "start": "node dist/src/server.js",
28
30
  "prepublishOnly": "npm run build",
29
31
  "setup": "node scripts/setup.js",
32
+ "seed-default": "node scripts/seed-default.js",
33
+ "generate-key": "node scripts/generate-key.js",
30
34
  "validate": "node scripts/validate-db.js",
31
35
  "migrate:make": "knex migrate:make",
32
36
  "migrate:latest": "knex migrate:latest",
@@ -39,12 +43,16 @@
39
43
  },
40
44
  "dependencies": {
41
45
  "@supabase/supabase-js": "^2.38.0",
46
+ "@types/bcryptjs": "^2.4.6",
47
+ "@types/jsonwebtoken": "^9.0.10",
48
+ "bcryptjs": "^3.0.2",
42
49
  "compression": "^1.7.4",
43
50
  "cors": "^2.8.5",
44
51
  "dotenv": "^16.3.1",
45
52
  "express": "^4.18.2",
46
53
  "express-rate-limit": "^7.1.5",
47
54
  "helmet": "^7.1.0",
55
+ "jsonwebtoken": "^9.0.2",
48
56
  "knex": "^3.1.0",
49
57
  "openai": "^4.20.1",
50
58
  "pg": "^8.11.3",
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Generate API Key Script for Vezlo Assistant Server
5
+ * Creates an API key for the default admin's company
6
+ */
7
+
8
+ const { config } = require('dotenv');
9
+ const { initializeSupabase } = require('../dist/src/config/database.js');
10
+ const { SetupService } = require('../dist/src/services/SetupService.js');
11
+ const { ApiKeyService } = require('../dist/src/services/ApiKeyService.js');
12
+ const logger = require('../dist/src/config/logger.js');
13
+
14
+ // Load environment variables
15
+ config();
16
+
17
+ async function generateApiKey(options = { quiet: false }) {
18
+ try {
19
+ if (!options.quiet) console.log('🔑 Starting API Key Generation...\n');
20
+
21
+ // Initialize Supabase
22
+ const supabase = initializeSupabase();
23
+
24
+ // Wait for schema cache to refresh
25
+ if (!options.quiet) console.log('⏳ Waiting for schema cache to refresh...');
26
+ await new Promise(resolve => setTimeout(resolve, 2000));
27
+
28
+ // Get default credentials from environment
29
+ const credentials = SetupService.getDefaultCredentials();
30
+ if (!options.quiet) console.log(`🔍 Using admin email: ${credentials.adminEmail}`);
31
+
32
+ // Check if default company and admin exist
33
+ if (!options.quiet) console.log('🔍 Checking for default company and admin...');
34
+
35
+ // Find the admin user
36
+ const { data: user, error: userError } = await supabase
37
+ .from('vezlo_users')
38
+ .select('id, uuid, name')
39
+ .eq('email', credentials.adminEmail)
40
+ .single();
41
+
42
+ if (userError || !user) {
43
+ throw new Error(`Admin user not found (${credentials.adminEmail}). Run seed-default first.`);
44
+ }
45
+
46
+ if (!options.quiet) console.log(`✅ Found admin user: ${user.name} (${user.uuid})`);
47
+
48
+ // Find the admin's company profile
49
+ const { data: profile, error: profileError } = await supabase
50
+ .from('vezlo_user_company_profiles')
51
+ .select(`
52
+ id,
53
+ role,
54
+ company_id,
55
+ companies:company_id(
56
+ id,
57
+ uuid,
58
+ name,
59
+ domain
60
+ )
61
+ `)
62
+ .eq('user_id', user.id)
63
+ .eq('role', 'admin')
64
+ .single();
65
+
66
+ if (profileError || !profile) {
67
+ throw new Error(`Admin profile not found. Run seed-default first.`);
68
+ }
69
+
70
+ if (!options.quiet) console.log(`✅ Found company: ${profile.companies.name} (${profile.companies.uuid})`);
71
+
72
+ // Generate the API key - use joined company ID with fallback to direct company_id
73
+ const apiKeyService = new ApiKeyService(supabase);
74
+ const companyId = profile.companies?.id || profile.company_id;
75
+ if (!companyId) {
76
+ throw new Error('Could not determine company ID from profile');
77
+ }
78
+ const { uuid, apiKey } = await apiKeyService.generateApiKey(companyId);
79
+
80
+ if (!options.quiet) {
81
+ // Display success summary
82
+ console.log('\n🎉 API Key Generated Successfully!');
83
+ console.log('=====================================');
84
+ console.log('📋 API Key Details:');
85
+ console.log(` Company: ${profile.companies.name}`);
86
+ console.log(` API Key: ${apiKey}`);
87
+ console.log('');
88
+ console.log('⚠️ IMPORTANT: Save this key securely. It will not be shown again.');
89
+ console.log('');
90
+ console.log('🔧 Usage Example:');
91
+ console.log(' curl -X POST https://your-server/api/knowledge/items \\');
92
+ console.log(' -H "X-API-Key: ' + apiKey + '" \\');
93
+ console.log(' -H "Content-Type: application/json" \\');
94
+ console.log(' -d \'{"title": "Example", "type": "document", "content": "Example content"}\'');
95
+ console.log('');
96
+ }
97
+
98
+ // Return the generated API key details
99
+ return {
100
+ success: true,
101
+ uuid,
102
+ apiKey,
103
+ company: profile.companies.name,
104
+ user: {
105
+ name: user.name,
106
+ uuid: user.uuid
107
+ }
108
+ };
109
+
110
+ } catch (error) {
111
+ console.error('❌ API key generation failed:', error.message);
112
+ if (!options.quiet) {
113
+ process.exit(1);
114
+ }
115
+ return { success: false, error: error.message };
116
+ }
117
+ }
118
+
119
+ // Run if called directly
120
+ if (require.main === module) {
121
+ generateApiKey();
122
+ }
123
+
124
+ module.exports = { generateApiKey };
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Default Data Setup Script for Vezlo Assistant Server
5
+ * Creates default company and admin user
6
+ */
7
+
8
+ const { config } = require('dotenv');
9
+ const { initializeSupabase } = require('../dist/src/config/database.js');
10
+ const { SetupService } = require('../dist/src/services/SetupService.js');
11
+ const logger = require('../dist/src/config/logger.js');
12
+
13
+ // Load environment variables
14
+ config();
15
+
16
+ async function runDefaultSetup() {
17
+ try {
18
+ console.log('🚀 Starting Default Data Setup...\n');
19
+
20
+ // Initialize Supabase
21
+ const supabase = initializeSupabase();
22
+
23
+ // Wait for schema cache to refresh (Supabase needs time after migrations)
24
+ console.log('⏳ Waiting for schema cache to refresh...');
25
+ await new Promise(resolve => setTimeout(resolve, 2000));
26
+
27
+ const setupService = new SetupService(supabase);
28
+
29
+ // Check if setup is already completed
30
+ const status = await setupService.getSetupStatus();
31
+ if (status.completed) {
32
+ console.log('✅ Default data already exists!');
33
+ console.log(`🏢 Company: ${status.company?.name}`);
34
+ console.log(`👤 Admin User: ${status.adminUser?.email}`);
35
+ return;
36
+ }
37
+
38
+ // Get setup parameters from service (already required at top)
39
+ const credentials = SetupService.getDefaultCredentials();
40
+
41
+ console.log('📋 Setup Configuration:');
42
+ console.log(` Company Name: ${credentials.companyName}`);
43
+ console.log(` Admin Email: ${credentials.adminEmail}`);
44
+ console.log(` Admin Password: ${credentials.adminPassword}`);
45
+ console.log('');
46
+
47
+ // Create default data
48
+ const result = await setupService.createDefaultData(credentials);
49
+
50
+ // Display success summary
51
+ console.log('\n🎉 Default Data Setup Completed!');
52
+ console.log('=====================================');
53
+ console.log('📋 Default Admin Credentials:');
54
+ console.log('');
55
+ console.log(` Company Name: ${result.company.name}`);
56
+ console.log(` Admin Email: ${result.user.email}`);
57
+ console.log(` Admin Password: ${credentials.adminPassword}`);
58
+ console.log(` Admin Name: ${result.user.name}`);
59
+ console.log('');
60
+
61
+ } catch (error) {
62
+ console.error('❌ Setup failed:', error);
63
+ process.exit(1);
64
+ }
65
+ }
66
+
67
+ // Run setup if called directly
68
+ if (require.main === module) {
69
+ runDefaultSetup();
70
+ }
71
+
72
+ module.exports = { runDefaultSetup };
package/scripts/setup.js CHANGED
@@ -97,6 +97,31 @@ async function main() {
97
97
 
98
98
  const migrationStatus = await setupMigrations(config, validationStatus) || { migrations: validationStatus.database === 'success' ? 'success' : 'skipped' };
99
99
 
100
+ // Step 6: Default Data Setup (only if migrations succeeded)
101
+ if (migrationStatus.migrations === 'success') {
102
+ log('\n═══════════════════════════════════════════════════════════', 'cyan');
103
+ log(' STEP 6: Default Data Setup', 'bright');
104
+ log('═══════════════════════════════════════════════════════════\n', 'cyan');
105
+
106
+ const defaultDataStatus = await setupDefaultData(config);
107
+ migrationStatus.defaultData = defaultDataStatus;
108
+
109
+ // Step 7: API Key Generation (only if default data setup succeeded)
110
+ if (defaultDataStatus === 'success') {
111
+ log('\n═══════════════════════════════════════════════════════════', 'cyan');
112
+ log(' STEP 7: API Key Generation', 'bright');
113
+ log('═══════════════════════════════════════════════════════════\n', 'cyan');
114
+
115
+ const apiKeyStatus = await setupApiKey(config);
116
+ migrationStatus.apiKey = apiKeyStatus;
117
+ } else {
118
+ migrationStatus.apiKey = 'skipped';
119
+ }
120
+ } else {
121
+ migrationStatus.defaultData = 'skipped';
122
+ migrationStatus.apiKey = 'skipped';
123
+ }
124
+
100
125
  // Final Instructions / Summary
101
126
  log('\n═══════════════════════════════════════════════════════════', 'green');
102
127
  log(' 🎉 Setup Complete!', 'bright');
@@ -108,12 +133,29 @@ async function main() {
108
133
  log(` Supabase API: ${supaStatus === 'OK' ? colors.green + 'OK' : supaStatus === 'FAILED' ? colors.red + 'FAILED' : colors.yellow + 'UNKNOWN'}${colors.reset}`);
109
134
  log(` Database: ${validationStatus.database === 'success' ? colors.green + 'OK' : colors.red + (validationStatus.database === 'skipped' ? 'SKIPPED' : 'FAILED')}${colors.reset}`);
110
135
  log(` Migrations: ${migrationStatus.migrations === 'success' ? colors.green + 'OK' : migrationStatus.migrations === 'skipped' ? colors.yellow + 'SKIPPED' : colors.red + 'FAILED'}${colors.reset}`);
136
+ log(` Default Data: ${migrationStatus.defaultData === 'success' ? colors.green + 'OK' : migrationStatus.defaultData === 'skipped' ? colors.yellow + 'SKIPPED' : colors.red + 'FAILED'}${colors.reset}`);
137
+ log(` API Key: ${migrationStatus.apiKey === 'success' ? colors.green + 'OK' : migrationStatus.apiKey === 'skipped' ? colors.yellow + 'SKIPPED' : colors.red + 'FAILED'}${colors.reset}`);
111
138
 
112
139
  log('\nNext steps:');
113
140
  log(' 1. Review your .env file');
114
141
  if (migrationStatus.migrations !== 'success') {
142
+ log('\n⚠️ IMPORTANT: Migrations were not run. You must run migrations first before seeding default data.', 'yellow');
115
143
  log(' 2. Run database migrations: ' + colors.bright + 'npm run migrate:latest' + colors.reset);
116
- log(' Or via API (after starting server): ' + colors.bright + 'GET /api/migrate?key=$MIGRATION_SECRET_KEY' + colors.reset);
144
+ log(' 3. Then run seed: ' + colors.bright + 'npm run seed-default' + colors.reset + ' (only after migrations complete)', 'yellow');
145
+ log(' 4. Generate API key: ' + colors.bright + 'npm run generate-key' + colors.reset + ' (if not already done)');
146
+ log(' 5. Start the server: ' + colors.bright + 'vezlo-server' + colors.reset);
147
+ log(' 6. Visit: ' + colors.bright + 'http://localhost:3000/health' + colors.reset);
148
+ log(' 7. API docs: ' + colors.bright + 'http://localhost:3000/docs' + colors.reset);
149
+ log(' 8. Test API: ' + colors.bright + 'curl http://localhost:3000/health' + colors.reset + '\n');
150
+ } else if (migrationStatus.defaultData !== 'success') {
151
+ log(' 2. Setup default data: ' + colors.bright + 'npm run seed-default' + colors.reset);
152
+ log(' 3. Generate API key: ' + colors.bright + 'npm run generate-key' + colors.reset + ' (after default data is created)');
153
+ log(' 4. Start the server: ' + colors.bright + 'vezlo-server' + colors.reset);
154
+ log(' 5. Visit: ' + colors.bright + 'http://localhost:3000/health' + colors.reset);
155
+ log(' 6. API docs: ' + colors.bright + 'http://localhost:3000/docs' + colors.reset);
156
+ log(' 7. Test API: ' + colors.bright + 'curl http://localhost:3000/health' + colors.reset + '\n');
157
+ } else if (migrationStatus.apiKey !== 'success') {
158
+ log(' 2. Generate API key: ' + colors.bright + 'npm run generate-key' + colors.reset + ' (for library integration)');
117
159
  log(' 3. Start the server: ' + colors.bright + 'vezlo-server' + colors.reset);
118
160
  log(' 4. Visit: ' + colors.bright + 'http://localhost:3000/health' + colors.reset);
119
161
  log(' 5. API docs: ' + colors.bright + 'http://localhost:3000/docs' + colors.reset);
@@ -165,14 +207,22 @@ async function setupSupabase() {
165
207
  const client = createClient(supabaseUrl.trim(), supabaseServiceKey.trim());
166
208
  const { error } = await client.from('vezlo_conversations').select('count').limit(0);
167
209
 
168
- if (error && error.code !== 'PGRST116') {
169
- throw error;
210
+ if (error) {
211
+ // Check for table not found errors (normal before migrations run)
212
+ if (error.code === 'PGRST116' ||
213
+ error.message.includes('does not exist') ||
214
+ error.message.includes('Could not find the table')) {
215
+ log('✅ Supabase connection successful!', 'green');
216
+ log('⚠️ Note: Table not found - this is normal before running migrations\n', 'yellow');
217
+ } else {
218
+ throw error;
219
+ }
220
+ } else {
221
+ log('✅ Supabase connection successful!\n', 'green');
170
222
  }
171
-
172
- log('✅ Supabase connection successful!\n', 'green');
173
223
  } catch (err) {
174
224
  log(`❌ Supabase connection failed: ${err.message}`, 'red');
175
- log('⚠️ Continuing setup. You can fix credentials and rerun validations later.', 'yellow');
225
+ log('⚠️ This might be because migrations haven\'t run yet, or check your credentials.', 'yellow');
176
226
  }
177
227
 
178
228
  // Validate database connection (same as validate script)
@@ -314,11 +364,19 @@ async function validateEnvironment(config) {
314
364
  const client = createClient(config.SUPABASE_URL, config.SUPABASE_SERVICE_KEY);
315
365
  const { error } = await client.from('vezlo_conversations').select('count').limit(0);
316
366
 
317
- if (error && error.code !== 'PGRST116') {
318
- throw error;
367
+ if (error) {
368
+ // Check for table not found errors (normal before migrations run)
369
+ if (error.code === 'PGRST116' ||
370
+ error.message.includes('does not exist') ||
371
+ error.message.includes('Could not find the table')) {
372
+ log('✅ Supabase API connection validated', 'green');
373
+ log('⚠️ Note: Table not found - this is normal before running migrations', 'yellow');
374
+ } else {
375
+ throw error;
376
+ }
377
+ } else {
378
+ log('✅ Supabase API connection validated', 'green');
319
379
  }
320
-
321
- log('✅ Supabase API connection validated', 'green');
322
380
  } catch (err) {
323
381
  log(`❌ Supabase API validation failed: ${err.message}`, 'red');
324
382
  // non-blocking; proceed to DB check anyway
@@ -414,9 +472,10 @@ async function setupMigrations(config, validationStatus) {
414
472
  log('✅ Migrations completed successfully!', 'green');
415
473
  return { migrations: 'success' };
416
474
  } else {
417
- log('\n⚠️ Migrations skipped. You can run them later using:', 'yellow');
418
- log(' npm run migrate:latest', 'cyan');
419
- log(' Or via API: GET /api/migrate?key=your-migration-secret\n', 'cyan');
475
+ log('\n⚠️ Migrations skipped by user.', 'yellow');
476
+ log(' You can run them later using: ' + colors.cyan + 'npm run migrate:latest' + colors.reset, 'yellow');
477
+ log(' Or via API: ' + colors.cyan + 'GET /api/migrate?key=your-migration-secret' + colors.reset, 'yellow');
478
+ log('\n ⚠️ Note: Default data seeding will be skipped until migrations are run.\n', 'yellow');
420
479
  return { migrations: 'skipped' };
421
480
  }
422
481
  } else {
@@ -436,11 +495,20 @@ async function setupMigrations(config, validationStatus) {
436
495
  execSync('npm run migrate:latest', { stdio: 'inherit' });
437
496
 
438
497
  log('✅ Migration check completed!', 'green');
498
+ await client.end();
439
499
  return { migrations: 'success' };
500
+ } else {
501
+ log('⚠️ Migration check skipped by user.', 'yellow');
502
+ log(' You can run them later using: ' + colors.cyan + 'npm run migrate:latest' + colors.reset, 'yellow');
503
+ log(' Or via API: ' + colors.cyan + 'GET /api/migrate?key=your-migration-secret' + colors.reset, 'yellow');
504
+ log('\n ⚠️ Note: Default data seeding will be skipped until migrations are run.\n', 'yellow');
505
+ await client.end();
506
+ return { migrations: 'skipped' };
440
507
  }
441
508
  }
442
509
 
443
510
  await client.end();
511
+ return { migrations: 'skipped' };
444
512
  } catch (err) {
445
513
  log(`❌ Migration setup failed: ${err.message}`, 'red');
446
514
  log('\nYou can run migrations manually later:', 'yellow');
@@ -463,3 +531,70 @@ main().catch(error => {
463
531
  rl.close();
464
532
  process.exit(1);
465
533
  });
534
+ async function setupDefaultData(config) {
535
+ log('🔄 Setting up default company and admin user...', 'yellow');
536
+
537
+ try {
538
+ // Import the setup service dynamically
539
+ const { runDefaultSetup } = await import('./seed-default.js');
540
+
541
+ // Set environment variables for the setup
542
+ process.env.SUPABASE_URL = config.SUPABASE_URL;
543
+ process.env.SUPABASE_SERVICE_KEY = config.SUPABASE_SERVICE_KEY;
544
+ process.env.DEFAULT_ADMIN_EMAIL = config.DEFAULT_ADMIN_EMAIL || 'admin@vezlo.org';
545
+ process.env.DEFAULT_ADMIN_PASSWORD = config.DEFAULT_ADMIN_PASSWORD || 'admin123';
546
+ process.env.ORGANIZATION_NAME = config.ORGANIZATION_NAME || 'Vezlo';
547
+ process.env.JWT_SECRET = config.JWT_SECRET || require('crypto').randomBytes(32).toString('hex');
548
+
549
+ // Run the default setup
550
+ await runDefaultSetup();
551
+
552
+ log('✅ Default data setup completed successfully!', 'green');
553
+ return 'success';
554
+ } catch (err) {
555
+ log(`❌ Default data setup failed: ${err.message}`, 'red');
556
+ log('\nYou can run default data setup manually later:', 'yellow');
557
+ log(' npm run seed-default', 'cyan');
558
+ return 'failed';
559
+ }
560
+ }
561
+
562
+ async function setupApiKey(config) {
563
+ log('🔄 Generating API key for library integration...', 'yellow');
564
+
565
+ try {
566
+ // Import the API key generator dynamically
567
+ const { generateApiKey } = await import('./generate-key.js');
568
+
569
+ // Set environment variables for the setup (already set in setupDefaultData)
570
+
571
+ // Run the API key generator in quiet mode
572
+ const result = await generateApiKey({ quiet: true });
573
+
574
+ if (result.success) {
575
+ // Show API key details
576
+ log('✅ API key generated successfully!', 'green');
577
+ log('\n📋 API Key Details:', 'bright');
578
+ log(` Company: ${result.company}`, 'reset');
579
+ log(` User: ${result.user.name}`, 'reset');
580
+ log(` API Key: ${result.apiKey}`, 'bright');
581
+ log('\n⚠️ IMPORTANT: Save this key securely. It will not be shown again.', 'yellow');
582
+
583
+ // Show usage example
584
+ log('\n🔧 Usage Example:', 'bright');
585
+ log(` curl -X POST http://localhost:3000/api/knowledge/items \\
586
+ -H "X-API-Key: ${result.apiKey}" \\
587
+ -H "Content-Type: application/json" \\
588
+ -d '{"title": "Example", "type": "document", "content": "Example content"}'`, 'cyan');
589
+
590
+ return 'success';
591
+ } else {
592
+ throw new Error(result.error);
593
+ }
594
+ } catch (err) {
595
+ log(`❌ API key generation failed: ${err.message}`, 'red');
596
+ log('\nYou can generate an API key manually later:', 'yellow');
597
+ log(' npm run generate-key', 'cyan');
598
+ return 'failed';
599
+ }
600
+ }
@@ -57,15 +57,24 @@ async function validateDatabase() {
57
57
  process.env.SUPABASE_SERVICE_KEY
58
58
  );
59
59
 
60
- // Try to query a table
60
+ // Try to query any table (query will fail if connection is bad)
61
61
  const { error } = await supabase.from('vezlo_conversations').select('count').limit(0);
62
62
 
63
- if (error && error.code !== 'PGRST116') {
64
- throw error;
63
+ if (error) {
64
+ // Check for table not found errors (normal before migrations run)
65
+ if (error.code === 'PGRST116' ||
66
+ error.message.includes('does not exist') ||
67
+ error.message.includes('Could not find the table')) {
68
+ log('✅ Supabase connection successful', 'green');
69
+ log('⚠️ Note: Tables not found yet - this is normal before running migrations\n', 'yellow');
70
+ } else {
71
+ // Only throw if it's a real connection error
72
+ throw error;
73
+ }
74
+ } else {
75
+ log('✅ Supabase connection successful\n', 'green');
65
76
  }
66
77
 
67
- log('✅ Supabase connection successful\n', 'green');
68
-
69
78
  } catch (error) {
70
79
  log(`❌ Supabase connection failed: ${error.message}\n`, 'red');
71
80
  process.exit(1);
@@ -96,6 +105,10 @@ async function validateDatabase() {
96
105
 
97
106
  // Check required tables
98
107
  const requiredTables = [
108
+ 'vezlo_companies',
109
+ 'vezlo_users',
110
+ 'vezlo_user_company_profiles',
111
+ 'vezlo_api_keys',
99
112
  'vezlo_conversations',
100
113
  'vezlo_messages',
101
114
  'vezlo_message_feedback',
@@ -142,7 +155,10 @@ async function validateDatabase() {
142
155
  ORDER BY t.table_name
143
156
  `, [requiredTables]);
144
157
 
145
- log('\n📊 Table Structure:', 'cyan');
158
+ log('\n📊 Database Tables Summary:', 'cyan');
159
+ log(` Total tables found: ${schemaCheck.rows.length}`, 'green');
160
+
161
+ log('\n📋 Table Details:', 'cyan');
146
162
  schemaCheck.rows.forEach(row => {
147
163
  log(` ✓ ${row.table_name} (${row.column_count} columns)`, 'green');
148
164
  });