type-mongodb
Advanced tools
Comparing version 0.0.1-beta7 to 0.0.1-beta8
@@ -1,45 +0,34 @@ | ||
import { DocumentClass, Newable } from '../types'; | ||
import { DocumentClass, Newable } from '..'; | ||
import { AbstractDocumentMetadata } from '../metadata/AbstractDocumentMetadata'; | ||
export declare class DocumentTransformer { | ||
/** | ||
* Creates a model from model properties. | ||
*/ | ||
static init<T, D extends Newable = DocumentClass>(meta: AbstractDocumentMetadata<T, D>, props: Partial<T> | { | ||
import { OptionalId } from '../types'; | ||
export declare type DocumentTransformerCompiledFunction = (target: any, source: any, parent?: any) => any; | ||
export declare class DocumentTransformer<T = any, D extends Newable = DocumentClass> { | ||
private meta; | ||
private isCompiled; | ||
private compiledToDB; | ||
private compiledFromDB; | ||
private compiledMerge; | ||
private constructor(); | ||
static readonly transformers: Map<any, DocumentTransformer<any, Newable<any>>>; | ||
static create<T = any, D extends Newable = DocumentClass>(meta: AbstractDocumentMetadata<T, D>): DocumentTransformer<T, D>; | ||
static compile(): void; | ||
compile(): void; | ||
init(props: OptionalId<Partial<T>> | { | ||
[key: string]: any; | ||
}): T; | ||
/** | ||
* Merges props into the given model | ||
*/ | ||
static merge<T, D extends Newable = DocumentClass>(meta: AbstractDocumentMetadata<T, D>, model: T, props: Partial<T> | { | ||
}, parent?: any): T; | ||
merge(model: T, props: Partial<T> | { | ||
[key: string]: any; | ||
}): T; | ||
/** | ||
* Maps model fields to a mongodb document. | ||
*/ | ||
static toDB<T, D extends Newable = DocumentClass>(meta: AbstractDocumentMetadata<T, D>, model: Partial<T> | { | ||
}, parent?: any): T; | ||
fromDB(doc: Partial<T> | { | ||
[key: string]: any; | ||
}, parent?: any): T; | ||
toDB(model: Partial<T> | { | ||
[key: string]: any; | ||
}): T & { | ||
[key: string]: any; | ||
}; | ||
/** | ||
* Maps mongodb document(s) to a model. | ||
*/ | ||
static fromDB<T, D extends Newable = DocumentClass>(meta: AbstractDocumentMetadata<T, D>, doc: Partial<T> | { | ||
[key: string]: any; | ||
}): T; | ||
protected static getInstance<T>(meta: AbstractDocumentMetadata<T>, prepare?: boolean): T; | ||
protected static createParentMapper<T>(map: (meta: AbstractDocumentMetadata<T>, value: any) => T): (meta: AbstractDocumentMetadata<T>, value: any, parent: any) => T; | ||
/** | ||
* Iterates over the fields for mapping between different types | ||
*/ | ||
protected static mapDataInto<T>(opts: { | ||
meta: AbstractDocumentMetadata<T>; | ||
into: any; | ||
intoField: 'fieldName' | 'propertyName'; | ||
data: any; | ||
dataField: 'fieldName' | 'propertyName'; | ||
map: (meta: AbstractDocumentMetadata<T>, value: any, parent: any) => any; | ||
}): T; | ||
protected static prepare<T>(meta: AbstractDocumentMetadata<T>, object: any): T; | ||
private createCompiler; | ||
private prepare; | ||
private assertIsCompiled; | ||
} | ||
//# sourceMappingURL=DocumentTransformer.d.ts.map |
"use strict"; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DocumentTransformer = void 0; | ||
// simple helper to create unique variable names | ||
let variableCount = 0; | ||
function reserveVariable(name) { | ||
return `${name}_${++variableCount}`; | ||
} | ||
class DocumentTransformer { | ||
/** | ||
* Creates a model from model properties. | ||
*/ | ||
static init(meta, props) { | ||
return this.mapDataInto({ | ||
meta, | ||
into: this.getInstance(meta), | ||
intoField: 'propertyName', | ||
data: props, | ||
dataField: 'propertyName', | ||
map: this.createParentMapper(this.init.bind(this)), | ||
}); | ||
constructor(meta) { | ||
this.meta = meta; | ||
this.isCompiled = false; | ||
} | ||
/** | ||
* Merges props into the given model | ||
*/ | ||
static merge(meta, model, props) { | ||
return this.mapDataInto({ | ||
meta, | ||
into: model, | ||
intoField: 'propertyName', | ||
data: props, | ||
dataField: 'propertyName', | ||
map: this.createParentMapper(this.init.bind(this)), | ||
}); | ||
static create(meta) { | ||
// create transformer if it does not exist | ||
let transformer = DocumentTransformer.transformers.get(meta.DocumentClass); | ||
if (!transformer) { | ||
transformer = new DocumentTransformer(meta); | ||
} | ||
DocumentTransformer.transformers.set(meta.DocumentClass, transformer); | ||
return transformer; | ||
} | ||
/** | ||
* Maps model fields to a mongodb document. | ||
*/ | ||
static toDB(meta, model) { | ||
return this.mapDataInto({ | ||
meta, | ||
into: {}, | ||
intoField: 'fieldName', | ||
data: this.prepare(meta, model), | ||
dataField: 'propertyName', | ||
map: this.toDB.bind(this), | ||
// compiles all of the transformers | ||
static compile() { | ||
DocumentTransformer.transformers.forEach((transformer) => { | ||
transformer.compile(); | ||
}); | ||
} | ||
/** | ||
* Maps mongodb document(s) to a model. | ||
*/ | ||
static fromDB(meta, doc) { | ||
const instance = this.getInstance(meta, false); | ||
const model = this.mapDataInto({ | ||
meta, | ||
into: instance, | ||
intoField: 'propertyName', | ||
data: doc, | ||
dataField: 'fieldName', | ||
map: this.createParentMapper(this.fromDB.bind(this)), | ||
}); | ||
return model; | ||
compile() { | ||
if (this.isCompiled) { | ||
return; | ||
} | ||
this.compiledToDB = this.createCompiler(false, true); | ||
this.compiledFromDB = this.createCompiler(true, false); | ||
this.compiledMerge = this.createCompiler(false, false); | ||
this.isCompiled = true; | ||
} | ||
// ------------------------------------------------------------------------- | ||
// Protected Methods | ||
// ------------------------------------------------------------------------- | ||
static getInstance(meta, prepare = true) { | ||
const instance = new meta.DocumentClass(); | ||
return prepare ? this.prepare(meta, instance) : instance; | ||
init(props, parent) { | ||
this.assertIsCompiled(); | ||
return this.compiledMerge(this.prepare(new this.meta.DocumentClass()), props, parent); | ||
} | ||
static createParentMapper(map) { | ||
return (m, v, parent) => { | ||
const model = map.bind(this)(m, v); | ||
if (m.parent) { | ||
model[m.parent.propertyName] = parent; | ||
merge(model, props, parent) { | ||
this.assertIsCompiled(); | ||
return this.compiledMerge(this.prepare(model), props, parent); | ||
} | ||
fromDB(doc, parent) { | ||
this.assertIsCompiled(); | ||
return this.compiledFromDB(new this.meta.DocumentClass(), doc, parent); | ||
} | ||
toDB(model) { | ||
this.assertIsCompiled(); | ||
return this.compiledToDB({}, this.prepare(model)); | ||
} | ||
createCompiler(isFromDB, isToDB) { | ||
const context = new Map(); | ||
const has = (accessor) => { | ||
return `(source && "${accessor}" in source)`; | ||
}; | ||
const getComparator = (fieldMetadata, accessor, setter) => { | ||
const { embeddedMetadata, fieldName, isEmbeddedArray, isEmbedded } = fieldMetadata; | ||
// simple getter/setter | ||
if (!isEmbedded) { | ||
return ` | ||
if (${has(accessor)}) { | ||
target["${setter}"] = source["${accessor}"]; | ||
} | ||
`; | ||
} | ||
return model; | ||
const embeddedTransformer = DocumentTransformer.create(embeddedMetadata); | ||
const transformerFnVar = reserveVariable(`${fieldName}_transformer`); | ||
const transformerFn = isToDB | ||
? embeddedTransformer.toDB | ||
: embeddedTransformer.fromDB; | ||
context.set(transformerFnVar, transformerFn.bind(embeddedTransformer)); | ||
if (isEmbeddedArray) { | ||
return ` | ||
if (${has(accessor)} && Array.isArray(source["${accessor}"])) { | ||
target["${setter}"] = source["${accessor}"].map(v => ${transformerFnVar}(v, target)); | ||
} | ||
`; | ||
} | ||
return ` | ||
if (${has(accessor)}) { | ||
target["${setter}"] = ${transformerFnVar}(source["${accessor}"], target); | ||
} | ||
`; | ||
}; | ||
} | ||
/** | ||
* Iterates over the fields for mapping between different types | ||
*/ | ||
static mapDataInto(opts) { | ||
const { meta, into, intoField, data, dataField, map } = opts; | ||
meta.fields.forEach((_a) => { | ||
var { isEmbedded, isEmbeddedArray, embeddedMetadata } = _a, fieldMeta = __rest(_a, ["isEmbedded", "isEmbeddedArray", "embeddedMetadata"]); | ||
const dataFieldName = fieldMeta[dataField]; | ||
const intoFieldName = fieldMeta[intoField]; | ||
if (typeof data !== 'undefined' && | ||
typeof data[dataFieldName] !== 'undefined') { | ||
if (!isEmbedded) { | ||
into[intoFieldName] = data[dataFieldName]; | ||
} | ||
else if (isEmbeddedArray) { | ||
into[intoFieldName] = (data[dataFieldName] || []).map((value) => value ? map(embeddedMetadata, value, into) : null); | ||
} | ||
else { | ||
into[intoFieldName] = data[dataFieldName] | ||
? map(embeddedMetadata, data[dataFieldName], into) | ||
: null; | ||
} | ||
const props = []; | ||
for (const fieldMetadata of this.meta.fields.values()) { | ||
const { fieldName, propertyName } = fieldMetadata; | ||
const accessor = isFromDB ? fieldName : propertyName; | ||
const setter = isToDB ? fieldName : propertyName; | ||
props.push(getComparator(fieldMetadata, accessor, setter)); | ||
} | ||
const parentMapper = () => { | ||
if (isToDB || !this.meta.parent) { | ||
return ''; | ||
} | ||
}); | ||
return into; | ||
return ` | ||
target["${this.meta.parent.propertyName}"] = parent; | ||
`; | ||
}; | ||
const functionCode = ` | ||
return function(target, source, parent) { | ||
${props.join('\n')} | ||
${parentMapper()} | ||
return target; | ||
} | ||
`; | ||
const compiled = new Function(...context.keys(), functionCode); | ||
return compiled(...context.values()); | ||
} | ||
static prepare(meta, object) { | ||
if (meta.hasId()) { | ||
object._id = meta.id(object._id); | ||
prepare(object) { | ||
if (this.meta.hasId()) { | ||
object._id = this.meta.id(object._id); | ||
} | ||
return object; | ||
} | ||
assertIsCompiled() { | ||
if (!this.isCompiled) { | ||
throw new Error('DocumentTransformers are not compiled'); | ||
} | ||
} | ||
} | ||
exports.DocumentTransformer = DocumentTransformer; | ||
DocumentTransformer.transformers = new Map(); | ||
//# sourceMappingURL=DocumentTransformer.js.map |
@@ -31,3 +31,3 @@ import { MongoClient, SessionOptions } from 'mongodb'; | ||
readonly container: ContainerLike; | ||
constructor(opts: DocumentManagerOptions); | ||
private constructor(); | ||
buildMetadata(): Promise<void>; | ||
@@ -34,0 +34,0 @@ buildSubscribers(): void; |
@@ -17,2 +17,3 @@ "use strict"; | ||
const Session_1 = require("./transaction/Session"); | ||
const DocumentTransformer_1 = require("./document/DocumentTransformer"); | ||
const defaultContainer = { | ||
@@ -151,2 +152,3 @@ get: (Service) => new Service() | ||
dm.buildSubscribers(); | ||
DocumentTransformer_1.DocumentTransformer.compile(); | ||
return dm; | ||
@@ -153,0 +155,0 @@ }); |
@@ -41,8 +41,8 @@ "use strict"; | ||
this.documentsWithSubscribers.clear(); | ||
const documents = Array.from(dm.metadataFactory.loadedDocumentMetadata.values()).map(meta => meta.DocumentClass); | ||
this.subscribers.forEach(subscriber => { | ||
const documents = Array.from(dm.metadataFactory.loadedDocumentMetadata.values()).map((meta) => meta.DocumentClass); | ||
this.subscribers.forEach((subscriber) => { | ||
const subscribedDocuments = typeof subscriber.getSubscribedDocuments === 'function' | ||
? subscriber.getSubscribedDocuments(dm) | ||
: null; | ||
documents.forEach(DocumentClass => { | ||
documents.forEach((DocumentClass) => { | ||
if (!subscribedDocuments) { | ||
@@ -94,3 +94,3 @@ this.attachSubscriberToDocument(DocumentClass, subscriber); | ||
const subscribers = this.documentsWithSubscribers.get(DocumentClass); | ||
Object.keys(interfaces_1.Events).forEach(event => { | ||
Object.keys(interfaces_1.Events).forEach((event) => { | ||
const fn = interfaces_1.Events[event]; | ||
@@ -97,0 +97,0 @@ if (typeof subscriber[fn] === 'function') { |
import { ObjectId } from 'mongodb'; | ||
import { Newable, OptionalId } from '../types'; | ||
import { FieldMetadata } from './FieldMetadata'; | ||
import { DocumentTransformer } from '../document/DocumentTransformer'; | ||
import { ParentDefinition } from './definitions'; | ||
@@ -14,2 +15,3 @@ export declare type FieldsMetadata = Map<string, FieldMetadata>; | ||
readonly fields: FieldsMetadata; | ||
readonly transformer: DocumentTransformer; | ||
readonly parent?: ParentDefinition; | ||
@@ -16,0 +18,0 @@ constructor(DocumentClass: D, fields: FieldsMetadata, parent?: ParentDefinition); |
@@ -16,2 +16,3 @@ "use strict"; | ||
this.parent = parent; | ||
this.transformer = DocumentTransformer_1.DocumentTransformer.create(this); | ||
} | ||
@@ -46,3 +47,3 @@ // ------------------------------------------------------------------------- | ||
toDB(model) { | ||
return DocumentTransformer_1.DocumentTransformer.toDB(this, model); | ||
return this.transformer.toDB(model); | ||
} | ||
@@ -53,3 +54,3 @@ /** | ||
fromDB(doc) { | ||
return DocumentTransformer_1.DocumentTransformer.fromDB(this, doc); | ||
return this.transformer.fromDB(doc); | ||
} | ||
@@ -60,3 +61,3 @@ /** | ||
init(props) { | ||
return DocumentTransformer_1.DocumentTransformer.init(this, props); | ||
return this.transformer.merge(new this.DocumentClass(), props); | ||
} | ||
@@ -67,3 +68,3 @@ /** | ||
merge(model, props) { | ||
return DocumentTransformer_1.DocumentTransformer.merge(this, model, props); | ||
return this.transformer.merge(model, props); | ||
} | ||
@@ -70,0 +71,0 @@ } |
@@ -88,3 +88,3 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield Promise.all(this.opts.documents.map(DocumentClass => { | ||
yield Promise.all(this.opts.documents.map((DocumentClass) => { | ||
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { | ||
@@ -140,3 +140,3 @@ try { | ||
if (definitionStorage_1.definitionStorage.fields.has(target)) { | ||
definitionStorage_1.definitionStorage.fields.get(target).forEach(prop => { | ||
definitionStorage_1.definitionStorage.fields.get(target).forEach((prop) => { | ||
if (!prop.isEmbedded) { | ||
@@ -143,0 +143,0 @@ fields.set(prop.fieldName, new FieldMetadata_1.FieldMetadata(Object.assign(Object.assign({}, prop), { isEmbeddedArray: false }))); |
@@ -81,3 +81,3 @@ "use strict"; | ||
return this.find({ | ||
_id: { $in: ids.map((id) => this.id(id)) }, | ||
_id: { $in: ids.map((id) => this.id(id)) } | ||
}, opts); | ||
@@ -132,3 +132,3 @@ } | ||
meta: this.metadata, | ||
model: model, | ||
model: model | ||
}, () => this.collection.insertOne(doc, opts)); | ||
@@ -148,7 +148,7 @@ }); | ||
meta: this.metadata, | ||
model: model, | ||
model: model | ||
})); | ||
afterInsertEvents.push(this.manager.eventManager.dispatch(events_1.Events.AfterInsert, { | ||
meta: this.metadata, | ||
model: model, | ||
model: model | ||
})); | ||
@@ -167,3 +167,3 @@ }); | ||
filter, | ||
update, | ||
update | ||
}, () => __awaiter(this, void 0, void 0, function* () { | ||
@@ -213,3 +213,3 @@ return this.findOneAnd('Update', filter, update, Object.assign({ returnOriginal: false }, opts)); | ||
meta: this.metadata, | ||
filter, | ||
filter | ||
}, () => __awaiter(this, void 0, void 0, function* () { return this.findOneAnd('Delete', filter, opts); })); | ||
@@ -238,3 +238,3 @@ }); | ||
filter, | ||
update, | ||
update | ||
}, () => this.collection.updateOne(filter, update, opts)); | ||
@@ -253,3 +253,3 @@ }); | ||
filter, | ||
update, | ||
update | ||
}, () => this.collection.updateMany(filter, update, opts)); | ||
@@ -277,3 +277,3 @@ }); | ||
meta: this.metadata, | ||
filter, | ||
filter | ||
}, () => __awaiter(this, void 0, void 0, function* () { | ||
@@ -294,3 +294,3 @@ const result = yield this.collection.deleteOne(filter, opts); | ||
meta: this.metadata, | ||
filter, | ||
filter | ||
}, () => this.collection.deleteMany(filter, opts)); | ||
@@ -297,0 +297,0 @@ }); |
@@ -11,3 +11,3 @@ import { WithId } from 'mongodb'; | ||
*/ | ||
export { Db, OptionalId, WithId, Collection, CollectionInsertManyOptions, InsertWriteOpResult, CommonOptions, CollectionInsertOneOptions, InsertOneWriteOpResult, FindOneAndDeleteOption, FindOneAndUpdateOption, FindOneAndReplaceOption, UpdateWriteOpResult, ReplaceWriteOpResult, DeleteWriteOpResultObject, FilterQuery, UpdateQuery, UpdateManyOptions, UpdateOneOptions, ReplaceOneOptions, } from 'mongodb'; | ||
export { Db, OptionalId, WithId, Collection, CollectionInsertManyOptions, InsertWriteOpResult, CommonOptions, CollectionInsertOneOptions, InsertOneWriteOpResult, FindOneAndDeleteOption, FindOneAndUpdateOption, FindOneAndReplaceOption, UpdateWriteOpResult, ReplaceWriteOpResult, DeleteWriteOpResultObject, FilterQuery, UpdateQuery, UpdateManyOptions, UpdateOneOptions, ReplaceOneOptions } from 'mongodb'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -15,3 +15,3 @@ "use strict"; | ||
throw new Error(`No need to set field type on for: ObjectId, ${exports.builtins | ||
.map(type => type.name) | ||
.map((type) => type.name) | ||
.join(', ')}`); | ||
@@ -18,0 +18,0 @@ } |
@@ -17,4 +17,4 @@ "use strict"; | ||
yield Promise.all(dm | ||
.filterMetadata(meta => !!meta.collection) | ||
.map(meta => meta.collection.deleteMany({}))); | ||
.filterMetadata((meta) => !!meta.collection) | ||
.map((meta) => meta.collection.deleteMany({}))); | ||
}); | ||
@@ -21,0 +21,0 @@ } |
{ | ||
"name": "type-mongodb", | ||
"version": "0.0.1-beta7", | ||
"version": "0.0.1-beta8", | ||
"description": "A simple decorator based MongoDB ODM.", | ||
@@ -26,10 +26,9 @@ "keywords": [], | ||
}, | ||
"dependencies": { | ||
"mongodb": "^3.5.9" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "^26.0.3", | ||
"@types/mongodb": "3.5.25", | ||
"benchmark": "^2.1.4", | ||
"husky": "^4.2.5", | ||
"jest": "^26.1.0", | ||
"mongodb": "3.x.x", | ||
"mongodb-runner": "^4.7.2", | ||
@@ -43,6 +42,8 @@ "prettier": "^2.0.5", | ||
"peerDependencies": { | ||
"mongodb": "3.x.x", | ||
"reflect-metadata": "^0.1.13" | ||
}, | ||
"prettier": { | ||
"singleQuote": true | ||
"singleQuote": true, | ||
"trailingComma": "none" | ||
}, | ||
@@ -49,0 +50,0 @@ "husky": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
180350
2303
12
- Removedmongodb@^3.5.9