Created
September 3, 2018 14:23
-
-
Save nclsndr/c47fb601cef289b5ec5d621ea9a41608 to your computer and use it in GitHub Desktop.
Mongo Document manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------ | |
DataCollection | |
--------------------------------------------- */ | |
class DataCollection { | |
constructor(v) { | |
this.value = v || [] | |
} | |
override(v) { | |
this.value = v.slice(0) | |
} | |
exec(fn) { | |
this.value = fn(this.value) | |
} | |
get() { | |
return this.value | |
} | |
} | |
module.exports = DataCollection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------ | |
DataMap | |
--------------------------------------------- */ | |
class DataMap { | |
constructor(v) { | |
this.value = v || {} | |
} | |
set(k, v) { | |
this.value = { ...this.value, [k]: v } | |
} | |
remove(k) { | |
this.value = Object | |
.entries(this.value) | |
.reduce((acc, [a,b]) => ({ | |
...acc, | |
...k === a ? {} : { [a]: b } | |
}), {}) | |
} | |
merge(v) { | |
this.value = { ...this.value, ...v } | |
} | |
get() { | |
return this.value | |
} | |
} | |
module.exports = DataMap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------ | |
Document | |
--------------------------------------------- */ | |
const { ObjectId } = require('mongodb') | |
const capitalize = require('lodash/capitalize') | |
const { get } = require('../../services/db') | |
const HooksManager = require('./HooksManager') | |
const DataCollection = require('./DataCollection') | |
const DataMap = require('./DataMap') | |
const Schema = require('./Schema') | |
// TODO @Nico : Delete | |
// TODO @Nico : Set index | |
class Document { | |
constructor(collection, schema) { | |
this.schema = new Schema(schema) | |
this.collection = collection | |
this.schema = {} | |
this.hooks = { | |
beforeCreate: new HooksManager('beforeCreate'), | |
afterCreate: new HooksManager('afterCreate'), | |
beforeUpdate: new HooksManager('beforeUpdate'), | |
afterUpdate: new HooksManager('afterUpdate'), | |
beforeFind: new HooksManager('beforeFind'), | |
afterFind: new HooksManager('afterFind'), | |
afterFindById: new HooksManager('afterFindById'), | |
} | |
} | |
registerHookDomain(name) { | |
const pre = `before${capitalize(name)}` | |
this.hooks[pre] = new HooksManager(pre) | |
const post = `after${capitalize(name)}` | |
this.hooks[post] = new HooksManager(post) | |
} | |
registerHook(hook, signature, promise) { | |
const hookNames = Object.keys(this.hooks) | |
if (!hookNames.includes(hook)) throw new Error(`Document do not contains "${hook}" hook`) | |
this.hooks[hook].register(signature, promise) | |
} | |
removeHook(hook, signature) { | |
const hookNames = Object.keys(this.hooks) | |
if (!hookNames.includes(hook)) throw new Error(`Document do not contains "${hook}" hook`) | |
this.hooks[hook].remove(signature) | |
} | |
async create(data) { | |
const db = await get() | |
const preHooksResult = new DataMap(data) | |
await this.hooks.beforeCreate.run(data, preHooksResult) | |
const doc = await db | |
.collection(this.collection) | |
.insertOne(preHooksResult.get()) | |
.then(op => op.ops[0]) | |
const postHooksResult = new DataMap(doc) | |
await this.hooks.afterCreate.run(doc, postHooksResult) | |
return postHooksResult.get() | |
} | |
async update(filter, upgrade, options) { | |
const db = await get() | |
const preHooksResult = new DataMap(upgrade) | |
await this.hooks.beforeCreate.run(upgrade, preHooksResult) | |
const doc = await db | |
.collection(this.collection) | |
.findOneAndUpdate(filter, preHooksResult, {...options, new: true }) | |
.then(op => op.value) | |
const postHooksResult = new DataMap(doc) | |
await this.hooks.afterUpdate.run(doc, postHooksResult) | |
return postHooksResult.get() | |
} | |
async find(query, options) { | |
const db = await get() | |
const preHooksResult = new DataMap(query) | |
await this.hooks.beforeFind.run(query, preHooksResult) | |
const docs = await db | |
.collection(this.collection) | |
.find(preHooksResult.get(), options) | |
.toArray() | |
const postHooksResult = new DataCollection(docs) | |
await this.hooks.afterFind.run(docs, postHooksResult) | |
return postHooksResult.get() | |
} | |
async findById(id, options) { | |
const db = await get() | |
const docs = await db | |
.collection(this.collection) | |
.find({ _id: ObjectId(id) }, options) | |
.toArray() | |
if (docs.length === 0) return null | |
const doc = docs.reduce((acc, c) => ({ ...acc, ...c }), {}) | |
const postHooksResult = new DataMap(doc) | |
await this.hooks.afterFindById.run(doc, postHooksResult) | |
return postHooksResult.get() | |
} | |
async collection() { | |
const db = await get() | |
return db.collection(this.collection) | |
} | |
} | |
module.exports = Document |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------ | |
HooksManager | |
--------------------------------------------- */ | |
class HooksManager { | |
constructor(name) { | |
this.name = name | |
this.fns = [] | |
} | |
register(signature, promise) { | |
this.fns.forEach(h => { | |
if (h.signature === signature) throw new Error(`Signature ${signature} is already registered`) | |
}) | |
this.fns.push({ signature, promise }) | |
} | |
remove(signature) { | |
const index = this.fns.reduce((acc, c, i) => c.signature === signature ? i : acc, -1) | |
this.fns.splice(index, 1) | |
} | |
async run(...args) { | |
const [...inputs, output] = args | |
if (this.fns.length === 0) return Promise.resolve(output) | |
for (let f of this.fns) { | |
await f.promise(...inputs, output) | |
} | |
} | |
} | |
module.exports = HooksManager |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------ | |
Schema manager | |
--------------------------------------------- */ | |
class Schema { | |
constructor({ shape }) { | |
this.shape = shape | |
} | |
generate(input) { | |
const final = Object | |
.entries(this.shape) | |
// .() | |
return { | |
updatedAt: null, | |
createdAt: new Date() | |
} | |
} | |
} | |
module.exports = Schema |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment