tspace-mysql
Version:
Tspace MySQL is a promise-based ORM for Node.js, designed with modern TypeScript and providing type safety for schema databases.
175 lines • 6.19 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DBCache = void 0;
const Model_1 = require("../Model");
const DB_1 = require("../DB");
const Blueprint_1 = require("../Blueprint");
const utils_1 = require("../../utils");
const constants_1 = require("../../constants");
class DBCache {
_cacheTable = '$cache';
_v0x = 'v0x';
_maxAddress = 10;
_maxLength = 100;
_db = () => new DB_1.DB(this._cacheTable);
provider() {
return 'db';
}
async all() {
const cacheds = await this._db().get();
const values = [];
for (const cached of cacheds) {
for (let i = 0; i < this._maxAddress; i++) {
const find = cached[this._addressNumber(i)];
if (find == null || find === '')
break;
if (Number.isNaN(+cached.expiredAt) ||
new Date() > new Date(+cached.expiredAt)) {
await this._db()
.where('key', cached.key)
.delete();
continue;
}
const maybeArray = this._safetyJsonParse(find);
if (Array.isArray(maybeArray)) {
values.push(...this._safetyJsonParse(find));
continue;
}
values.push(this._safetyJsonParse(find));
}
}
return values;
}
async exists(key) {
const cached = await this._db().where('key', key).exists();
return cached;
}
async get(key) {
try {
const addresses = Array.from({ length: this._maxAddress }, (_, i) => this._addressNumber(i));
const cached = await this._db().select('expiredAt', ...addresses).where('key', key).findOne();
if (!cached)
return null;
const now = Date.now();
const expiredAt = +cached.expiredAt;
if (Number.isNaN(expiredAt) || now > expiredAt) {
await this._db()
.where('key', key)
.deleteMany();
return null;
}
const value = this._safetyJsonParse(cached[this._addressNumber(0)]);
if (!Array.isArray(value))
return value;
const values = [];
for (let i = 0; i < this._maxAddress; i++) {
const find = cached[this._addressNumber(i)];
if (find == null || find === '')
break;
const parsed = this._safetyJsonParse(find);
if (Array.isArray(parsed)) {
values.push(...parsed);
continue;
}
values.push(parsed);
}
return values.length === 1 ? values[0] : values;
}
catch (err) {
const message = String(err?.message ?? '');
if (message.toLocaleLowerCase().includes("doesn't exist")) {
await this._checkTableCacheExists();
return await this.get(key);
}
throw err;
}
}
async set(key, value, ms) {
const expiredAt = +new Date() + ms;
if (!Array.isArray(value)) {
await this._db()
.create({
key,
[this._addressNumber(0)]: JSON.stringify(value),
expiredAt,
createdAt: utils_1.utils.timestamp(),
updatedAt: utils_1.utils.timestamp()
})
.void()
.save();
return;
}
const avg = value.length / this._maxAddress;
const chunked = utils_1.utils.chunkArray(value, avg > this._maxLength ? avg : this._maxLength);
const caches = {};
for (const [index, value] of chunked.entries()) {
caches[this._addressNumber(index)] = JSON.stringify(value);
}
await this._db()
.create({
key,
...caches,
expiredAt,
createdAt: utils_1.utils.timestamp(),
updatedAt: utils_1.utils.timestamp()
})
.void()
.save();
return;
}
async clear() {
await this._db().truncate({ force: true });
return;
}
async delete(key) {
await this._db().where('key', key).delete();
return;
}
_addressNumber(number) {
const index = `0${number}`.slice(-2);
return `${this._v0x}${index}`;
}
async _checkTableCacheExists() {
const table = this._cacheTable;
const checkTables = await DB_1.DB.rawQuery(`${constants_1.CONSTANTS.SHOW_TABLES} ${constants_1.CONSTANTS.LIKE} '${table}'`);
const existsTables = checkTables.map((c) => Object.values(c)[0])[0];
if (existsTables != null)
return;
let addresses = {};
for (let i = 0; i < this._maxAddress; i++) {
addresses[this._addressNumber(i)] = new Blueprint_1.Blueprint().json().null();
}
const schema = {
id: new Blueprint_1.Blueprint().int().notNull().primary().autoIncrement(),
key: new Blueprint_1.Blueprint().varchar(255).notNull().index(),
...addresses,
expiredAt: new Blueprint_1.Blueprint().bigInt().notNull(),
createdAt: new Blueprint_1.Blueprint().timestamp().notNull(),
updatedAt: new Blueprint_1.Blueprint().timestamp().notNull()
};
class Cache extends Model_1.Model {
boot() {
this.useSchema(schema);
this.useTable(table);
}
}
await new Cache().sync({ index: true });
return;
}
_safetyJsonParse(value) {
if (typeof value !== 'string')
return value;
const v = value.trim();
if (!v || (v[0] !== '{' && v[0] !== '['))
return value;
try {
return JSON.parse(v);
}
catch {
return value;
}
}
}
exports.DBCache = DBCache;
exports.default = DBCache;
//# sourceMappingURL=DBCache.js.map