#!/usr/bin/env node /** * Apply SurrealDB schema to production database * * Usage: * SURREALDB_URL= SURREALDB_USER= SURREALDB_PASS= \ * SURREALDB_NS= SURREALDB_DB= SURREALDB_JWT_SECRET= \ * node scripts/apply-schema-prod.js */ const Surreal = require('surrealdb').default; const fs = require('fs'); const path = require('path'); async function applySchema() { // Read config from environment const config = { url: process.env.SURREALDB_URL, username: process.env.SURREALDB_USER, password: process.env.SURREALDB_PASS, namespace: process.env.SURREALDB_NS, database: process.env.SURREALDB_DB, jwtSecret: process.env.SURREALDB_JWT_SECRET, }; // Validate required config const missing = Object.entries(config) .filter(([_, value]) => !value) .map(([key]) => key); if (missing.length > 0) { console.error('[Schema] ✗ Missing required environment variables:', missing.join(', ')); console.error('[Schema] Please set all required variables:'); console.error('[Schema] SURREALDB_URL, SURREALDB_USER, SURREALDB_PASS,'); console.error('[Schema] SURREALDB_NS, SURREALDB_DB, SURREALDB_JWT_SECRET'); process.exit(1); } const db = new Surreal(); try { console.log('[Schema] Connecting to SurrealDB...'); console.log(`[Schema] URL: ${config.url}`); await db.connect(config.url); console.log('[Schema] Signing in...'); await db.signin({ username: config.username, password: config.password, }); console.log('[Schema] Using namespace and database...'); console.log(`[Schema] Namespace: ${config.namespace}`); console.log(`[Schema] Database: ${config.database}`); await db.use({ namespace: config.namespace, database: config.database, }); console.log('[Schema] Reading schema file...'); const schemaPath = path.join(__dirname, '..', 'db', 'schema.surql'); let schema = fs.readFileSync(schemaPath, 'utf-8'); // Replace $env.SURREALDB_JWT_SECRET with actual value schema = schema.replace('$env.SURREALDB_JWT_SECRET', `'${config.jwtSecret}'`); console.log('[Schema] Executing schema...'); let result; try { result = await db.query(schema); } catch (error) { // If error contains "already exists", it's OK - schema was already applied if (error.message.includes('already exists')) { console.log('[Schema] ⚠ Some schema elements already exist (this is OK)'); console.log('[Schema] ✓ Schema is up to date!'); return; } else { throw error; } } if (result) { console.log(`[Schema] Executed ${result.length} queries`); // Log any errors (if results have status property) if (Array.isArray(result)) { result.forEach((r, i) => { if (r && typeof r === 'object') { if (r.status === 'ERR') { console.error(`[Schema] Error in query ${i + 1}:`, r.result); } else if (r.status === 'OK') { console.log(`[Schema] ✓ Query ${i + 1} succeeded`); } } }); } } console.log('[Schema] ✓ Schema applied successfully!'); } catch (error) { console.error('[Schema] ✗ Failed to apply schema:', error); process.exit(1); } finally { await db.close(); } } applySchema();