Skip to content

Instantly share code, notes, and snippets.

@koresar
Created July 21, 2021 08:54
Show Gist options
  • Save koresar/aa4cad04453d5b307f8ed4f6e0b932d4 to your computer and use it in GitHub Desktop.
Save koresar/aa4cad04453d5b307f8ed4f6e0b932d4 to your computer and use it in GitHub Desktop.
Protect JS object properties
const HasProtectedAccessor = stampit({
// stamp configuration
deepConf: {
// collect all the property names to protect
protectedProperties: {}
},
statics: {
// API of the stamp
protectProperty(names) {
// will deep merge the base objects with `names`
return this.deepConf({ protectedProperties: names });
}
},
init(keyValueMap, { stamp }) {
// The properties to protect
let { protectedProperties } = stamp.compose.deepConfiguration || {};
// The closured map of protector functions
const protectors = new Map(Object.entries(protectedProperties)
.filter(([key, value]) => typeof value === "function"));
// The closured map of protected values
const map = new Map();
for (const key of protectors.keys()) map.set(key, undefined);
for (const name of map.keys()) {
// Using JS getters and setters to protect properties
Object.defineProperty(this, name, {
get () { return map.get(name); },
set (value) {
if (protectors.get(name)(value, name))
map.set(name, value);
}
});
}
// Initialise this object instance with the configured values
for (const [key, value] of Object.entries(keyValueMap)) {
if (map.has(key)) this[key] = value;
}
}
});
const _ = require("lodash");
const TestAccessors = stampit(
HasProtectedAccessor.protectProperty({
fullName: v => v === undefined || _.isString(v),
address: _.isArray,
}),
{ name: "TestAccessors" }
);
const instance1 = TestAccessors({ fullName: "John Johnson", address: [] });
t.strictEqual(instance1.fullName, "John Johnson");
t.deepEqual(instance1.address, []);
const instance2 = TestAccessors({ fullName: ["array"], address: "oops" }); // WILL NOT SET
t.strictEqual(instance2.fullName, undefined);
t.strictEqual(instance2.address, undefined);
instance2.fullName = function () {}; // WILL NOT SET
t.strictEqual(instance2.fullName, undefined);
instance2.address = { NotAnArray: 111 }; // WILL NOT SET
t.strictEqual(instance2.address, undefined);
instance2.fullName = "Andrew Anderson";
t.strictEqual(instance2.fullName, "Andrew Anderson");
instance2.address = ["111 Acme St", "London"];
t.deepEqual(instance2.address, ["111 Acme St", "London"]);
instance2.fullName = undefined;
t.strictEqual(instance2.fullName, undefined);
instance2.address = undefined; // WILL NOT SET
t.deepEqual(instance2.address, ["111 Acme St", "London"]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment