Skip to content

Instantly share code, notes, and snippets.

@crobinson42
Created November 30, 2019 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crobinson42/36c6ccd7dbe03df67c58b1a1f59e1046 to your computer and use it in GitHub Desktop.
Save crobinson42/36c6ccd7dbe03df67c58b1a1f59e1046 to your computer and use it in GitHub Desktop.
/*
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)
},
}
const { DataStore } = require('js-data')
class ExtendedDataStore extends DataStore {
constructor(props) {
super(props)
if (props.extends)
Object.assign(this, props.extends)
}
}
module.exports = ExtendedDataStore
const { Mapper } = require('js-data')
class ExtendedMapper extends Mapper {
constructor(props) {
super(props)
if (props.extends)
Object.assign(this, props.extends)
}
}
module.exports = ExtendedMapper
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
/**
* 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