UNPKG

@telcomdataperu/zeus-vue-model-manager

Version:

Vue 3 Model Manager for Microfrontends with OpenUI5-style API - Part of ZEUS Platform by TelcomdataPeru

600 lines (599 loc) 17.4 kB
import { reactive as v, computed as A, watch as w } from "vue"; class b { constructor(e, t = {}) { this.validators = {}, this.watchers = [], this.eventListeners = {}, this.changeCount = 0, this.options = { enableLogging: !1, enableValidation: !1, immutable: !1, pathSeparator: "/", ...t }, this.data = v(e), this.metadata = { version: "1.0.0", created: /* @__PURE__ */ new Date(), lastModified: /* @__PURE__ */ new Date(), changeCount: 0, paths: this.getAllPaths(this.data), size: JSON.stringify(this.data).length }, this.options.enableLogging && console.log("[JsonModel] Created with options:", this.options); } // ===== BASIC METHODS ===== getData() { return this.data; } getProperty(e) { return e.replace(/^\//, "").split(this.options.pathSeparator || "/").reduce((s, r) => { if (s && typeof s == "object" && r in s) return s[r]; }, this.data); } setProperty(e, t) { const s = this.getProperty(e); if (this.options.enableValidation) { const c = this.validatePath(e, t); if (c.length > 0) { this.emit("validation-error", { path: e, errors: c }); return; } } const r = e.replace(/^\//, "").split(this.options.pathSeparator || "/"), a = r.pop(), i = r.reduce((c, n) => { if (c && typeof c == "object" && n in c) return c[n]; }, this.data); i && typeof i == "object" && a && (i[a] = t, this.updateMetadata(), this.emit("property-changed", { path: e, oldValue: s, newValue: t, timestamp: Date.now(), source: "user" }), this.options.enableLogging && console.log(`[JsonModel] Property changed: ${e}`, { oldValue: s, newValue: t })); } // ===== ADVANCED METHODS ===== updateProperties(e) { Object.entries(e).forEach(([t, s]) => { this.setProperty(t, s); }); } createBinding(e) { return A(() => this.getProperty(e)); } // ===== ARRAY OPERATIONS ===== addToArray(e, t) { const s = this.getProperty(e); Array.isArray(s) && (s.push(t), this.updateMetadata(), this.emit("array-changed", { path: e, action: "add", index: s.length - 1, item: t })); } removeFromArray(e, t) { const s = this.getProperty(e); if (Array.isArray(s) && t >= 0 && t < s.length) { const r = s[t]; s.splice(t, 1), this.updateMetadata(), this.emit("array-changed", { path: e, action: "remove", index: t, item: r }); } } updateArrayItem(e, t, s) { const r = this.getProperty(e); if (Array.isArray(r)) { const a = r.findIndex(t); if (a !== -1) return Object.assign(r[a], s), this.updateMetadata(), this.emit("array-changed", { path: e, action: "update", index: a, item: r[a] }), !0; } return !1; } // ===== UTILITIES ===== getArrayLength(e) { const t = this.getProperty(e); return Array.isArray(t) ? t.length : 0; } hasProperty(e) { return this.getProperty(e) !== void 0; } resetProperty(e, t = void 0) { this.setProperty(e, t); } getObjectKeys(e) { const t = this.getProperty(e); return t && typeof t == "object" && !Array.isArray(t) ? Object.keys(t) : []; } // ===== SERIALIZATION ===== clone() { return new b(JSON.parse(JSON.stringify(this.data)), this.options); } toJSON() { return JSON.stringify(this.data, null, 2); } fromJSON(e) { try { const t = JSON.parse(e); Object.assign(this.data, t), this.updateMetadata(), this.emit("model-reset", { timestamp: Date.now() }); } catch (t) { console.error("[JsonModel] Error parsing JSON:", t); } } // ===== WATCHERS AND EVENTS ===== watch(e, t, s = {}) { const r = w( () => this.getProperty(e), t, { immediate: s.immediate || !1, deep: s.deep || !0, flush: s.flush || "post" } ); return this.watchers.push(r), r; } // ===== VALIDATION ===== addValidator(e, t) { this.validators[e] || (this.validators[e] = []), this.validators[e].push(t); } removeValidator(e) { delete this.validators[e]; } validate(e) { if (e) { const t = this.getProperty(e); return this.validatePath(e, t).length === 0; } for (const t of Object.keys(this.validators)) if (!this.validate(t)) return !1; return !0; } getErrors(e) { if (e) { const s = this.getProperty(e); return this.validatePath(e, s); } const t = []; for (const s of Object.keys(this.validators)) t.push(...this.getErrors(s)); return t; } validatePath(e, t) { const s = this.validators[e] || [], r = []; for (const a of s) { const i = a.validate(t); i !== !0 && r.push(typeof i == "string" ? i : a.message || "Validation failed"); } return r; } // ===== METADATA ===== getMetadata() { return { ...this.metadata }; } reset(e) { e ? e.forEach((t) => { const s = this.options.defaultValues?.[t]; this.setProperty(t, s); }) : this.options.defaultValues && Object.assign(this.data, this.options.defaultValues), this.updateMetadata(), this.emit("model-reset", { timestamp: Date.now() }); } destroy() { this.watchers.forEach((e) => e()), this.watchers = [], this.validators = {}, this.eventListeners = {}, this.options.enableLogging && console.log("[JsonModel] Destroyed"); } // ===== PRIVATE HELPERS ===== updateMetadata() { this.changeCount++, this.metadata.lastModified = /* @__PURE__ */ new Date(), this.metadata.changeCount = this.changeCount, this.metadata.paths = this.getAllPaths(this.data), this.metadata.size = JSON.stringify(this.data).length; } getAllPaths(e, t = "") { const s = []; for (const r in e) if (e.hasOwnProperty(r)) { const a = t ? `${t}/${r}` : r; s.push(`/${a}`), e[r] && typeof e[r] == "object" && !Array.isArray(e[r]) && s.push(...this.getAllPaths(e[r], a)); } return s; } emit(e, t) { (this.eventListeners[e] || []).forEach((r) => r(t)); } // ===== EVENT SYSTEM ===== on(e, t) { this.eventListeners[e] || (this.eventListeners[e] = []), this.eventListeners[e].push(t); } off(e, t) { const s = this.eventListeners[e] || [], r = s.indexOf(t); r > -1 && s.splice(r, 1); } } class O { constructor(e, t = {}) { this.models = /* @__PURE__ */ new Map(), this.config = { scope: e, security: { level: "basic" }, audit: { enabled: !1 }, ...t }, this.config.audit?.enabled && console.log(`[ModelManager] Created for scope: ${e} with config:`, this.config); } create(e, t, s) { const r = { enableLogging: this.config.audit?.enabled || !1, enableValidation: this.config.security?.level !== "basic", ...s }, a = new b(t, r); return this.models.set(e, a), this.config.audit?.enabled && console.log(`[ModelManager] Model '${e}' created in scope '${this.config.scope}'`), a; } createShared(e, t, s) { const r = { ...s, enableLogging: !0, enableValidation: !0 }; return this.create(e, t, r); } createGlobal(e, t, s) { const r = { ...s, enableLogging: !0, enableValidation: !0 }; return this.create(e, t, r); } getModel(e) { return this.models.get(e); } hasModel(e) { return this.models.has(e); } removeModel(e) { const t = this.models.get(e); return t ? (t.destroy(), this.models.delete(e), this.config.audit?.enabled && console.log(`[ModelManager] Model '${e}' removed from scope '${this.config.scope}'`), !0) : !1; } getAllModels() { const e = {}; return this.models.forEach((t, s) => { e[s] = t; }), e; } getModelNames() { return Array.from(this.models.keys()); } getScope() { return this.config.scope; } getConfig() { return { ...this.config }; } clear() { this.models.forEach((e, t) => { e.destroy(); }), this.models.clear(), this.config.audit?.enabled && console.log(`[ModelManager] All models cleared from scope '${this.config.scope}'`); } // Enterprise features exportModels() { const e = {}; return this.models.forEach((t, s) => { e[s] = t.toJSON(); }), e; } importModels(e) { Object.entries(e).forEach(([t, s]) => { const r = this.models.get(t); r && r.fromJSON(s); }); } getStatistics() { return { scope: this.config.scope, modelCount: this.models.size, modelNames: this.getModelNames(), totalSize: Array.from(this.models.values()).reduce((e, t) => e + t.getMetadata().size, 0) }; } } class L { constructor() { this.managers = /* @__PURE__ */ new Map(), this.accessLog = [], this.enableAudit = !1; } // Basic operations register(e, t) { this.managers.has(e) && console.warn(`[GlobalRegistry] Manager for scope '${e}' already exists. Replacing...`), this.managers.set(e, t), this.enableAudit && console.log(`[GlobalRegistry] Manager registered for scope: ${e}`); } get(e) { return this.managers.get(e); } unregister(e) { const t = this.managers.get(e); t && (t.clear(), this.managers.delete(e), this.enableAudit && console.log(`[GlobalRegistry] Manager unregistered for scope: ${e}`)); } hasModel(e, t) { const s = this.managers.get(e); return s ? s.hasModel(t) : !1; } removeModel(e, t) { const s = this.managers.get(e); return s && s.hasModel(t) ? (s.removeModel(t), !0) : !1; } getAllScopes() { return Array.from(this.managers.keys()); } clear() { this.managers.forEach((e, t) => { e.clear(); }), this.managers.clear(), this.accessLog = [], this.enableAudit && console.log("[GlobalRegistry] All managers cleared"); } enableAuditing(e = !0) { this.enableAudit = e, console.log(`[GlobalRegistry] Auditing ${e ? "enabled" : "disabled"}`); } getModelFromScope(e, t, s) { const r = this.managers.get(t); if (!r) { console.warn(`[GlobalRegistry] Target scope '${t}' not found`); return; } const a = r.getModel(s); return a && this.enableAudit && this.logAccess({ sourceScope: e, targetScope: t, modelName: s, accessType: "read", timestamp: /* @__PURE__ */ new Date() }), a; } getStatistics() { const e = this.getAllScopes(), t = Array.from(this.managers.values()).reduce((s, r) => s + r.getModelNames().length, 0); return { totalManagers: this.managers.size, totalModels: t, scopes: e, lastActivity: /* @__PURE__ */ new Date() }; } getManagerStatistics(e) { if (e) { const s = this.managers.get(e); return s ? { [e]: s.getStatistics() } : {}; } const t = {}; return this.managers.forEach((s, r) => { t[r] = s.getStatistics(); }), t; } broadcastToScope(e, t, s) { return this.managers.get(e) ? (this.enableAudit && console.log(`[GlobalRegistry] Broadcasting '${t}' to scope '${e}'`, s), !0) : (console.warn(`[GlobalRegistry] Cannot broadcast to scope '${e}' - not found`), !1); } shareModel(e, t, s, r) { const a = this.managers.get(e), i = this.managers.get(t); if (!a || !i) return console.error("[GlobalRegistry] Source or target scope not found for model sharing"), !1; const c = a.getModel(s); if (!c) return console.error(`[GlobalRegistry] Model '${s}' not found in source scope '${e}'`), !1; const n = JSON.parse(c.toJSON()), l = r || s; return i.create(l, n), this.enableAudit && console.log(`[GlobalRegistry] Model '${s}' shared from '${e}' to '${t}' as '${l}'`), !0; } inspectScope(e) { const t = this.managers.get(e); if (!t) return { error: `Scope '${e}' not found` }; const s = t.getAllModels(), r = { scope: e, config: t.getConfig(), statistics: t.getStatistics(), models: {} }; return Object.entries(s).forEach(([a, i]) => { r.models[a] = { metadata: i.getMetadata(), data: i.getData() }; }), r; } getAccessLog() { return [...this.accessLog]; } logAccess(e) { this.accessLog.push(e), this.accessLog.length > 1e3 && (this.accessLog = this.accessLog.slice(-1e3)); } dumpState() { console.group("[GlobalRegistry] Current State"), console.log("Statistics:", this.getStatistics()), console.log("Manager Statistics:", this.getManagerStatistics()), this.getAllScopes().forEach((e) => { console.group(`Scope: ${e}`), console.log(this.inspectScope(e)), console.groupEnd(); }), this.accessLog.length > 0 && console.log("Recent Access Log:", this.accessLog.slice(-10)), console.groupEnd(); } } const g = new L(); let f = { fallbackToGlobalSearch: !0 }; function E(o) { f.currentScope = o; } function p(o) { if (o) return g.get(o); if (f.currentScope) return g.get(f.currentScope); if (f.fallbackToGlobalSearch) { const e = g.getAllScopes(); if (e.length > 0) return g.get(e[0]); } } function y(o, e) { if (e) { const s = g.get(e)?.getModel(o); if (s) return { model: s, scope: e }; } if (f.currentScope) { const s = g.get(f.currentScope)?.getModel(o); if (s) return { model: s, scope: f.currentScope }; } if (f.fallbackToGlobalSearch) for (const t of g.getAllScopes()) { const r = g.get(t)?.getModel(o); if (r) return { model: r, scope: t }; } } function C(o) { f = { ...f, ...o }; } function J() { return { ...f }; } function P(o, e, t = {}) { const { scope: s, fallbackSearch: r = !0, defaultValue: a } = t; return A({ get() { if (s) { const l = p(s)?.getModel(o); if (l) { const u = l.getProperty(e); return u !== void 0 ? u : a; } } if (r) { const n = y(o, s); if (n) { const l = n.model.getProperty(e); return l !== void 0 ? l : a; } } const c = p()?.getModel(o); if (c) { const n = c.getProperty(e); return n !== void 0 ? n : a; } return a; }, set(i) { if (i === void 0) return; if (s) { const u = p(s)?.getModel(o); if (u) { u.setProperty(e, i); return; } } if (r) { const l = y(o, s); if (l) { l.model.setProperty(e, i); return; } } const n = p()?.getModel(o); if (n) { n.setProperty(e, i); return; } console.warn(`[useModel] No se pudo encontrar el modelo '${o}' para actualizar '${e}'`); } }); } function R(o, e, t) { return P(e, t, { scope: o, fallbackSearch: !1 }); } function V(o, e, t) { return P(o, e, { defaultValue: t }); } const M = /* @__PURE__ */ new Map(); function S(o, e = "", t = {}) { const { scope: s, fallbackSearch: r = !0 } = t, a = `${o}:${e}`; if (M.has(a)) return M.get(a); const i = new Proxy({}, { get(c, n) { if (n === Symbol.toStringTag) return "ZeusModelProxy"; if (n === Symbol.toPrimitive) return () => "[ZeusModelProxy]"; if (typeof n == "symbol") return; const l = String(n), u = e ? `${e}/${l}` : `/${l}`; let d; if (s ? d = p(s)?.getModel(o) : r ? d = y(o, s)?.model : d = p()?.getModel(o), !d) return; const h = d.getProperty(u); if (h && typeof h == "object" && !Array.isArray(h)) { const m = S(o, u, t); return M.set(`${o}:${u}`, m), m; } return h; }, set(c, n, l) { if (typeof n == "symbol") return !1; const u = String(n), d = e ? `${e}/${u}` : `/${u}`; let h; return s ? h = p(s)?.getModel(o) : r ? h = y(o, s)?.model : h = p()?.getModel(o), h ? (h.setProperty(d, l), !0) : (console.warn(`[useModels] No se pudo encontrar el modelo '${o}' para actualizar '${d}'`), !1); }, has(c, n) { if (typeof n == "symbol") return !1; const l = String(n), u = e ? `${e}/${l}` : `/${l}`; let d; return s ? d = p(s)?.getModel(o) : d = y(o, s)?.model, d ? d.hasProperty(u) : !1; } }); return M.set(a, i), i; } function $(o, e = {}) { const t = {}; return o.forEach((s) => { t[s] = v(S(s, "", e)); }), t; } function D(o, e = {}) { const t = {}; return o.forEach((s) => { t[s] = S(s, "", e); }), t; } function x(o, e) { return $(e, { scope: o, fallbackSearch: !1 }); } function k(o) { return $(o, {}); } function z(o, e) { const t = new O(o, e); return g.register(o, t), t; } function T() { g.enableAuditing(!0); } function F() { g.dumpState(); } function j() { return { registry: g.getStatistics(), managers: g.getManagerStatistics() }; } function B(o, e, t) { return g.getModelFromScope(o, e, t); } function I(o, e, t, s) { return g.shareModel(o, e, t, s); } export { g as GlobalRegistry, b as JsonModel, O as ModelManager, C as configureComposables, z as createModelManager, F as dumpGlobalState, T as enableGlobalAuditing, J as getComposableContext, j as getGlobalStatistics, B as getModelFromMicrofrontend, E as setComposableScope, I as shareModelBetweenMicrofrontends, P as useModel, R as useModelFromScope, V as useModelWithDefault, $ as useModels, x as useModelsFromScope, D as useModelsRaw, k as useModelsShallow };