@nic-jennings/sql-datasource
Version:
SQL DataSource with Batching and Caching Support
89 lines (88 loc) • 3.43 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BatchedSQLDataSource = void 0;
const crypto_1 = require("crypto");
const dataloader_1 = __importDefault(require("dataloader"));
const knex_1 = __importDefault(require("knex"));
const knex_tiny_logger_1 = __importDefault(require("knex-tiny-logger"));
const utils_keyvaluecache_1 = require("@apollo/utils.keyvaluecache");
const { DEBUG } = process.env;
let hasCache = false;
let hasLogger = false;
let hasBatch = false;
class BatchedSQLDataSource {
cache;
context;
db;
constructor(config) {
this.cache = config.cache ? config.cache : new utils_keyvaluecache_1.InMemoryLRUCache();
this.context = config.context;
const { queryConnection, writeConnection } = this._connectToDatabase(config);
this.db = {
query: queryConnection,
write: writeConnection,
};
this._extendKnex();
}
_extendKnex() {
const _this = this;
const knexQueryBuilder = knex_1.default.QueryBuilder;
if (!this.db.query.cache && !hasCache) {
knexQueryBuilder.extend("cache", function (ttl) {
return _this._cacheQuery(this, ttl);
});
hasCache = true;
}
if (!this.db.query.batch && !hasBatch) {
knexQueryBuilder.extend("batch", function (callback) {
const query = this.clone();
return _this._batchQuery(query, callback);
});
hasBatch = true;
}
}
_connectToDatabase(config) {
let seperateInstances = true;
const queryConnection = typeof config.knexConfig === "function"
? config.knexConfig
: (0, knex_1.default)(config.knexConfig);
if (!config.writeKnexConfig) {
seperateInstances = false;
config.writeKnexConfig = queryConnection;
}
const writeConnection = typeof config.writeKnexConfig === "function"
? config.writeKnexConfig
: (0, knex_1.default)(config.writeKnexConfig);
if (DEBUG && !hasLogger) {
hasLogger = true; // Prevent duplicate loggers
(0, knex_tiny_logger_1.default)(queryConnection); // Add a logging utility for debugging
if (seperateInstances)
(0, knex_tiny_logger_1.default)(writeConnection); // Add a logging utility for debugging
}
return { queryConnection, writeConnection };
}
_batchQuery(query, callback) {
return new dataloader_1.default((keys) => {
const finalQuery = query.clone();
return callback(finalQuery, keys);
});
}
_cacheQuery(query, ttl = 5) {
const cacheKey = (0, crypto_1.createHash)("sha1")
.update(query.toString())
.digest("base64");
return this.cache?.get(cacheKey).then((entry) => {
if (entry)
return Promise.resolve(JSON.parse(entry));
return query.then((rows) => {
if (rows)
this.cache?.set(cacheKey, JSON.stringify(rows), { ttl });
return Promise.resolve(rows);
});
});
}
}
exports.BatchedSQLDataSource = BatchedSQLDataSource;