Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
const Enmap = require("enmap");
// Normal enmap with default options
const myEnmap = new Enmap({name: "points"});
// non-cached, auto-fetch enmap:
const otherEnmap = new Enmap({
name: "settings",
autoFetch: true,
fetchAll: false
});<Enmap>.set(key, value);myEnmap.set('boolean', true);
myEnmap.set('integer', 42);
myEnmap.set('someFloat', 73.2345871);
myEnmap.set("Test2", "test2");const floatValue = myEnmap.get('someFloat');
const test = myEnmap.get('Test2');
// you can even use booleans in conditions:
if(myEnmap.get('boolean')) {
// boolean is true!
}myEnmap.delete("integer");
myEnmap.delete("boolean");const Enmap = require("enmap");
const Provider = require("enmap-mongo");
const SQLite = require("enmap-sqlite");
let options = {
name: "test",
user: "username",
host: "yourhost",
collection: "enmap",
password: "password",
port: 55258
};
const source = new Provider(options);
const target = new SQLite({"name": "test", dataDir: '../coolbot-copy/data'});
Enmap.migrate(source, target).then( () => process.exit(0) );const Enmap = require("enmap");
const SQLite = require("enmap-sqlite");
const source = new SQLite({"name": "test"});
const target = new SQLite({"name": "test"});
Enmap.migrate(source, target).then( () => process.exit(0) );// Change From:
const Enmap = require("enmap");
const Provider = require("enmap-mongo");
client.points = new Enmap({provider: new Provider({name: "points", url: "blah"});
// Change To:
const Enmap = require("enmap");
client.points = new Enmap({name: "points"});// Change from V3:
const Enmap = require("enmap");
const Provider = require("enmap-mongo");
Object.assign(client, Enmap.multi(["settings", "tags"], Provider, { url: "blah" }));
// Change to V4:
const Enmap = require("enmap");
Object.assign(client, Enmap.multi(["settings", "tags"]));// First run:
npm i -g --add-python-to-path --vs2015 --production windows-build-tools
// Then run:
npm i -g node-gyp@latestnpm i enmapconst myObject = {
a: "foo",
b: true,
c: {
but: "who",
are: "you?",
and: ["are you", "you?"],
},
sub: { values: { are: { "cool" } } },
};myEnmap.set("myObject", {
a: "foo",
b: true,
c: {
but: "who",
are: "you?",
and: ["are you", "you?"],
},
sub: { values: { are: { "cool" } } },
});enmap.fetch([array, of, keys]) will fetch each key in the requested array, and return an array of [key, value] pairs for each fetched value. const Enmap = require("enmap");
const points = new Enmap({
name: "points",
fetchAll: false,
autoFetch: true
});const myStructure = {
first: "blah",
second: "foo",
changeme: "initial",
isCool: false
sub: {
yay: true,
thing: "amagig"
}
}const Enmap = require("enmap");
client.points = new Enmap("points");myEnmap.set("someObject", myStructure);
// Or directly the object
myEnmap.set("someObject", {first: "blah", ...});
// Works with arrays, too!
myEnmap.set("someArray", ["one", "two", "three"]);const second = myEnmap.get("someObject", "second");
// returns "foo"
const thing = myEnmap.get("someObject", "sub.yay");
// returns true
// The path can be dynamic, too:
const propToGet = "thing";
const blah = myEnmap.get("someObject", `sub.${propToGet}`);myEnmap.has("someObject", "sub.thing"); // returns true
myEnmap.has("someObject", "heck"); // returns false.// Set an object property
myEnmap.set("someObject", "newThing", "sub.blah");
// Set an array property
myEnmap.set("someArray", "four", 3);client.on("message", message => {
if (message.author.bot) return;
// This is where we'll put our code.
if (message.content.indexOf(config.prefix) !== 0) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
// Command-specific code here!
});client.on("message", message => {
if (message.author.bot) return;
if (message.guild) {
// This is where we'll put our code.
}
// Rest of message handler
});client.on("message", message => {
if (message.author.bot) return;
if (message.guild) {
client.points.ensure(`${message.guild.id}-${message.author.id}`, {
user: message.author.id,
guild: message.guild.id,
points: 0,
level: 1
});
// Code continued...
}
// Rest of message handler
});client.on("message", message => {
if (message.author.bot) return;
if (message.guild) {
// Let's simplify the `key` part of this.
const key = `${message.guild.id}-${message.author.id}`;
client.points.ensure(key, {
user: message.author.id,
guild: message.guild.id,
points: 0,
level: 1
});
client.points.inc(key, "points");
}
// Rest of message handler
});const curLevel = Math.floor(0.1 * Math.sqrt(client.points.get(key, "points")));if (client.points.get(key, "level") < curLevel) {
message.reply(`You've leveled up to level **${curLevel}**! Ain't that dandy?`);
}client.points.set(key, curLevel, "level");client.on("message", message => {
// As usual, ignore all bots.
if (message.author.bot) return;
// If this is not in a DM, execute the points code.
if (message.guild) {
// We'll use the key often enough that simplifying it is worth the trouble.
const key = `${message.guild.id}-${message.author.id}`;
// Triggers on new users we haven't seen before.
client.points.ensure(`${message.guild.id}-${message.author.id}`, {
user: message.author.id,
guild: message.guild.id,
points: 0,
level: 1
});
client.points.inc(key, "points");
// Calculate the user's current level
const curLevel = Math.floor(0.1 * Math.sqrt(client.points.get(key, "points")));
// Act upon level up by sending a message and updating the user's level in enmap.
if (client.points.get(key, "level") < curLevel) {
message.reply(`You've leveled up to level **${curLevel}**! Ain't that dandy?`);
client.points.set(key, curLevel, "level");
}
}
// Rest of message handler
});client.on("message", message => {
if (message.author.bot) return;
if (message.guild) { /* Points Code Here */ }
if (message.content.indexOf(config.prefix) !== 0) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
// Command-specific code here!
}); if (command === "points") {
const key = `${message.guild.id}-${message.author.id}`;
return message.channel.send(`You currently have ${client.points.get(key, "points")} points, and are level ${client.points.get(key, "level")}!`);
}if(command === "leaderboard") {
// Get a filtered list (for this guild only), and convert to an array while we're at it.
const filtered = client.points.filter( p => p.guild === message.guild.id ).array();
// Sort it to get the top results... well... at the top. Y'know.
const sorted = filtered.sort((a, b) => b.points - a.points);
// Slice it, dice it, get the top 10 of it!
const top10 = sorted.splice(0, 10);
// Now shake it and show it! (as a nice embed, too!)
const embed = new Discord.MessageEmbed()
.setTitle("Leaderboard")
.setAuthor(client.user.username, message.guild.iconURL())
.setDescription("Our top 10 points leaders!")
.setColor(0x00AE86);
for(const data of top10) {
try {
embed.addField(client.users.cache.get(data.user).tag, `${data.points} points (level ${data.level})`);
} catch {
embed.addField(`<@${data.user}>`, `${data.points} points (level ${data.level})`);
}
}
return message.channel.send({embed});
} if(command === "give") {
// Limited to guild owner - adjust to your own preference!
if(message.author.id !== message.guild.ownerID)
return message.reply("You're not the boss of me, you can't do that!");
const user = message.mentions.users.first() || client.users.get(args[0]);
if(!user) return message.reply("You must mention someone or give their ID!");
const pointsToAdd = parseInt(args[1], 10);
if(!pointsToAdd)
return message.reply("You didn't tell me how many points to give...")
// Ensure there is a points entry for this user.
client.points.ensure(`${message.guild.id}-${user.id}`, {
user: message.author.id,
guild: message.guild.id,
points: 0,
level: 1
});
// Get their current points.
let userPoints = client.points.get(`${message.guild.id}-${user.id}`, "points");
userPoints += pointsToAdd;
// And we save it!
client.points.set(`${message.guild.id}-${user.id}`, userPoints, "points")
message.channel.send(`${user.tag} has received **${pointsToAdd}** points and now stands at **${userPoints}** points.`);
}
if(command === "cleanup") {
// Let's clean up the database of all "old" users,
// and those who haven't been around for... say a month.
// Get a filtered list (for this guild only).
const filtered = client.points.filter( p => p.guild === message.guild.id );
// We then filter it again (ok we could just do this one, but for clarity's sake...)
// So we get only users that haven't been online for a month, or are no longer in the guild.
const rightNow = new Date();
const toRemove = filtered.filter(data => {
return !message.guild.members.cache.has(data.user) || rightNow - 2592000000 > data.lastSeen;
});
toRemove.forEach(data => {
client.points.delete(`${message.guild.id}-${data.user}`);
});
message.channel.send(`I've cleaned up ${toRemove.size} old farts.`);
}const Discord = require("discord.js");
const client = new Discord.Client();
const Enmap = require("enmap");
// this is the important bit
client.settings = new Enmap({ name: "settings" });
client.tags = new Enmap({ name: "tags" });
// your normal events here
client.on("message", message => {
const guildSettings = client.settings.get(message.guild.id);
// works here
});
client.login(token);const Enmap = require("enmap");
module.exports = {
settings: new Enmap({
name: "settings",
autoFetch: true,
fetchAll: false
}),
users: new Enmap("users"),
tags: new Emmap({ name : "tags" })
}const db = require("./db.js");
console.log(db.settings.size);
db.tags.set("blah", {
guild: "1234",
author: "4231",
name: "blah",
content: "I'm bored, mommy!"
});const guildTags = db.tags.find(tag => tag.guild === message.guild.id);const Enmap = require("enmap");
module.exports = {
settings: new Enmap({
name: "settings",
autoFetch: true,
fetchAll: false
}),
users: new Enmap("users"),
tags: new Emmap({ name : "tags" }),
getTags: (guild) => {
return this.tags.find(tag => tag.guild === message.guild.id);
}
}The complete and unadultered API documentation for every single method and property accessible in Enmap.
integerarray.<string>number****Promise.<*>*booleanbooleannullstringArrayArray.<(string|number)>* | Array.<*>* | Array.<*>Array*string | numbernumberArrayArraybooleanboolean*Array.<Map>This page describes using 2 different enmaps in tandem using autonum and a reference array.
// start discord.js init
// config with token and prefix.
const config = require("./config.json");
// Code below supports and is tested under "stable" 11.3.x
const Discord = require("discord.js");
const client = new Discord.Client();
// end discord.js init
// Initialize the server configurations
const Enmap = require('enmap');
// I attach settings to client to allow for modular bot setups
// In this example we'll leverage fetchAll:false and autoFetch:true for
// best efficiency in memory usage. We also have to use cloneLevel:'deep'
// to avoid our values to be "reference" to the default settings.
// The explanation for why is complex - just go with it.
client.settings = new Enmap({
name: "settings",
fetchAll: false,
autoFetch: true,
cloneLevel: 'deep',
autoEnsure: {
prefix: "!",
modLogChannel: "mod-log",
modRole: "Moderator",
adminRole: "Administrator",
welcomeChannel: "welcome",
welcomeMessage: "Say hello to {{user}}, everyone!"
}
});
djs-collection-persistent
myEnmap.push("simpleArray", 6);
// now [1,2,3,4,5,6]
myEnmap.push("arrInObj", "Robby", "aliases");
// now ["Bobby", "Robert", "Robby"]myEnmap.remove("simpleArray", 2);
// now [1,3,4,5,6]
myEnmap.remove("arrInObject", "Bobby", "aliases");
// now ["Robert", "Robby"]
myEnmap.remove('objectarray', (value) => value.e === 5);
// value is now [{ a: 1, b: 2, c: 3 }]// the default serializer
const serializer = (data, key) => {
return data;
};// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.math("number", "/", 2); // 21
points.math("number", "add", 5); // 26
points.math("number", "modulo", 3); // 2
points.math("numberInObject", "+", 10, "sub.anInt");// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.inc("number"); // 43
points.inc("numberInObject", "sub.anInt"); // {sub: { anInt: 6 }}// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.dec("number"); // 41
points.dec("numberInObject", "sub.anInt"); // {sub: { anInt: 4 }}// the default deserializer
const deserializer = (data, key) => {
return data;
};// Imagine the client and stuff is already defined.
// The function that runs when storing data
const serializeData: data => {
return {
...data,
// stores the guild as ID
guild: guild.id,
// stores the user as ID
user: user.id,
}
};
// This one runs when loading.
const deserializeData: data => {
return {
...data,
// gets the guild itself from the cache from its ID
guild: client.guilds.cache.get(data.guild),
// Same with the user!
user: client.users.cache.get(data.user),
}
};
// Default Settings can no longer store defaults for roles and channels.
const defaultSettings = {
prefix: "!",
modLogChannel: null,
modRole: null,
adminRole: null,
welcomeChannel: null,
welcomeMessage: "Say hello to {{user}}, everyone!"
}
// Our enmap has shiny new options here!
client.settings = new Enmap({
name: "settings",
cloneLevel: 'deep',
serializer: serializeData,
deserializer: deserializeData,
// Might as well autoensure, eh?
autoEnsure: defaultSettings,
});
// Store some data, obviously needs to be run in the right place:
client.settings.set(message.guild.id,
message.mentions.channels.first(),
'welcomeChannel'
);
client.settings.set(message.guild.id,
message.mentions.roles.first(),
'adminRole'
);
// GET the data after
const welcomeChannel = client.settings.get(message.guild.id, 'welcomeChannel');
welcomeChannel.send("This works without having to find or get the channel!");client.on("guildDelete", guild => {
// When the bot leaves or is kicked, delete settings to prevent stale entries.
client.settings.delete(guild.id);
});
client.on("guildMemberAdd", member => {
// This executes when a member joins, so let's welcome them!
// First, ensure the settings exist
client.settings.ensure(member.guild.id, defaultSettings);
// First, get the welcome message using get:
let welcomeMessage = client.settings.get(member.guild.id, "welcomeMessage");
// Our welcome message has a bit of a placeholder, let's fix that:
welcomeMessage = welcomeMessage.replace("{{user}}", member.user.tag)
// we'll send to the welcome channel.
member.guild.channels.cache
.find(channel => channel.name === client.settings.get(member.guild.id, "welcomeChannel"))
.send(welcomeMessage)
.catch(console.error);
});client.on("message", async (message) => {
// This stops if it's not a guild (obviously), and we ignore all bots.
// Pretty standard for any bot.
if(!message.guild || message.author.bot) return;
// We get the value, and autoEnsure guarantees we have a value already.
const guildConf = client.settings.get(message.guild.id);
// Now we can use the values! We stop processing if the message does not
// start with our prefix for this guild.
if(message.content.indexOf(guildConf.prefix) !== 0) return;
//Then we use the config prefix to get our arguments and command:
const args = message.content.split(/\s+/g);
const command = args.shift().slice(guildConf.prefix.length).toLowerCase();
// Commands Go Here
}); // Alright. Let's make a command! This one changes the value of any key
// in the configuration.
if(command === "setconf") {
// Command is admin only, let's grab the admin value:
const adminRole = message.guild.roles.cache.find(role => role.name === guildConf.adminRole);
if(!adminRole) return message.reply("Administrator Role Not Found");
// Then we'll exit if the user is not admin
if(!message.member.roles.cache.has(adminRole.id)) {
return message.reply("You're not an admin, sorry!");
}
// Let's get our key and value from the arguments.
// This is array destructuring, by the way.
const [prop, ...value] = args;
// Example:
// prop: "prefix"
// value: ["+"]
// (yes it's an array, we join it further down!)
// We can check that the key exists to avoid having multiple useless,
// unused keys in the config:
if(!client.settings.has(message.guild.id, prop)) {
return message.reply("This key is not in the configuration.");
}
// Now we can finally change the value. Here we only have strings for values
// so we won't bother trying to make sure it's the right type and such.
client.settings.set(message.guild.id, value.join(" "), prop);
// We can confirm everything's done to the client.
message.channel.send(`Guild configuration item ${prop} has been changed to:\n\`${value.join(" ")}\``);
} if(command === "showconf") {
let configProps = Object.keys(guildConf).map(prop => {
return `${prop} : ${guildConf[prop]}`;
});
message.channel.send(`The following are the server's current configuration:
\`\`\`${configProps.join("\n")}\`\`\``);
}npm i enmap better-sqlite-pool koa koa-session koa-ejs koa-bodyparser koa-router bcrypt// Native Imports
const { sep, resolve, join } = require("path");
// Enmap Imports
const Enmap = require("enmap");
const users = new Enmap({ name: "users" });
// Bcrypt's hashing system
const bcrypt = require("bcrypt");
// Koa Imports
const Koa = require("koa");
// Koa's EJS renderer for HTML views.
const render = require("koa-ejs");
// The Body Parser to accept incoming form data and file uploads.
const parser = require("koa-bodyparser");
// The default "sessions" support.
const session = require("koa-session");
// Koa's get/post/etc router to simplify routes.
const Router = require("koa-router");
// Initializing the main components.
const router = new Router();
const app = new Koa();
// Define the data directory for templates (views).
const dataDir = resolve(`${process.cwd()}${sep}`);const newuser = (username, name, plainpw, admin = false) => {
if (users.has(username)) throw Error(`User ${username} already exists!`);
bcrypt.hash(plainpw, 10, (err, password) => {
if (err) throw err;
users.set(username, {
username, name, password, admin, created: Date.now()
});
});
};const login = (username, password) => {
const user = this.users.get(username);
if (!user) return new Promise(resp => resp(false));
if (!password) return new Promise(resp => resp(false));
return bcrypt.compare(password, user.password);
};app.keys = ['some secret hurr'];
app.use(session(app));render(app, {
root: join(__dirname, 'views'),
layout: 'template',
viewExt: 'html',
cache: false,
debug: true
});router.get("/", async (ctx, next) => {
// This is our static index page. It will render the views/index.js file
await ctx.render("index");
});// we obviously need a route to show the login page itself, too!
router.get("/login", async (ctx) => {
await ctx.render("login");
});
router.post("/login", async (ctx) => {
// Fail if there is no username and password.
// This relies on koa-bodyparser
if (!ctx.request.body.username || !ctx.request.body.password) {
ctx.throw(400, "Missing Username or Password");
}
// Use our login function to verify the username/password is correct
const success = await login(ctx.request.body.username, ctx.request.body.password);
if (success) {
// get the user's information
const user = users.get(ctx.request.body.username);
// Set all our session parameters:
ctx.session.logged = true;
ctx.session.username = ctx.request.body.username;
ctx.session.admin = user.admin;
ctx.session.name = user.name;
// Save the session itself. This sets the cookie in the browser,
// as well as save into the sessions in memory.
ctx.session.save();
console.log(`User authenticated: ${user.username}`);
// Once logged in, redirect to the secret page.
ctx.redirect("/secret");
} else {
console.log("Authentication Failed");
// Throw if the above login returns false.
ctx.throw(403, "Nope. Not allowed, mate.");
}
});router.get("/logout", async (ctx) => {
ctx.session = null;
ctx.redirect("/");
});router.get("/secret", async (ctx) => {
if(!ctx.session.logged) ctx.throw(403, "Unauthorized to view this page");
await ctx.render("secret");
});app
.use(parser())
.use(router.routes())
.use(router.allowedMethods());
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
app.listen(3000);<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>A Page</title>
</head>
<body>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/login">Login</a></li>
<li><a href="/secret">Secret</a></li>
</ul>
</nav>
<%- body %>
</body>
</html><h1>Index</h1>
<p>Lorem Ipsum Carrots</p><h1>Login</h1>
<form method="POST">
<p>Username: <input type="text" name="username" id="username"></p>
<p>Password: <input type="password" name="password" id="password"></p>
<p><button type="submit">Login</button></p>
</form><h1>Some Secret</h1>
<p>Han Shot First.</p>
client.modActions = new Enmap({
name: 'actions'
});const newActionId = client.modActions.autonum;
client.modActions.set(newActionId, {
user: target.id,
guild: message.guild.id,
type: 'warning',
moderator: message.author.id,
reason: "Don't do it again!",
when: Date.now()
});client.userProfiles = new Enmap({
name: 'userProfiles'
});client.userProfiles.ensure(message.author.id, {
id: message.author.id,
guild: message.guild.id,
totalActions: 0,
warnings: [],
kicks: []
});if (command === 'warn') {
// get a target user
const target = message.mentions.users.first();
// remove the mention from the message, join for a reason
const reason = args.slice(1).join(" ");
const newActionId = client.modActions.autonum;
client.modActions.set(newActionId, {
user: target.id,
guild: message.guild.id,
type: 'warning',
moderator: message.author.id,
reason: reason,
when: Date.now()
});
// Push the action to the user's warnings
client.userProfiles.push(target.id, newActionId, 'warnings');
client.userProfiles.inc(target.id, 'totalActions');
// then send some message or embed or whatever
message.channel.send(`${target} was warned for '${reason}'`);
}if (command === 'mywarns') {
const warnIDs = client.userProfiles.get(message.author.id, 'warnings');
const warnData = warnIDs.map(id => client.modActions.get(id));
// have fun displaying this wooh!
message.reply(`You have ${warnIDs.length} warns, buddy!`);
}const Enmap = require("enmap");
// Non-persistent enmap:
const inMemory = new Enmap();
// Named, Persistent enmap with string option
const myEnmap = new Enmap("testing");
// Enmap that does not fetch everything, but does so on per-query basis:
const myEnmap = new Enmap({name: "testing", fetchAll: false});
// Enmap that automatically assigns a default object when getting or setting anything.
const autoEnmap = new Enmap({name: "settings", autoEnsure: { setting1: false, message: "default message"}})enmap.set(enmap.autonum, "This is a new value");// Direct Value Examples
enmap.set('simplevalue', 'this is a string');
enmap.set('isEnmapGreat', true);
enmap.set('TheAnswer', 42);
enmap.set('IhazObjects', { color: 'black', action: 'paint', desire: true });
enmap.set('ArraysToo', [1, "two", "tree", "foor"])
// Settings Properties
enmap.set('IhazObjects', 'blue', 'color'); //modified previous object
enmap.set('ArraysToo', 'three', 2); // changes "tree" to "three" in array.// Define an object we're going to update
enmap.set("obj", { a: 1, b: 2, c: 3 });
// Direct merge
enmap.update("obj", { d: 4, e: 5 });
// obj is now { a: 1, b: 2, c: 3, d: 4, e: 5 }
// Functional update
enmap.update("obj", (previous) => ({
...obj,
f: 6,
g: 7
}));
// this example takes heavy advantage of the spread operators.
// More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntaxconst myKeyValue = enmap.get("myKey");
console.log(myKeyValue);
const someSubValue = enmap.get("anObjectKey", "someprop.someOtherSubProp");enmap.changed((keyName, oldValue, newValue) => {
console.log(`Value of ${keyName} has changed from: \n${oldValue}\nto\n${newValue}`);
});// Assuming
enmap.set("simpleArray", [1, 2, 3, 4]);
enmap.set("arrayInObject", {sub: [1, 2, 3, 4]});
enmap.push("simpleArray", 5); // adds 5 at the end of the array
enmap.push("arrayInObject", "five", "sub"); // adds "five" at the end of the sub array// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.math("number", "/", 2); // 21
points.math("number", "add", 5); // 26
points.math("number", "modulo", 3); // 2
points.math("numberInObject", "+", 10, "sub.anInt");// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.inc("number"); // 43
points.inc("numberInObject", "sub.anInt"); // {sub: { anInt: 6 }}// Assuming
points.set("number", 42);
points.set("numberInObject", {sub: { anInt: 5 }});
points.dec("number"); // 41
points.dec("numberInObject", "sub.anInt"); // {sub: { anInt: 4 }}// Simply ensure the data exists (for using property methods):
enmap.ensure("mykey", {some: "value", here: "as an example"});
enmap.has("mykey"); // always returns true
enmap.get("mykey", "here") // returns "as an example";
// Get the default value back in a variable:
const settings = mySettings.ensure("1234567890", defaultSettings);
console.log(settings) // enmap's value for "1234567890" if it exists, otherwise the defaultSettings value.if(enmap.has("myKey")) {
// key is there
}
if(!enmap.has("myOtherKey", "oneProp.otherProp.SubProp")) return false;// Assuming
enmap.set('array', [1, 2, 3])
enmap.set('objectarray', [{ a: 1, b: 2, c: 3 }, { d: 4, e: 5, f: 6 }])
enmap.remove('array', 1); // value is now [2, 3]
enmap.remove('objectarray', (value) => value.e === 5); // value is now [{ a: 1, b: 2, c: 3 }]enmap.findAll('username', 'Bob');enmap.find('username', 'Bob');enmap.find(val => val.username === 'Bob');enmap.findKey('username', 'Bob');enmap.findKey(val => val.username === 'Bob');const newColl = someColl.clone();const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl);// Using local variables.
const Enmap = require('enmap');
const { settings, tags, blacklist } = Enmap.multi(['settings', 'tags', 'blacklist']);
// Attaching to an existing object (for instance some API's client)
const Enmap = require("enmap");
Object.assign(client, Enmap.multi(["settings", "tags", "blacklist"]));