@gameroom/kit
Version:
Node kit for the Gameroom API
149 lines (146 loc) • 5.14 kB
JavaScript
const uuid = require('uuid')
const config = require('../config'),
{ SecondsFrom1970 } = require('../lib'),
store = require('../store')
module.exports = store.define(
'Base',
{
created_at: { type: SecondsFrom1970, default: SecondsFrom1970.now },
updated_at: { type: SecondsFrom1970, default: SecondsFrom1970.now },
id: { type: String, default: uuid.v1 }
},
{
collectionMethods: {
batch(n) {
const result = []
for (let i = 0; i < this.length; i += n) result.push(this.slice(i, i + n))
return result
},
async get(Model, options, onBatch, onError) {
if (!options) options = {}
const schema = Model.schema.name.toLowerCase()
const foreign_key = options.foreign_key ? options.foreign_key : schema === 'address' ? 'addressable_id' : schema === 'charge' ? 'chargeable_id' : schema === 'image' ? 'imageable_id' : schema === 'note' ? 'noteable_id' : schema === 'changelog' ? 'changeable_id' : schema === 'location' ? 'locatable_id' : `${this.schema.name.toLowerCase().replace('_extended', '')}_id`
const results = new Model.Collection()
const key = options.key || 'id'
const promises = this.batch(60).reduce(
(a, b) => [
...a,
config.limit(async () => {
try {
const filter = { or: b.reduce((a, i) => [...a, { key: foreign_key, value: i[key] }], []) }
// const filter = { key, value: i.id }
const os = Object.assign({}, options)
os.filter = options.filter ? { and: [filter, options.filter] } : filter
const result = await Model.getAll(os)
results.push(...result)
if (onBatch) await onBatch(results)
} catch (err) {
if (onError) await onError(err)
}
})
],
[]
)
await Promise.all(promises)
return results
},
async refresh(onBatch, onError) {
const results = new this.constructor()
if (!this.length) return results
const Model = this[0].constructor
const promises = this.batch(60).reduce(
(a, b) => [
...a,
config.limit(async () => {
try {
const filter = { or: b.reduce((a, i) => [...a, { key: 'id', value: i.id }], []) }
const result = await Model.get({ filter })
results.push(...result)
if (onBatch) await onBatch(results)
} catch (err) {
if (onError) await onError(err, b)
}
})
],
[]
)
await Promise.all(promises)
return results
},
async save(onBatch, onError) {
const results = new this.constructor()
const promises = this.reduce(
(a, b) => [
...a,
config.limit(async () => {
try {
const result = await b.save()
results.push(result)
if (onBatch) await onBatch(results)
} catch (err) {
if (onError) await onError(err, b)
}
})
],
[]
)
await Promise.all(promises)
return results
}
},
staticMethods: {
async all(options, onBatch, onError) {
if (!options) options = {}
let { filter, limit, offset, sort } = options
if (!limit) limit = 500
if (!offset) offset = 0
if (!sort) sort = [{ created_at: 1 }]
const results = new this.Collection()
const promises = []
let done = false
while (!done) {
for (let i = 0; i < 20; i++) {
const options = { filter, limit, offset, sort }
promises.push(
config.limit(async () => {
try {
const result = await this.get(options)
results.unshift(...result)
if (onBatch) await onBatch(results)
if (result.length < limit) done = true
} catch (err) {
if (onError) await onError(err)
}
})
)
offset += limit
}
await Promise.all(promises)
}
return results
},
async getAll(options, onBatch, onError) {
if (!options) options = {}
let { filter, limit, offset, sort } = options
if (!limit) limit = 400
if (!offset) offset = 0
if (!sort) sort = [{ created_at: 1 }]
const results = new this.Collection()
let done = false
while (!done) {
try {
const storables = await this.get({ filter, limit, offset, sort })
results.push(...storables)
if (onBatch) await onBatch(results)
offset += limit
if (storables.length < limit) done = true
} catch (err) {
if (onError) await onError(err)
}
}
return results
}
},
strict: false
}
)