kist
Version:
Lightweight Package Pipeline Processor with Plugin Architecture
86 lines • 3.09 kB
JavaScript
import { AbstractProcess } from "../abstract/AbstractProcess.js";
import { defaultConfig } from "./defaultConfig.js";
export class ConfigStore extends AbstractProcess {
constructor() {
super();
this.config = defaultConfig;
this.logDebug("ConfigStore initialized with default configuration.");
}
static getInstance() {
if (!ConfigStore.instance) {
ConfigStore.instance = new ConfigStore();
}
return ConfigStore.instance;
}
get(key) {
const keys = key.split(".");
let current = this.config;
for (const k of keys) {
if (current[k] === undefined) {
return undefined;
}
current = current[k];
}
this.logDebug(`Configuration key "${key}" retrieved.`);
return current;
}
set(key, value) {
const keys = key.split(".");
let current = this.config;
for (let i = 0; i < keys.length - 1; i++) {
const k = keys[i];
if (["__proto__", "constructor", "prototype"].includes(k)) {
this.logWarn(`Attempted prototype pollution detected: "${k}"`);
return;
}
if (!Object.prototype.hasOwnProperty.call(current, k) ||
typeof current[k] !== "object") {
current[k] = Object.create(null);
}
current = current[k];
}
const finalKey = keys[keys.length - 1];
if (["__proto__", "constructor", "prototype"].includes(finalKey)) {
this.logWarn(`Attempted prototype pollution detected: "${finalKey}"`);
return;
}
current[finalKey] = value;
this.logDebug(`Set configuration key "${key}" to: ${JSON.stringify(value)}`);
}
merge(newConfig) {
this.config = this.deepMerge(this.config, newConfig);
this.logDebug("Configuration successfully merged.");
}
getConfig() {
return this.config;
}
print() {
console.log("Current Configuration:", JSON.stringify(this.config, null, 2));
}
deepMerge(target, source) {
if (typeof target !== "object" || target === null) {
return source;
}
for (const key of Object.keys(source)) {
if (["__proto__", "constructor", "prototype"].includes(key)) {
this.logWarn(`Skipping unsafe key during merge: "${key}"`);
continue;
}
if (source[key] &&
typeof source[key] === "object" &&
!Array.isArray(source[key])) {
if (!Object.prototype.hasOwnProperty.call(target, key) ||
typeof target[key] !== "object") {
target[key] = Object.create(null);
}
target[key] = this.deepMerge(target[key], source[key]);
}
else {
target[key] = source[key];
}
}
return target;
}
}
ConfigStore.instance = null;
//# sourceMappingURL=ConfigStore.js.map