vulcain-corejs
Version:
Vulcain micro-service framework
310 lines (308 loc) • 13.6 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
const annotations_1 = require("./../../di/annotations");
const requestContext_1 = require("./../../servers/requestContext");
const mongodb_1 = require("mongodb");
const annotations_2 = require("../../di/annotations");
const applicationRequestError_1 = require("../../errors/applicationRequestError");
const system_1 = require("../../configurations/globals/system");
/**
* Default mongo provider
*/
let MongoProvider = class MongoProvider {
constructor(_logger, ctx, uri, options) {
this._logger = _logger;
this.ctx = ctx;
this.options = options;
this.options = this.options || {};
// Try to fix topology was destroy error
this.options.socketOptions = this.options.socketOptions || {
noDelay: true,
connectTimeoutMS: 0,
socketTimeoutMS: 0
};
this.state = { uri: uri };
}
get address() {
return this.state.uri;
}
initializeWithSchemaAsync(tenant, schema) {
if (!schema)
throw new Error("schema is not set for provider.");
if (!tenant)
throw new Error("tenant is required");
this.state.uri = this.state.uri + "/" + tenant;
this.state.keyPropertyName = schema.getIdProperty() || "_id";
this.ctx.logVerbose(`MONGODB: Creating provider ${this.state.uri} for schema ${schema.name}`);
let keys;
for (let p in schema.description.properties) {
if (!schema.description.properties.hasOwnProperty(p))
continue;
let prop = schema.description.properties[p];
if (prop.unique) {
if (!keys)
keys = {};
keys[p] = prop.unique === true ? 1 : prop.unique;
}
}
const state = this.state;
const options = this.options;
return new Promise((resolve, reject) => {
// Don't use this here to avoid memory leaks
// Open connexion
mongodb_1.MongoClient.connect(state.uri, options, (err, db) => {
if (err) {
reject(err);
system_1.System.log.error(null, err, `MONGODB: Error when opening database ${state.uri} for schema ${schema.name}`);
return;
}
state._mongo = db;
state.dispose = () => {
db.close();
};
if (keys) {
let indexName = schema.description.storageName + "_uniqueIndex";
db.createIndex(schema.description.storageName, keys, { w: 1, background: true, name: indexName, unique: true }, (err) => {
if (err) {
system_1.System.log.error(null, err, `MONGODB: Error when creating index for ${state.uri} for schema ${schema.name}`);
}
else {
system_1.System.log.info(null, `MONGODB: Unique index created for ${state.uri} for schema ${schema.name}`);
}
});
}
resolve(state);
});
});
}
/**
* Return a list of entities
* @param options
* @returns {Promise}
*/
getAllAsync(schema, options) {
let page = options.page || 0;
let maxByPage = options.maxByPage || 100;
let query = options.query ? options.query.filter || options.query : {};
this.ctx.logVerbose(`MONGODB: Get all on ${this.state.uri} for schema ${schema.name} with query: ${JSON.stringify(query)}`);
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let db = this.state._mongo;
let cursor = db.collection(schema.description.storageName).find(query)
.skip(page * maxByPage)
.limit(maxByPage);
cursor.toArray((err, res) => {
if (err) {
this.ctx.logError(err, `Error when getting all entities for schema: ${schema.name}`);
reject(err);
}
else
resolve(res);
});
}
catch (err) {
this.ctx.logError(err, `Error when getting all entities for schema: ${schema.name}`);
reject(err);
}
}));
}
findOneAsync(schema, query) {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let db = this.state._mongo;
db.collection(schema.description.storageName).findOne(query, (err, res) => {
if (err) {
this.ctx.logError(err, `Error when find one entity for schema: ${schema.name}`);
reject(err);
}
else
resolve(res);
});
}
catch (err) {
this.ctx.logError(err, `Error when find one entity for schema: ${schema.name}`);
reject(err);
}
}));
}
/**
* Read an entity
* @param name
* @returns {Promise}
*/
getAsync(schema, name) {
this.ctx.logVerbose(`MONGODB: Get on ${this.state.uri} for schema ${schema.name} with id: ${name}`);
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let filter = {};
filter[this.state.keyPropertyName || "_id"] = name;
let db = this.state._mongo;
db.collection(schema.description.storageName).findOne(filter, (err, res) => {
if (err) {
this.ctx.logError(err, `Error when getting entity ${name}, schema: ${schema.name}`);
reject(this.normalizeErrors(name, err));
}
else
resolve(res);
});
}
catch (err) {
this.ctx.logError(err, `Error when getting entity ${name}, schema: ${schema.name}`);
reject(err);
}
}));
}
/**
* Delete an entity
* @param id
* @returns {Promise}
*/
deleteAsync(schema, old) {
if (!old)
throw new Error("Argument is required");
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
let id;
if (typeof old === "string")
id = old;
else
id = old[this.state.keyPropertyName];
if (!id)
throw new Error("Mongo : Error on delete. Id must not be null");
try {
let filter = {};
filter[this.state.keyPropertyName || "_id"] = id;
this.ctx.logVerbose(`MONGODB: Deleting on ${this.state.uri} for schema ${schema.name} with filter: ${JSON.stringify(filter)}`);
let db = this.state._mongo;
db.collection(schema.description.storageName).remove(filter, (err, res) => {
if (err) {
this.ctx.logError(err, `Error when deleting entity ${id}, schema: ${schema.name}`);
reject(this.normalizeErrors(id, err));
}
else
resolve();
});
}
catch (err) {
this.ctx.logError(err, `Error when deleting entity ${id}, schema: ${schema.name}`);
reject(err);
}
}));
}
normalizeErrors(id, err) {
if (!err || !err.errors)
return err;
let error = new applicationRequestError_1.ApplicationRequestError("Mongo error", []);
if (err.errors) {
for (let e in err.errors) {
if (!err.errors.hasOwnProperty(e))
continue;
let error = err.errors[e];
error.errors.push({ message: error.message, property: error.path, id: id });
}
}
return error;
}
/**
* Persist an entity
* @param entity
* @returns {Promise}
*/
createAsync(schema, entity) {
if (!entity)
throw new Error("Entity is required");
entity._created = new Date().toUTCString();
this.ctx.logVerbose(`MONGODB: Create entity on ${this.state.uri} for schema ${schema.name} with entity: ${JSON.stringify(entity)}`);
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let db = this.state._mongo;
db.collection(schema.description.storageName).insertOne(entity, (err) => {
if (err) {
let id = entity[this.state.keyPropertyName];
this.ctx.logError(err, `Error when creating entity ${id}, schema: ${schema.name}`);
reject(this.normalizeErrors(entity[this.state.keyPropertyName], err));
}
else {
resolve(entity);
}
});
}
catch (err) {
reject(err);
}
}));
}
/**
* Update an entity
* @param entity
* @param old
* @returns {Promise<T>}
*/
updateAsync(schema, entity, old) {
if (!entity)
throw new Error("Entity is required");
this.ctx.logVerbose(`MONGODB: Update entity on ${this.state.uri} for schema ${schema.name} with entity: ${JSON.stringify(entity)}`);
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let id = (old || entity)[this.state.keyPropertyName];
let filter = {};
filter[this.state.keyPropertyName || "_id"] = id;
let db = this.state._mongo;
let collection = db.collection(schema.description.storageName);
collection.findOne(filter, (err, initial) => {
if (err) {
this.ctx.logError(err, `Error when updating entity ${id}, schema: ${schema.name}`);
reject(new Error(`Error when updating entity ${id}, schema: ${schema.name}, error: ${err.message}`));
return;
}
if (!initial) {
err = new Error(`Can not update unknow entity ${id}, schema: ${schema.name}`);
this.ctx.logError(err, `Error when updating entity ${id}, schema: ${schema.name}`);
reject();
return;
}
let _id = initial._id;
initial = schema.deepAssign(initial, entity);
initial._updated = new Date().toUTCString();
initial._id = _id;
collection.updateOne(filter, initial, err => {
if (err) {
this.ctx.logError(err, `Error when updating entity ${id}, schema: ${schema.name}`);
reject(this.normalizeErrors(id, err));
}
else
resolve(initial);
});
});
}
catch (err) {
reject(err);
}
}));
}
};
MongoProvider = __decorate([
__param(0, annotations_2.Inject(annotations_1.DefaultServiceNames.Logger)),
__param(1, annotations_2.Inject(annotations_1.DefaultServiceNames.RequestContext, true)),
__metadata("design:paramtypes", [Object, requestContext_1.RequestContext, String, Object])
], MongoProvider);
exports.MongoProvider = MongoProvider;
//# sourceMappingURL=provider.js.map