lakutata
Version:
An IoC-based universal application framework.
342 lines (330 loc) • 9.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, {
value: "Module"
});
const e = require("events");
const t = require("buffer");
const n = require("mongodb");
const s = e => e && e.__esModule ? e : {
default: e
};
const o = s(e);
var a = new Set([ "url", "collection", "namespace", "serialize", "deserialize", "uri", "useGridFS", "dialect", "db" ]);
var i = class extends o.default {
ttlSupport=false;
opts;
connect;
namespace;
constructor(e, t) {
super();
e ??= {};
if (typeof e === "string") {
e = {
url: e
};
}
if (e.uri) {
e = {
url: e.uri,
...e
};
}
this.opts = {
url: "mongodb://127.0.0.1:27017",
collection: "keyv",
...e,
...t
};
delete this.opts.emitErrors;
const s = Object.fromEntries(Object.entries(this.opts).filter((([e]) => !a.has(e))));
this.opts = Object.fromEntries(Object.entries(this.opts).filter((([e]) => a.has(e))));
this.connect = new Promise((async (e, t) => {
try {
let t = "";
if (this.opts.url) {
t = this.opts.url;
}
const o = new n.MongoClient(t, s);
await o.connect();
const a = o.db(this.opts.db);
if (this.opts.useGridFS) {
const t = new n.GridFSBucket(a, {
readPreference: this.opts.readPreference,
bucketName: this.opts.collection
});
const s = a.collection(`${this.opts.collection}.files`);
await s.createIndex({
uploadDate: -1
});
await s.createIndex({
"metadata.expiresAt": 1
});
await s.createIndex({
"metadata.lastAccessed": 1
});
await s.createIndex({
"metadata.filename": 1
});
e({
bucket: t,
store: s,
db: a,
mongoClient: o
});
} else {
let t = "keyv";
if (this.opts.collection) {
t = this.opts.collection;
}
const n = a.collection(t);
await n.createIndex({
key: 1
}, {
unique: true,
background: true
});
await n.createIndex({
expiresAt: 1
}, {
expireAfterSeconds: 0,
background: true
});
e({
store: n,
mongoClient: o
});
}
} catch (e) {
this.emit("error", e);
}
}));
}
async get(e) {
const n = await this.connect;
if (this.opts.useGridFS) {
await n.store.updateOne({
filename: e
}, {
$set: {
"metadata.lastAccessed": new Date
}
});
const s = n.bucket.openDownloadStreamByName(e);
return new Promise((e => {
const n = [];
s.on("error", (() => {
e(void 0);
}));
s.on("end", (() => {
const s = t.Buffer.concat(n).toString("utf8");
e(s);
}));
s.on("data", (e => {
n.push(e);
}));
}));
}
const s = await n.store.findOne({
key: {
$eq: e
}
});
if (!s) {
return void 0;
}
return s.value;
}
async getMany(e) {
if (this.opts.useGridFS) {
const t = [];
for (const n of e) {
t.push(this.get(n));
}
const n = await Promise.allSettled(t);
const s = [];
for (const e of n) {
s.push(e.value);
}
return s;
}
const t = await this.connect;
const n = await t.store.s.db.collection(this.opts.collection).find({
key: {
$in: e
}
}).project({
_id: 0,
value: 1,
key: 1
}).toArray();
const s = [ ...e ];
let o = 0;
for (const t of e) {
const e = n.findIndex((e => e.key === t));
s[o] = e > -1 ? n[e].value : void 0;
o++;
}
return s;
}
async set(e, t, n) {
const s = typeof n === "number" ? new Date(Date.now() + n) : null;
if (this.opts.useGridFS) {
const n = await this.connect;
const o = n.bucket.openUploadStream(e, {
metadata: {
expiresAt: s,
lastAccessed: new Date
}
});
return new Promise((e => {
o.on("finish", (() => {
e(o);
}));
o.end(t);
}));
}
const o = await this.connect;
await o.store.updateOne({
key: {
$eq: e
}
}, {
$set: {
key: e,
value: t,
expiresAt: s
}
}, {
upsert: true
});
}
async delete(e) {
if (typeof e !== "string") {
return false;
}
const t = await this.connect;
if (this.opts.useGridFS) {
try {
const s = t.db;
const o = new n.GridFSBucket(s, {
bucketName: this.opts.collection
});
const a = await o.find({
filename: e
}).toArray();
await t.bucket.delete(a[0]._id);
return true;
} catch {
return false;
}
}
const s = await t.store.deleteOne({
key: {
$eq: e
}
});
return s.deletedCount > 0;
}
async deleteMany(e) {
const t = await this.connect;
if (this.opts.useGridFS) {
const s = t.db;
const o = new n.GridFSBucket(s, {
bucketName: this.opts.collection
});
const a = await o.find({
filename: {
$in: e
}
}).toArray();
if (a.length === 0) {
return false;
}
await Promise.all(a.map((async e => t.bucket.delete(e._id))));
return true;
}
const s = await t.store.deleteMany({
key: {
$in: e
}
});
return s.deletedCount > 0;
}
async clear() {
const e = await this.connect;
if (this.opts.useGridFS) {
try {
await e.bucket.drop();
} catch (e) {
if (!(e instanceof n.MongoServerError && e.code === 26)) {
throw e;
}
}
}
await e.store.deleteMany({
key: {
$regex: this.namespace ? `^${this.namespace}:*` : ""
}
});
}
async clearExpired() {
if (!this.opts.useGridFS) {
return false;
}
return this.connect.then((async e => {
const t = e.db;
const s = new n.GridFSBucket(t, {
bucketName: this.opts.collection
});
return s.find({
"metadata.expiresAt": {
$lte: new Date(Date.now())
}
}).toArray().then((async t => Promise.all(t.map((async t => e.bucket.delete(t._id)))).then((() => true))));
}));
}
async clearUnusedFor(e) {
if (!this.opts.useGridFS) {
return false;
}
const t = await this.connect;
const s = t.db;
const o = new n.GridFSBucket(s, {
bucketName: this.opts.collection
});
const a = await o.find({
"metadata.lastAccessed": {
$lte: new Date(Date.now() - e * 1e3)
}
}).toArray();
await Promise.all(a.map((async e => t.bucket.delete(e._id))));
return true;
}
async* iterator(e) {
const t = await this.connect;
const n = new RegExp(`^${e ? e + ":" : ".*"}`);
const s = this.opts.useGridFS ? t.store.find({
filename: n
}).map((async e => [ e.filename, await this.get(e.filename) ])) : t.store.find({
key: n
}).map((e => [ e.key, e.value ]));
yield* s;
}
async has(e) {
const t = await this.connect;
const n = {
[this.opts.useGridFS ? "filename" : "key"]: {
$eq: e
}
};
const s = await t.store.count(n);
return s !== 0;
}
async disconnect() {
const e = await this.connect;
await e.mongoClient.close();
}
};
var c = i;
exports.KeyvMongo = i;
exports.default = c;