Files
app/scripts/apply-schema-prod.js
Albert d56e19c561 feat: Add production schema deployment scripts
- Create apply-schema-prod.js for deploying schema to any SurrealDB instance
- Create deploy-schema.sh to easily deploy using .prod.env
- Add npm scripts: schema:apply (local) and schema:deploy (production)

Usage:
  pnpm schema:deploy  # Deploy to production using .prod.env

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 15:44:05 +00:00

106 lines
3.1 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Apply SurrealDB schema to production database
*
* Usage:
* SURREALDB_URL=<url> SURREALDB_USER=<user> SURREALDB_PASS=<pass> \
* SURREALDB_NS=<ns> SURREALDB_DB=<db> SURREALDB_JWT_SECRET=<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
result.forEach((r, i) => {
if (r.status === 'ERR') {
console.error(`[Schema] Error in query ${i + 1}:`, r.result);
} else {
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();