@minatojs/driver-memory
Version:
In-memory Driver for Minato
220 lines (218 loc) • 8.45 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
MemoryDriver: () => MemoryDriver,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
var import_cosmokit = require("cosmokit");
var import_minato = require("minato");
var MemoryDriver = class extends import_minato.Driver {
static name = "memory";
_store = {
_fields: []
};
_indexes = {};
async prepare(name) {
}
async start() {
}
async $save(name) {
}
async stop() {
}
table(sel, env = {}) {
if (typeof sel === "string") {
return this._store[sel] ||= [];
}
if (!import_minato.Selection.is(sel)) {
throw new Error("Should not reach here");
}
const { ref, query, table, args, model } = sel;
const { fields, group, having, optional = {} } = sel.args[0];
let data;
if (typeof table === "object" && !import_minato.Selection.is(table)) {
const entries = Object.entries(table).map(([name, sel2]) => [name, this.table(sel2, env)]);
const catesian = /* @__PURE__ */ __name((entries2) => {
if (!entries2.length) return [];
const [[name, rows], ...tail] = entries2;
if (!tail.length) return rows.map((row) => ({ [name]: row }));
return rows.flatMap((row) => {
let res = catesian(tail).map((tail2) => ({ ...tail2, [name]: row }));
if (Object.keys(table).length === tail.length + 1) {
res = res.map((row2) => ({ ...env, [ref]: row2 })).filter((data2) => (0, import_minato.executeEval)(data2, having)).map((x) => x[ref]);
}
return !optional[tail[0]?.[0]] || res.length ? res : [{ [name]: row }];
});
}, "catesian");
data = catesian(entries);
} else {
data = this.table(table, env).filter((row) => (0, import_minato.executeQuery)(row, query, ref, env));
}
env[ref] = data;
const branches = [];
const groupFields = group ? (0, import_cosmokit.pick)(fields, group) : fields;
for (let row of (0, import_minato.executeSort)(data, args[0], ref)) {
row = model.format(row, false);
for (const key in model.fields) {
if (!import_minato.Field.available(model.fields[key])) continue;
row[key] ??= null;
}
let index = row;
if (fields) {
index = (0, import_cosmokit.mapValues)(groupFields, (expr) => (0, import_minato.executeEval)({ ...env, [ref]: row }, expr));
}
let branch = branches.find((branch2) => {
if (!group || !groupFields) return false;
for (const key in groupFields) {
if (!(0, import_cosmokit.deepEqual)(branch2.index[key], index[key])) return false;
}
return true;
});
if (!branch) {
branch = { index, table: [] };
branches.push(branch);
}
branch.table.push(row);
}
return branches.map(({ index, table: table2 }) => {
if (group) {
if (having) {
const value = (0, import_minato.executeEval)(table2.map((row) => ({ ...env, [ref]: row, _: row })), having);
if (!value) return;
}
for (const key in (0, import_cosmokit.omit)(fields, group)) {
index[key] = (0, import_minato.executeEval)(table2.map((row) => ({ ...env, [ref]: row, _: row })), fields[key]);
}
}
return model.parse(index, false);
}).filter(Boolean);
}
async drop(table) {
delete this._store[table];
}
async dropAll() {
this._store = { _fields: [] };
}
async stats() {
return { tables: (0, import_cosmokit.mapValues)(this._store, (rows, name) => ({ name, count: rows.length, size: 0 })), size: 0 };
}
async get(sel) {
return this.table(sel);
}
async eval(sel, expr) {
const { query, table } = sel;
const ref = typeof table === "string" ? sel.ref : table.ref;
const data = this.table(table).filter((row) => (0, import_minato.executeQuery)(row, query, ref));
return (0, import_minato.executeEval)(data.map((row) => ({ [ref]: row, _: row })), expr);
}
async set(sel, data) {
const { table, ref, query } = sel;
const matched = this.table(table).filter((row) => (0, import_minato.executeQuery)(row, query, ref)).map((row) => (0, import_minato.executeUpdate)(row, data, ref)).length;
this.$save(table);
return { matched };
}
async remove(sel) {
const { ref, query, table } = sel;
const data = this.table(table);
this._store[table] = data.filter((row) => !(0, import_minato.executeQuery)(row, query, ref));
this.$save(table);
const count = data.length - this._store[table].length;
return { removed: count, matched: count };
}
async create(sel, data) {
const { table, model } = sel;
const { primary, autoInc } = model;
const store = this.table(table);
if (!Array.isArray(primary) && autoInc && !(primary in data)) {
let meta = this._store._fields.find((row) => row.table === table && row.field === primary);
if (!meta) {
meta = { table, field: primary, autoInc: 0 };
this._store._fields.push(meta);
}
meta.autoInc += 1;
data[primary] = meta.autoInc;
} else {
const duplicated = await this.database.get(table, (0, import_cosmokit.pick)(model.format(data), (0, import_cosmokit.makeArray)(primary)));
if (duplicated.length) {
throw new import_minato.RuntimeError("duplicate-entry");
}
}
store.push((0, import_cosmokit.clone)(data));
this.$save(table);
return (0, import_cosmokit.clone)((0, import_cosmokit.clone)(data));
}
async upsert(sel, data, keys) {
const { table, model, ref } = sel;
const result = { inserted: 0, matched: 0 };
for (const update of data) {
const row = this.table(table).find((row2) => {
return keys.every((key) => row2[key] === update[key]);
});
if (row) {
(0, import_minato.executeUpdate)(row, update, ref);
result.matched++;
} else {
const data2 = (0, import_minato.executeUpdate)(model.create(), update, ref);
await this.create(sel, data2).catch(import_cosmokit.noop);
result.inserted++;
}
}
this.$save(table);
return result;
}
executeSelection(sel, env = {}) {
const expr = sel.args[0], table = sel.table;
if (Array.isArray(env)) env = { [sel.ref]: env };
const data = this.table(sel.table, env);
const res = (0, import_minato.isAggrExpr)(expr) ? data.map((row) => (0, import_minato.executeEval)({ ...env, [table.ref]: row, _: row }, expr)) : (0, import_minato.executeEval)(Object.assign(data.map((row) => ({ [table.ref]: row, _: row })), env), expr);
return res;
}
async withTransaction(callback) {
const data = (0, import_cosmokit.clone)(this._store);
await callback().catch((e) => {
this._store = data;
throw e;
});
}
async getIndexes(table) {
return Object.values(this._indexes[table] ?? {});
}
async createIndex(table, index) {
const name = index.name ?? "index:" + Object.entries(index.keys).map(([key, direction]) => `${key}_${direction}`).join("+");
this._indexes[table] ??= {};
this._indexes[table][name] = { name, unique: false, ...index };
}
async dropIndex(table, name) {
this._indexes[table] ??= {};
delete this._indexes[table][name];
}
};
((MemoryDriver2) => {
MemoryDriver2.Config = import_minato.z.object({});
})(MemoryDriver || (MemoryDriver = {}));
var src_default = MemoryDriver;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MemoryDriver
});
//# sourceMappingURL=index.cjs.map