@stackmemoryai/stackmemory
Version:
Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.
61 lines (60 loc) • 1.73 kB
JavaScript
import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
class DatabaseAdapter {
projectId;
config;
constructor(projectId, config) {
this.projectId = projectId;
this.config = config || {};
}
// Utility methods
generateId() {
return crypto.randomUUID();
}
sanitizeQuery(query) {
console.warn(
"sanitizeQuery() is deprecated and unsafe - use parameterized queries"
);
return query.replace(/[;'"\\]/g, "");
}
buildWhereClause(conditions) {
const clauses = Object.entries(conditions).map(([key, value]) => {
if (value === null) {
return `${key} IS NULL`;
} else if (Array.isArray(value)) {
return `${key} IN (${value.map(() => "?").join(",")})`;
} else {
return `${key} = ?`;
}
});
return clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
}
buildOrderByClause(orderBy, direction) {
if (!orderBy) return "";
const isSafe = /^[a-zA-Z0-9_.]+$/.test(orderBy);
if (!isSafe) {
return "";
}
const dir = direction === "DESC" ? "DESC" : "ASC";
return ` ORDER BY ${orderBy} ${dir}`;
}
buildLimitClause(limit, offset) {
if (!limit) return "";
let clause = ` LIMIT ${limit}`;
if (offset) clause += ` OFFSET ${offset}`;
return clause;
}
}
class FeatureAwareDatabaseAdapter extends DatabaseAdapter {
async canUseFeature(feature) {
const features = this.getFeatures();
return features[feature] || false;
}
}
export {
DatabaseAdapter,
FeatureAwareDatabaseAdapter
};
//# sourceMappingURL=database-adapter.js.map