Created
May 7, 2017 00:17
-
-
Save caseyWebb/daf35c7ae617555bf8335f6608465007 to your computer and use it in GitHub Desktop.
Simple MongoDB Persistence
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
import * as Bluebird from 'bluebird' | |
import * as db from './db' | |
import Persistable from './_persistable' | |
beforeAll(() => db.connect()) | |
afterEach(() => db.drop()) | |
afterAll(() => db.disconnect()) | |
test('persistable abstract class adds `create', async () => { | |
const name = 'foos' | |
type SerializedFoo = { | |
foo: string | |
} | |
class Foo extends Persistable<SerializedFoo> { | |
static $collectionName = name | |
data: SerializedFoo | |
} | |
const foo = await Foo.create({ | |
foo: 'foo' | |
}) | |
expect(foo._static.collection).toEqual(db.collection(name)) | |
expect(foo.data.foo).toBe('foo') | |
}) | |
test('persistable abstract class adds `fetch`', async () => { | |
const name = 'foos' | |
type SerializedFoo = { | |
foo: string | |
} | |
class Foo extends Persistable<SerializedFoo> { | |
static $collectionName = name | |
data: SerializedFoo | |
} | |
const { _id } = await Foo.create({ | |
foo: 'foo' | |
}) | |
const foo = await Foo.fetch(_id) | |
expect(foo.data.foo).toEqual('foo') | |
}) | |
test('persistable abstract class adds `save', async () => { | |
const name = 'foos' | |
type SerializedFoo = { | |
foo: string | |
} | |
class Foo extends Persistable<SerializedFoo> { | |
static $collectionName = name | |
data: SerializedFoo | |
} | |
const foo = await Foo.create({ | |
foo: 'foo' | |
}) | |
foo.data.foo = 'bar' | |
await foo.save() | |
const bar = await Foo.fetch(foo._id) | |
expect(bar.data.foo).toBe('bar') | |
}) |
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
import * as Bluebird from 'bluebird' | |
import * as MongoDb from 'mongodb' | |
import { collection } from './db' | |
interface IPersistStatic<T, S> { | |
new (data: S, _id: MongoDb.ObjectID): T | |
collection: MongoDb.Collection | |
} | |
abstract class Persistable<S> { | |
abstract data: S | |
static $collectionName: string | |
_id: MongoDb.ObjectID | |
_static: typeof Persistable | |
constructor(data: S, _id: MongoDb.ObjectID) { | |
this.data = data | |
this._id = _id | |
this._static = this.constructor as typeof Persistable | |
} | |
save<S, T extends Persistable<S>>( | |
this: T | |
): Bluebird<void> { | |
return new Bluebird<void>((resolve, reject) => { | |
this._static.collection.updateOne( | |
{ _id: this._id }, | |
this.data, | |
(err, res) => { | |
if (err) { | |
return reject(err) | |
} | |
resolve() | |
} | |
) | |
}) | |
} | |
static _collection: MongoDb.Collection | |
static get collection(): MongoDb.Collection { | |
if (!this._collection) { | |
this._collection = collection(this.$collectionName) | |
} | |
return this._collection | |
} | |
static create<S, T extends Persistable<S>>( | |
this: IPersistStatic<T, S>, | |
data: S | |
): Bluebird<T> { | |
return new Bluebird<T>((resolve, reject) => { | |
this.collection.insertOne(data, (err, { insertedId: _id }) => { | |
if (err) { | |
return reject(err) | |
} | |
resolve(Reflect.construct(this, [data, _id])) | |
}) | |
}) | |
} | |
static fetch<S, T extends Persistable<S>>( | |
this: IPersistStatic<T, S>, | |
_id: MongoDb.ObjectID | |
): Bluebird<T> { | |
return new Bluebird<T>((resolve, reject) => { | |
this.collection.findOne({ _id }, (err, data) => { | |
if (err) { | |
return reject(err) | |
} | |
resolve(Reflect.construct(this, [data, data._id])) | |
}) | |
}) | |
} | |
} | |
export default Persistable |
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
import * as Bluebird from 'bluebird' | |
import { Collection, Db, MongoClient } from 'mongodb' | |
import config from './config' | |
let db: Db | |
let dbPromise: Bluebird<Db> | |
export function connect(): Bluebird<void> { | |
return Bluebird.coroutine(function* () { | |
if (db) { | |
return db | |
} | |
if (!dbPromise) { | |
dbPromise = Bluebird.promisify(MongoClient.connect)(config.MONGO_URL) as Bluebird<Db> | |
} | |
db = yield dbPromise | |
})() | |
} | |
export function disconnect(): Bluebird<void> { | |
return new Bluebird<void>((resolve, reject) => { | |
db.close((err, res) => { | |
if (err) { | |
return reject(err) | |
} | |
resolve(res) | |
}) | |
}) | |
} | |
export function collection(c: string): Collection { | |
return db.collection(c) | |
} | |
export function drop(): Bluebird<void> { | |
return new Bluebird<void>((resolve, reject) => { | |
db.dropDatabase((err, res) => { | |
if (err) { | |
return reject(err) | |
} | |
resolve(res) | |
}) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment