@deepbrainspace/nx-surrealdb
Version:
NX plugin for SurrealDB migrations with modular architecture
159 lines • 6.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SurrealDBClient = void 0;
const surrealdb_1 = require("surrealdb");
const debug_1 = require("./debug");
class SurrealDBClient {
constructor(dryRun = false) {
this.debug = debug_1.Debug.scope('surrealdb-client');
this.isDryRun = false;
this.db = new surrealdb_1.Surreal();
this.isDryRun = dryRun;
this.debug.log(`SurrealDBClient initialized with dry-run: ${dryRun}`);
}
async create(table, data) {
if (this.isDryRun) {
this.debug.log('🔍 [DRY-RUN] Would create record:');
this.debug.log(` Table: ${table}`);
this.debug.log(` Data:`, JSON.stringify(data, null, 2));
return;
}
try {
await this.db.create(table, data); // Cast to any if library expects it, or ensure library handles unknown
}
catch (error) {
throw new Error(`Failed to create record: ${error.message}`);
}
}
async connect(config) {
if (this.isDryRun) {
this.debug.log('🔍 [DRY-RUN] Connecting to SurrealDB for read-only queries:', {
url: config.url,
namespace: config.namespace,
database: config.database,
username: config.username,
hasPassword: !!config.password,
});
// Store connection details
this.username = config.username;
this.namespace = config.namespace;
this.database = config.database;
// Still establish real connection for read-only queries in dry-run mode
// This allows us to check migration status and other read operations
}
try {
this.debug.log('Connecting to SurrealDB:', {
url: config.url,
namespace: config.namespace,
database: config.database,
username: config.username,
hasPassword: !!config.password,
});
await this.db.connect(config.url);
await this.db.signin({
username: config.username,
password: config.password,
});
await this.db.use({
namespace: config.namespace,
database: config.database,
});
// Store connection details
this.username = config.username;
this.namespace = config.namespace;
this.database = config.database;
}
catch (error) {
this.debug.error('SurrealDB connection failed:', error);
throw new Error(`Failed to connect to SurrealDB: ${error.message}`);
}
}
async query(sql, params) {
if (this.isDryRun) {
// Check if this is a read-only query
const isReadOnlyQuery = this.isReadOnlyQuery(sql);
if (isReadOnlyQuery) {
this.debug.log('🔍 [DRY-RUN] Executing read-only query:');
}
else {
this.debug.log('🔍 [DRY-RUN] Would execute write query:');
}
// Format SQL for better readability
const formattedSql = this.formatSqlForDisplay(sql);
this.debug.log(` SQL:\n${formattedSql}`);
if (params && Object.keys(params).length > 0) {
this.debug.log(` Parameters:`);
for (const [key, value] of Object.entries(params)) {
this.debug.log(` $${key}: ${JSON.stringify(value)}`);
}
}
// For read-only queries, execute them even in dry-run mode
if (isReadOnlyQuery) {
try {
return await this.db.query(sql, params);
}
catch (error) {
throw new Error(`Query execution failed: ${error.message}`);
}
}
// For write queries, return empty result in dry-run mode
return [];
}
try {
return await this.db.query(sql, params);
}
catch (error) {
throw new Error(`Query execution failed: ${error.message}`);
}
}
isReadOnlyQuery(sql) {
// Normalize SQL for checking (case insensitive)
const normalizedSql = sql.trim().toLowerCase();
// Common read-only patterns (case insensitive)
const readOnlyPatterns = [
/^select\s/i, // SELECT queries
/^show\s/i, // SHOW queries
/^describe\s/i, // DESCRIBE queries
/^explain\s/i, // EXPLAIN queries
];
// Common write patterns (case insensitive)
const writePatterns = [
/^insert\s/i, // INSERT
/^update\s/i, // UPDATE
/^delete\s/i, // DELETE
/^create\s/i, // CREATE
/^drop\s/i, // DROP
/^alter\s/i, // ALTER
/^define\s/i, // DEFINE (SurrealDB)
/^remove\s/i, // REMOVE (SurrealDB)
/^relate\s/i, // RELATE (SurrealDB)
];
// Check for write patterns first (more specific)
if (writePatterns.some(pattern => pattern.test(normalizedSql))) {
return false;
}
// Check for read patterns
if (readOnlyPatterns.some(pattern => pattern.test(normalizedSql))) {
return true;
}
// Default to write operation for safety
return false;
}
formatSqlForDisplay(sql) {
// Simple SQL formatting for better readability
return sql
.trim()
.split('\n')
.map(line => ` ${line.trim()}`)
.join('\n');
}
async close() {
if (this.isDryRun) {
this.debug.log('🔍 [DRY-RUN] Would close database connection');
return;
}
await this.db.close();
}
}
exports.SurrealDBClient = SurrealDBClient;
//# sourceMappingURL=client.js.map