UNPKG

lakutata

Version:

An IoC-based universal application framework.

342 lines (330 loc) 9.8 kB
"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;