Creating an ODM

by molokoloco

HTML

https://jsfiddle.net/molokoloco/w82srpra/6/#run

Babel + JSX

// SOURCE : https://dev.to/ecarriou/creating-an-odm-with-javascript--523p

// create classes list
const classes = {};

// create instances list
const instances = {};

// create database
const db = {};

db.import = (name, documents) => {
  db[name] = JSON.parse(documents);

  // create instances
  Object.keys(db[name]).forEach((id) => {
    new classes[name](db[name][id]);
  });
};

db.export = (name) => {
  return JSON.stringify(db[name], null, 4);
};

class ODM {

  constructor(document) {
    // get class name
    const name = this.constructor.name;

    // add unique id
    if (!document._id) document._id = Math.random().toString();

    // create document
    if (!db[name]) db[name] = {};
    db[name][document._id] = document;

    // define accessors
    const configuration = {};
    Object.keys(document).forEach((prop) => {
      configuration[prop] = {
        get() {
          const value = db[name][document._id][prop];
          // return an instance or a value
          return value.indexOf('@') !== -1 ? instances[value.replace('@', '')] : value;
        },
        set(value) {
          if (classes[value.constructor.name]) {
            // store the id of the instance
            db[name][document._id][prop] = value._id;
          } else {
            db[name][document._id][prop] = value;
          }
        }
      };
    });

    // set accessors
    Object.defineProperties(this, configuration);

    // add it to the list of instances
    instances[document._id] = this;
  }
}

// create Jedi class
classes.Jedi = class Jedi extends ODM {};

const myVador = new classes.Jedi({
  _id: 'vador',
  'firstName': 'Dark',
  'lastName': 'Vador'
});

const myLuke = new classes.Jedi({
  _id: 'luke',
  'firstName': 'Luke',
  'lastName': 'Skywalker',
  'father': '@vador'
});

// Set father link  
//myLuke.father = myVador; // luke.father = '@vador';
console.log(myLuke.father.lastName);
//> Vador

// Final result
console.log(db.export('Jedi'));...