@trap_stevo/rolestack
Version:
Unify access logic across your applications with a single, elegant stack for roles. Define, query, and evolve roles on the fly.
206 lines (205 loc) • 6.98 kB
JavaScript
"use strict";
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
var _roles = /*#__PURE__*/new WeakMap();
var _normalizeName = /*#__PURE__*/new WeakMap();
var _validator = /*#__PURE__*/new WeakMap();
var _RoleStack_brand = /*#__PURE__*/new WeakSet();
class RoleStack {
constructor(opts) {
_classPrivateMethodInitSpec(this, _RoleStack_brand);
_classPrivateFieldInitSpec(this, _roles, new Map());
_classPrivateFieldInitSpec(this, _normalizeName, void 0);
_classPrivateFieldInitSpec(this, _validator, void 0);
_classPrivateFieldSet(_normalizeName, this, opts?.normalizeName || (n => {
if (typeof n !== "string") {
return String(n ?? "");
}
const t = n.trim();
return t ? t.toLowerCase() : "";
}));
_classPrivateFieldSet(_validator, this, typeof opts?.validator === "function" ? opts.validator : null);
if (Array.isArray(opts?.initial)) {
for (const item of opts.initial) {
this.set(item.name, item.data);
}
}
}
set(name, data) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k) {
return null;
}
_assertClassBrand(_RoleStack_brand, this, _assertValid).call(this, name, data);
_classPrivateFieldGet(_roles, this).set(k, _deepClone.call(RoleStack, data));
return this.get(name);
}
register(name, data) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k) {
return null;
}
if (_classPrivateFieldGet(_roles, this).has(k)) {
console.log(`Role "${name}" already exists.`);
return null;
}
return this.set(name, data);
}
upsert(name, patch, options) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k) {
return null;
}
const current = _classPrivateFieldGet(_roles, this).get(k);
let next;
if (typeof patch === "function") {
next = patch(_deepClone.call(RoleStack, current));
} else if (current) {
next = options?.merge ? options.merge(_deepClone.call(RoleStack, current), _deepClone.call(RoleStack, patch)) : {
...current,
...patch
};
} else {
next = _deepClone.call(RoleStack, patch);
}
return this.set(name, next);
}
get(name) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k) {
return null;
}
const val = _classPrivateFieldGet(_roles, this).get(k);
return val === undefined ? null : _deepClone.call(RoleStack, val);
}
remove(name) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k || !_classPrivateFieldGet(_roles, this).delete(k)) {
console.log(`Role "${name}" not found.`);
}
}
contains(name) {
return !!_assertClassBrand(_RoleStack_brand, this, _key).call(this, name) && _classPrivateFieldGet(_roles, this).has(_assertClassBrand(_RoleStack_brand, this, _key).call(this, name));
}
list() {
return [..._classPrivateFieldGet(_roles, this).entries()].map(([name, data]) => ({
name,
data: _deepClone.call(RoleStack, data)
}));
}
toJSON() {
return this.list();
}
static fromJSON(data, opts) {
return new RoleStack({
...opts,
initial: data
});
}
getField(name, fieldPath) {
const data = this.get(name);
if (data == null) return undefined;
const pathArr = String(fieldPath).split(".").map(s => s.trim()).filter(Boolean);
return _getPath.call(RoleStack, data, pathArr);
}
setField(name, fieldPath, value) {
const k = _assertClassBrand(_RoleStack_brand, this, _key).call(this, name);
if (!k || !_classPrivateFieldGet(_roles, this).has(k)) {
console.log(`Role "${name}" not found.`);
return null;
}
const data = _deepClone.call(RoleStack, _classPrivateFieldGet(_roles, this).get(k));
const pathArr = String(fieldPath).split(".").map(s => s.trim()).filter(Boolean);
_setPath.call(RoleStack, data, pathArr, value);
_assertClassBrand(_RoleStack_brand, this, _assertValid).call(this, name, data);
_classPrivateFieldGet(_roles, this).set(k, data);
return this.get(name);
}
query(fieldPath, value, opts) {
const cmp = typeof opts?.equals === "function" ? opts.equals : _deepEqual;
const paths = String(fieldPath).split(".").map(s => s.trim()).filter(Boolean);
const out = [];
for (const [name, data] of _classPrivateFieldGet(_roles, this).entries()) {
const v = _getPath.call(RoleStack, data, paths);
if (cmp(v, value)) {
out.push({
name,
data: _deepClone.call(RoleStack, data)
});
}
}
return out;
}
queryWhere(fieldPath, predicate) {
const paths = String(fieldPath).split(".").map(s => s.trim()).filter(Boolean);
const out = [];
for (const [name, data] of _classPrivateFieldGet(_roles, this).entries()) {
const v = _getPath.call(RoleStack, data, paths);
if (predicate(v, name, data)) {
out.push({
name,
data: _deepClone.call(RoleStack, data)
});
}
}
return out;
}
}
function _key(name) {
return _classPrivateFieldGet(_normalizeName, this).call(this, name);
}
function _assertValid(name, data) {
if (_classPrivateFieldGet(_validator, this)) _classPrivateFieldGet(_validator, this).call(this, name, data);
}
function _deepClone(v) {
return v === undefined ? undefined : JSON.parse(JSON.stringify(v));
}
function _getPath(obj, paths) {
let cur = obj;
for (const key of paths) {
if (cur == null) {
return undefined;
}
cur = cur[key];
}
return cur;
}
function _setPath(obj, paths, value) {
if (paths.length === 0) {
return value;
}
let cur = obj;
for (let i = 0; i < paths.length - 1; i++) {
const key = paths[i];
if (cur[key] == null || typeof cur[key] !== "object" || Array.isArray(cur[key])) {
cur[key] = {};
}
cur = cur[key];
}
cur[paths[paths.length - 1]] = value;
return obj;
}
function _deepEqual(a, b) {
if (a === b) {
return true;
}
if (typeof a !== typeof b) {
return false;
}
if (a && b && typeof a === "object") {
try {
return JSON.stringify(a) === JSON.stringify(b);
} catch {
return false;
}
}
return false;
}
;
module.exports = {
RoleStack
};