Created
November 30, 2019 21:32
-
-
Save crobinson42/36c6ccd7dbe03df67c58b1a1f59e1046 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* | |
This exported object is to be used when extending a class, ie: DataStore or Container. | |
There is special consideration here for not having the ability to use the keyword "super" | |
so we workaround with "Object.getPrototypeOf(this).findAll.call(this, ..." to get the | |
parent classes (super) methods. | |
*/ | |
const { recordsToJson } = require('./utils') | |
module.exports = { | |
as(name) { | |
const mapper = this.getMapper(name) | |
const self = this | |
const proxy = new Proxy(this, { | |
get(target, prop) { | |
// first try the prop on the Container/DataStore | |
if (target[prop]) | |
return (...args) => target[prop].apply(self, [name, ...args]) | |
// then try the mapper because we have custom props on mapper classes | |
if (mapper[prop] && typeof mapper[prop] === 'function') | |
return (...args) => mapper[prop].apply(self, args) | |
if (mapper[prop]) return mapper[prop] | |
throw new Error(`containerOverrides.as mapper prop "${prop}" not found`) | |
}, | |
}) | |
return proxy | |
}, | |
findById(mapperName, idOrIdList, opts) { | |
return this.findAll( | |
mapperName, | |
{ | |
where: { id: { in: idOrIdList } }, | |
}, | |
opts, | |
) | |
}, | |
findOne(mapperName, query, opts) { | |
// https://americansoftware.atlassian.net/browse/TCL-6 | |
if (!query || !Object.values(query || {}).length) return Promise.resolve(undefined) | |
return this.findAll(mapperName, { limit: 1, where: query }, opts).then( | |
result => { | |
if (Array.isArray(result)) return result[0] || undefined | |
return result | |
}, | |
) | |
}, | |
/** | |
* Over-ride async/sync methods on Container/DataStore class. | |
* We don't want computed prop objects returned from Record class but we want the relations loaded | |
* | |
* @NOTE: to bypass this over-ride and get the Record class instance returned, pass `withRecordClass: true` | |
* in the crud method options, ie: Store.User.find('123', { withRecordClass:true }) | |
* | |
*/ | |
create(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).create.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.create.call(this, ...args) | |
.then(recordsToJson) | |
}, | |
find(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).find.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.find.call(this, ...args) | |
.then(recordsToJson) | |
}, | |
findAll(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).findAll.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.findAll.call(this, ...args) | |
.then(recordsToJson) | |
}, | |
update(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).update.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.update.call(this, ...args) | |
.then(recordsToJson) | |
}, | |
updateAll(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).updateAll.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.updateAll.call(this, ...args) | |
.then(recordsToJson) | |
}, | |
get(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).get.call(this, ...args) | |
const record = Object.getPrototypeOf(this).get.call(this, ...args) | |
return recordsToJson(record) | |
}, | |
getAll(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).getAll.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.getAll.call(this, ...args) | |
.map(recordsToJson) | |
}, | |
filter(...args) { | |
if (args[2] && args[2].withRecordClass) | |
return Object.getPrototypeOf(this).filter.call(this, ...args) | |
return Object.getPrototypeOf(this) | |
.filter.call(this, ...args) | |
.map(recordsToJson) | |
}, | |
} |
This file contains hidden or 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
const { DataStore } = require('js-data') | |
class ExtendedDataStore extends DataStore { | |
constructor(props) { | |
super(props) | |
if (props.extends) | |
Object.assign(this, props.extends) | |
} | |
} | |
module.exports = ExtendedDataStore |
This file contains hidden or 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
const { Mapper } = require('js-data') | |
class ExtendedMapper extends Mapper { | |
constructor(props) { | |
super(props) | |
if (props.extends) | |
Object.assign(this, props.extends) | |
} | |
} | |
module.exports = ExtendedMapper |
This file contains hidden or 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
const ExtendedDataStore = require('./ExtendedDataStore') | |
const ExtendedMapper = require('./ExtendedMapper') | |
const overrides = require('./containerOverrides') | |
const store = new ExtendedDataStore({ | |
extends: overrides, | |
mapperClass: ExtendedMapper, | |
}) | |
// @note: these models should be in their own files with a full schema for each | |
const models = ['users', 'messages', 'bulletins'] | |
// Load all models in store | |
Object.keys(models).forEach(modelName => { | |
try { | |
store.defineMapper(modelName) | |
const modelAs = store.as(modelName) | |
// add the model to the store object capitalizing the first letter so | |
// it's available like this: `store.User.findAll({ where: {...} })` | |
store[`${modelName[0].toLocaleUpperCase()}${modelName.substr(1)}`] = modelAs | |
store[modelName] = modelAs | |
} catch (e) { | |
console.log(` Failed to define mapper "${modelName}"`) // eslint-disable-line no-console | |
throw e | |
} | |
}) | |
module.exports = store |
This file contains hidden or 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
/** | |
* A helper to invoked .toJSON on js-data Record objects | |
* @param result {Object|Array} | |
* @returns {*} | |
*/ | |
module.exports.recordsToJson = result => | |
// eslint-disable-next-line no-nested-ternary | |
result && Array.isArray(result) | |
? result.map(record => | |
record.toJSON ? record.toJSON({ withAll: true }) : record, | |
) | |
: result && result.toJSON | |
? result.toJSON({ withAll: true }) | |
: result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment