breeze-sequelize
Advanced tools
Comparing version 0.5.2 to 0.5.3
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
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) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const sequelize_1 = require("sequelize"); | ||
let utils = require('./utils.js'); | ||
let log = utils.log; | ||
exports.connect = connect; | ||
exports.createDb = createDb; | ||
const utils_1 = require("./utils"); | ||
/** Connect to existing database. | ||
* @returns Promise<"success"> or throws an error */ | ||
function connect(dbConfig, sequelizeOptions) { | ||
let sequelize = new sequelize_1.Sequelize(dbConfig.dbName, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
let statement = 'SELECT 1'; | ||
return sequelize.query(statement, { type: sequelize_1.QueryTypes.RAW }).then(function (results) { | ||
log("Connected to database: " + dbConfig.dbName); | ||
return "success"; | ||
}).error(function (err) { | ||
log("Database error: " + dbConfig.dbName + " error: " + err.message); | ||
throw err; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let sequelize = new sequelize_1.Sequelize(dbConfig.dbName, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
let statement = 'SELECT 1'; | ||
try { | ||
const results = yield sequelize.query(statement, { type: sequelize_1.QueryTypes.RAW }); | ||
utils_1.log("Connected to database: " + dbConfig.dbName); | ||
return "success"; | ||
} | ||
catch (err) { | ||
utils_1.log("Database error: " + dbConfig.dbName + " error: " + err.message); | ||
throw err; | ||
} | ||
}); | ||
} | ||
exports.connect = connect; | ||
; | ||
/** Create new database. | ||
* @returns Promise<void> or throws an error */ | ||
function createDb(dbConfig, sequelizeOptions) { | ||
let sequelize = new sequelize_1.Sequelize(null, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
let statement = 'CREATE DATABASE ' + dbConfig.dbName; | ||
return sequelize.query(statement, { type: sequelize_1.QueryTypes.RAW }).then(() => { | ||
log("Database created: " + dbConfig.dbName); | ||
}).error(err => { | ||
if (err.message && err.message.indexOf("ER_DB_CREATE_EXISTS") >= 0) { | ||
log("Database already exists: " + dbConfig.dbName); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let sequelize = new sequelize_1.Sequelize(null, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
let statement = 'CREATE DATABASE ' + dbConfig.dbName; | ||
try { | ||
yield sequelize.query(statement, { type: sequelize_1.QueryTypes.RAW }); | ||
utils_1.log("Database created: " + dbConfig.dbName); | ||
} | ||
else { | ||
log("Database creation error: " + dbConfig.dbName + " error: " + err.message); | ||
throw err; | ||
catch (err) { | ||
if (err.message && err.message.indexOf("ER_DB_CREATE_EXISTS") >= 0) { | ||
utils_1.log("Database already exists: " + dbConfig.dbName); | ||
} | ||
else { | ||
utils_1.log("Database creation error: " + dbConfig.dbName + " error: " + err.message); | ||
throw err; | ||
} | ||
} | ||
@@ -41,19 +54,2 @@ }); | ||
exports.createDb = createDb; | ||
; | ||
// old version using node 'next' semantics. | ||
// next => function(err, connection); | ||
//function createDb(dbConfig, next ) { | ||
// connect(dbConfig, function(err, connection) { | ||
// if (err) return next(err); | ||
// | ||
// connection.query('CREATE DATABASE ' + dbConfig.dbName, function(err, results) { | ||
// if (err && err.code != "ER_DB_CREATE_EXISTS") { | ||
// log("Database creation error: " + err.message); | ||
// next(err); | ||
// } | ||
// log("database created OR already exists."); | ||
// next(null, connection); | ||
// }); | ||
// }); | ||
//} | ||
//# sourceMappingURL=dbUtils.js.map |
@@ -12,6 +12,4 @@ "use strict"; | ||
exports.SaveMap = SaveMap_1.SaveMap; | ||
const utils = require("./utils"); | ||
exports.utils = utils; | ||
const dbUtils = require("./dbUtils"); | ||
exports.dbUtils = dbUtils; | ||
const dbUtils_1 = require("./dbUtils"); | ||
exports.connect = dbUtils_1.connect; | ||
const breeze_client_1 = require("breeze-client"); | ||
@@ -18,0 +16,0 @@ exports.breeze = breeze_client_1.breeze; |
@@ -8,3 +8,2 @@ "use strict"; | ||
let log = utils.log; | ||
; | ||
// TODO: still need to handle inherited entity types - TPT | ||
@@ -116,3 +115,3 @@ /** Maps Breeze metadata to Sequelize Models */ | ||
attributes.type = sqModel; | ||
if (dataProperty.dataType == breeze_client_1.breeze.DataType.String && dataProperty.maxLength) { | ||
if (dataProperty.dataType === breeze_client_1.breeze.DataType.String && dataProperty.maxLength) { | ||
attributes.type = sequelize_1.DataTypes.STRING(dataProperty.maxLength); | ||
@@ -125,5 +124,5 @@ } | ||
attributes.primaryKey = true; | ||
if (dataProperty.parentType.autoGeneratedKeyType == breeze_client_1.breeze.AutoGeneratedKeyType.Identity) { | ||
if (dataProperty.parentType.autoGeneratedKeyType === breeze_client_1.breeze.AutoGeneratedKeyType.Identity) { | ||
let dt = attributes.type; | ||
if (dt.key == "INTEGER" || dt.key == "BIGINT") { | ||
if (dt.key === "INTEGER" || dt.key === "BIGINT") { | ||
attributes.autoIncrement = true; | ||
@@ -130,0 +129,0 @@ } |
{ | ||
"name": "breeze-sequelize", | ||
"version": "0.5.2", | ||
"version": "0.5.3", | ||
"description": "Breeze Sequelize server implementation", | ||
@@ -25,4 +25,3 @@ "keywords": [ | ||
"peerDependencies": { | ||
"bluebird": "^3.7.2", | ||
"breeze-client": ">=2.0.4", | ||
"breeze-client": ">=2.0.7", | ||
"lodash": "^4.17.15", | ||
@@ -32,14 +31,13 @@ "sequelize": "^5.21.3" | ||
"devDependencies": { | ||
"@types/bluebird": "^3.5.29", | ||
"@types/lodash": "^4.14.137", | ||
"@types/node": "^12.12.26", | ||
"@types/validator": "^12.0.1", | ||
"breeze-client": "^2.0.7", | ||
"chai": "^4.2.0", | ||
"lodash": "^4.17.15", | ||
"mocha": "^6.2.0", | ||
"rimraf": "^3.0.1", | ||
"typescript": "^3.7.5", | ||
"bluebird": "^3.7.2", | ||
"breeze-client": ">=2.0.4", | ||
"lodash": "^4.17.15", | ||
"sequelize": "^5.21.3" | ||
"sequelize": "^5.21.3", | ||
"tslint": "^6.0.0", | ||
"typescript": "^3.7.5" | ||
}, | ||
@@ -51,3 +49,3 @@ "scripts": { | ||
"build": "tsc && npm pack && npm run install-to-demo", | ||
"install-to-demo": "cd ../test/BreezeExpressDemo && npm install ../../src/breeze-sequelize-0.5.2.tgz", | ||
"install-to-demo": "cd ../test/BreezeExpressDemo && npm install ../../src/breeze-sequelize-0.5.3.tgz", | ||
"clean": "rimraf *.js && rimraf *.map && rimraf types" | ||
@@ -54,0 +52,0 @@ }, |
@@ -43,5 +43,3 @@ "use strict"; | ||
const entityType = entityInfo.entityType; | ||
const keyValues = entityType.keyProperties.map(kp => { | ||
return entityInfo.entity[kp.nameOnServer]; | ||
}); | ||
const keyValues = entityType.keyProperties.map(kp => entityInfo.entity[kp.nameOnServer]); | ||
this.entityErrors.push({ | ||
@@ -48,0 +46,0 @@ entityTypeName: entityType.name, |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
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) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -31,8 +40,12 @@ const sequelize_1 = require("sequelize"); | ||
authenticate() { | ||
// check database connection | ||
return this.sequelize.authenticate().then(() => { | ||
log('Connection has been established successfully.'); | ||
}).error(err => { | ||
log('Unable to connect to the database:', err); | ||
throw err; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// check database connection | ||
try { | ||
yield this.sequelize.authenticate(); | ||
log('Connection has been established successfully.'); | ||
} | ||
catch (err) { | ||
log('Unable to connect to the database:', err); | ||
throw err; | ||
} | ||
}); | ||
@@ -54,20 +67,22 @@ } | ||
sync(shouldCreateDb, sequelizeOpts) { | ||
if (shouldCreateDb) { | ||
return this.createDb().then(() => { | ||
return this.syncCore(this.sequelize, sequelizeOpts); | ||
}); | ||
} | ||
else { | ||
return this.syncCore(this.sequelize, sequelizeOpts); | ||
} | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (shouldCreateDb) { | ||
yield this.createDb(); | ||
} | ||
return yield this.syncCore(this.sequelize, sequelizeOpts); | ||
}); | ||
} | ||
syncCore(sequelize, sequelizeOpts) { | ||
let defaultOptions = { force: true }; | ||
sequelizeOpts = _.extend(defaultOptions, sequelizeOpts || {}); | ||
return sequelize.sync(sequelizeOpts).then(() => { | ||
log("schema created"); | ||
return sequelize; | ||
}).catch(err => { | ||
console.log("schema creation failed"); | ||
throw err; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let defaultOptions = { force: true }; | ||
sequelizeOpts = _.extend(defaultOptions, sequelizeOpts || {}); | ||
try { | ||
return yield sequelize.sync(sequelizeOpts); | ||
log("schema created"); | ||
return sequelize; | ||
} | ||
catch (err) { | ||
console.log("schema creation failed"); | ||
throw err; | ||
} | ||
}); | ||
@@ -74,0 +89,0 @@ } |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
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) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const breeze_client_1 = require("breeze-client"); | ||
const sequelize_1 = require("sequelize"); | ||
const SQVisitor_1 = require("./SQVisitor"); | ||
const _ = require("lodash"); | ||
const sequelize_1 = require("sequelize"); | ||
const urlUtils = require("url"); | ||
const SQVisitor_1 = require("./SQVisitor"); | ||
/** Create an EntityQuery from a JSON-format breeze query string | ||
@@ -52,5 +61,6 @@ * @param url - url containing query, e.g. `/orders?{freight:{">":100}}` | ||
execute(options) { | ||
return this.executeRaw(options).then(r => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const r = yield this.executeRaw(options); | ||
let result = this._reshapeResults(r); | ||
return Promise.resolve(result); | ||
return result; | ||
}); | ||
@@ -60,33 +70,27 @@ } | ||
executeRaw(options) { | ||
let self = this; | ||
let model = self.sequelizeManager.resourceNameSqModelMap[self.entityQuery.resourceName]; | ||
let methodName = self.entityQuery.inlineCountEnabled ? "findAndCountAll" : "findAll"; | ||
options = options || { useTransaction: false, beforeQueryEntities: undefined }; | ||
return (function () { | ||
if (options.useTransaction) | ||
return self.sequelizeManager.sequelize.transaction() | ||
.then(function (trans) { | ||
self.transaction = trans; | ||
self.sqQuery.transaction = trans; | ||
}); | ||
else | ||
return Promise.resolve(); | ||
})() | ||
.then(function () { | ||
if (options.beforeQueryEntities) | ||
return options.beforeQueryEntities.call(self); | ||
else | ||
return Promise.resolve(); | ||
}) | ||
.then(function () { | ||
return model[methodName].call(model, self.sqQuery); | ||
}) | ||
.then(function (results) { | ||
if (options.useTransaction) | ||
self.sqQuery.transaction.commit(); | ||
return results; | ||
}, function (e) { | ||
if (options.useTransaction) | ||
self.sqQuery.transaction.rollback(); | ||
throw e; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let model = this.sequelizeManager.resourceNameSqModelMap[this.entityQuery.resourceName]; | ||
let methodName = this.entityQuery.inlineCountEnabled ? "findAndCountAll" : "findAll"; | ||
options = options || { useTransaction: false, beforeQueryEntities: undefined }; | ||
if (options.useTransaction) { | ||
const trans = yield this.sequelizeManager.sequelize.transaction(); | ||
this.transaction = trans; | ||
this.sqQuery.transaction = trans; | ||
} | ||
if (options.beforeQueryEntities) { | ||
return options.beforeQueryEntities.call(this); | ||
} | ||
try { | ||
const results = yield model[methodName].call(model, this.sqQuery); | ||
if (options.useTransaction) { | ||
this.sqQuery.transaction.commit(); | ||
} | ||
return results; | ||
} | ||
catch (e) { | ||
if (options.useTransaction) { | ||
this.sqQuery.transaction.rollback(); | ||
} | ||
throw e; | ||
} | ||
}); | ||
@@ -224,3 +228,3 @@ } | ||
// needed because we had to turn take(0) into limit(1) | ||
if (this.entityQuery.takeCount == 0) { | ||
if (this.entityQuery.takeCount === 0) { | ||
sqResults = []; | ||
@@ -328,3 +332,3 @@ } | ||
} | ||
if (expandProps == null || expandProps.length == 0) | ||
if (expandProps == null || expandProps.length === 0) | ||
return; | ||
@@ -342,5 +346,3 @@ // now blow out all of the expands | ||
return this._createResult(nextSqr, nextEntityType, true); | ||
}, this).filter(r => { | ||
return r != null; | ||
}); | ||
}, this).filter(r => r != null); | ||
} | ||
@@ -397,3 +399,3 @@ else { | ||
include.attributes = include.attributes || []; | ||
if (include.attributes.length == 0) { | ||
if (include.attributes.length === 0) { | ||
include.attributes = include.model.primaryKeyAttributes; | ||
@@ -440,5 +442,5 @@ } | ||
function getKey(sqResult, entityType) { | ||
let key = entityType.keyProperties.map(function (kp) { | ||
return sqResult[kp.nameOnServer]; | ||
}).join("::") + "^" + entityType.name; | ||
let key = entityType.keyProperties | ||
.map(kp => sqResult[kp.nameOnServer]) | ||
.join("::") + "^" + entityType.name; | ||
return key; | ||
@@ -453,5 +455,3 @@ } | ||
} | ||
parent.include && parent.include.forEach(function (inc) { | ||
processAndOr(inc); | ||
}); | ||
parent.include && parent.include.forEach(inc => processAndOr(inc)); | ||
console.trace(parent); | ||
@@ -464,5 +464,3 @@ } | ||
if (ands) { | ||
let clauses = ands.map(function (clause) { | ||
return processAndOrClause(clause); | ||
}); | ||
let clauses = ands.map(clause => processAndOrClause(clause)); | ||
return sequelize_1.Sequelize.and.apply(null, clauses); | ||
@@ -472,5 +470,3 @@ // return Sequelize.and(clauses[0], clauses[1]); | ||
else if (ors) { | ||
let clauses = ors.map(function (clause) { | ||
return processAndOrClause(clause); | ||
}); | ||
let clauses = ors.map(clause => processAndOrClause(clause)); | ||
return sequelize_1.Sequelize.or.apply(null, clauses); | ||
@@ -477,0 +473,0 @@ } |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
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) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const bluebird_1 = require("bluebird"); | ||
// import Promise from 'bluebird'; | ||
const breeze_client_1 = require("breeze-client"); | ||
const _ = require("lodash"); | ||
const SaveMap_1 = require("./SaveMap"); | ||
let toposort = require("toposort"); | ||
class ServerSaveError extends Error { | ||
constructor(m, entityErrors) { | ||
super(m); | ||
this.entityErrors = entityErrors; | ||
// Set the prototype explicitly. | ||
Object.setPrototypeOf(this, ServerSaveError.prototype); | ||
} | ||
} | ||
exports.ServerSaveError = ServerSaveError; | ||
class SequelizeSaveError extends Error { | ||
constructor(e, entity, entityState) { | ||
super(e.message); | ||
e.stack = undefined; | ||
breeze_client_1.core.extend(this, e); | ||
this.entity = entity; | ||
this.entityState = entityState; | ||
Object.setPrototypeOf(this, SequelizeSaveError.prototype); | ||
} | ||
} | ||
exports.SequelizeSaveError = SequelizeSaveError; | ||
/** Handles saving entities from Breeze SaveChanges requests */ | ||
@@ -23,170 +53,172 @@ class SequelizeSaveHandler { | ||
save() { | ||
let beforeSaveEntity = (this.beforeSaveEntity || noopBeforeSaveEntity).bind(this); | ||
let entityTypeMap = {}; | ||
let entityInfos = this.entitiesFromClient.map(entity => { | ||
// transform entities from how they are sent from the client | ||
// into entityInfo objects which is how they are exposed | ||
// to interception on the server. | ||
let entityAspect = entity.entityAspect; | ||
let entityTypeName = entityAspect.entityTypeName; | ||
let entityType = entityTypeMap[entityTypeName]; | ||
if (!entityType) { | ||
entityType = this.metadataStore.getEntityType(entityTypeName); | ||
if (entityType) { | ||
entityTypeMap[entityTypeName] = entityType; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let beforeSaveEntity = (this.beforeSaveEntity || noopBeforeSaveEntity).bind(this); | ||
let entityTypeMap = {}; | ||
let entityInfos = this.entitiesFromClient.map(entity => { | ||
// transform entities from how they are sent from the client | ||
// into entityInfo objects which is how they are exposed | ||
// to interception on the server. | ||
let entityAspect = entity.entityAspect; | ||
let entityTypeName = entityAspect.entityTypeName; | ||
let entityType = entityTypeMap[entityTypeName]; | ||
if (!entityType) { | ||
entityType = this.metadataStore.getEntityType(entityTypeName); | ||
if (entityType) { | ||
entityTypeMap[entityTypeName] = entityType; | ||
} | ||
else { | ||
throw new Error("Unable to locate server side metadata for an EntityType named: " + entityTypeName); | ||
} | ||
} | ||
else { | ||
throw new Error("Unable to locate server side metadata for an EntityType named: " + entityTypeName); | ||
let unmapped = entity.__unmapped; | ||
let ei = { entity: entity, entityType: entityType, entityAspect: entityAspect, unmapped: unmapped }; | ||
// just to be sure that we don't try to send it to the db server or return it to the client. | ||
delete entity.entityAspect; | ||
return ei; | ||
}); | ||
// create the saveMap (entities to be saved) grouped by entityType | ||
let saveMapData = _.groupBy(entityInfos, entityInfo => { | ||
// _.groupBy will bundle all undefined returns together. | ||
if (beforeSaveEntity(entityInfo)) { | ||
return entityInfo.entityType.name; | ||
} | ||
} | ||
let unmapped = entity.__unmapped; | ||
let ei = { entity: entity, entityType: entityType, entityAspect: entityAspect, unmapped: unmapped }; | ||
// just to be sure that we don't try to send it to the db server or return it to the client. | ||
delete entity.entityAspect; | ||
return ei; | ||
}, this); | ||
// create the saveMap (entities to be saved) grouped by entityType | ||
let saveMapData = _.groupBy(entityInfos, entityInfo => { | ||
// _.groupBy will bundle all undefined returns together. | ||
if (beforeSaveEntity(entityInfo)) { | ||
return entityInfo.entityType.name; | ||
} | ||
}); | ||
// remove the entries where beforeSaveEntity returned false ( they are all grouped under 'undefined' | ||
delete saveMapData["undefined"]; | ||
// want to have SaveMap functions available | ||
let saveMap = _.extend(new SaveMap_1.SaveMap(this), saveMapData); | ||
return this._saveWithTransaction(saveMap); | ||
}); | ||
// remove the entries where beforeSaveEntity returned false ( they are all grouped under 'undefined' | ||
delete saveMapData["undefined"]; | ||
// want to have SaveMap functions available | ||
let saveMap = _.extend(new SaveMap_1.SaveMap(this), saveMapData); | ||
return this._saveWithTransaction(saveMap); | ||
} | ||
_saveWithTransaction(saveMap) { | ||
let sequelize = this.sequelizeManager.sequelize; | ||
return sequelize.transaction().then(trx => { | ||
// this.transaction = trx; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let sequelize = this.sequelizeManager.sequelize; | ||
// TODO: consider making the isolation level settable on the SequelizeManager. | ||
// const trx = await sequelize.transaction( { isolationLevel: Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED }); | ||
const trx = yield sequelize.transaction(); | ||
let beforeSaveEntities = (this.beforeSaveEntities || noopBeforeSaveEntities).bind(this); | ||
// beforeSaveEntities will either return nothing or a promise. | ||
let nextPromise = bluebird_1.Promise.resolve(beforeSaveEntities(saveMap, trx)); | ||
const sm = yield beforeSaveEntities(saveMap, trx); | ||
// saveCore returns either a list of entities or an object with an errors property. | ||
return nextPromise.then(sm => { | ||
return this._saveCore(saveMap, trx); | ||
}).then((r) => { | ||
if (r.errors) { | ||
trx.rollback(); | ||
return r; | ||
try { | ||
const r = yield this._saveCore(saveMap, trx); | ||
trx.commit(); | ||
return { entities: r, keyMappings: this._keyMappings }; | ||
} | ||
catch (e) { | ||
// will throw either a ServerSaveError or a SequelizeSaveError | ||
trx.rollback(); | ||
// we have to return an object with an 'errors' property | ||
if (e instanceof ServerSaveError) { | ||
return { errors: e.entityErrors, message: e.message }; | ||
} | ||
else if (e instanceof SequelizeSaveError) { | ||
return { errors: [e], message: e.name + ": " + e.message }; | ||
} | ||
else { | ||
trx.commit(); | ||
return { entities: r, keyMappings: this._keyMappings }; | ||
return { errors: [], message: e.message }; | ||
} | ||
}).catch((e) => { | ||
trx.rollback(); | ||
throw e; | ||
}); | ||
} | ||
}); | ||
} | ||
; | ||
_saveCore(saveMap, transaction) { | ||
if (saveMap.entityErrors || saveMap.errorMessage) { | ||
return bluebird_1.Promise.resolve({ errors: saveMap.entityErrors || [], message: saveMap.errorMessage }); | ||
} | ||
let entityTypes = _.keys(saveMap).map((entityTypeName) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (saveMap.entityErrors || saveMap.errorMessage) { | ||
throw new ServerSaveError(saveMap.errorMessage, saveMap.entityErrors); | ||
} | ||
// guaranteed to succeed because these have all been looked up earlier. | ||
return this.metadataStore.getEntityType(entityTypeName); | ||
}, this); | ||
let sortedEntityTypes = toposortEntityTypes(entityTypes); | ||
let entityGroups = sortedEntityTypes.map((entityType) => { | ||
return { entityType: entityType, entityInfos: saveMap[entityType.name] }; | ||
}); | ||
// do adds/updates first followed by deletes in reverse order. | ||
// add/updates come first because we might move children off of a parent before deleting the parent | ||
// and we don't want to cause a constraint exception by deleting the parent before all of its | ||
// children have been moved somewhere else. | ||
return bluebird_1.Promise.reduce(entityGroups, (savedEntities, entityGroup) => { | ||
return this._processEntityGroup(entityGroup, transaction, false).then(entities => { | ||
Array.prototype.push.apply(savedEntities, entities); | ||
return savedEntities; | ||
let entityTypes = _.keys(saveMap).map(entityTypeName => this.metadataStore.getEntityType(entityTypeName)); | ||
let sortedEntityTypes = toposortEntityTypes(entityTypes); | ||
let entityGroups = sortedEntityTypes.map((entityType) => { | ||
return { entityType: entityType, entityInfos: saveMap[entityType.name] }; | ||
}); | ||
}, []).then(entitiesHandledSoFar => { | ||
return bluebird_1.Promise.reduce(entityGroups.reverse(), (savedEntities, entityGroup) => { | ||
return this._processEntityGroup(entityGroup, transaction, true).then(entities => { | ||
Array.prototype.push.apply(savedEntities, entities); | ||
return savedEntities; | ||
}); | ||
}, entitiesHandledSoFar); | ||
// do adds/updates first followed by deletes in reverse order. | ||
// add/updates come first because we might move children off of a parent before deleting the parent | ||
// and we don't want to cause a constraint exception by deleting the parent before all of its | ||
// children have been moved somewhere else. | ||
const addedUpdatedEntities = []; | ||
// can't use entityGroups.map here because we DO NOT want the groups to run in parallel. | ||
for (let entityGroup of entityGroups) { | ||
const r = yield this._processEntityGroup(entityGroup, transaction, false); | ||
addedUpdatedEntities.push(...r); | ||
} | ||
const deletedEntities = []; | ||
// can't use entityGroups.map here because we DO NOT want the groups to run in parallel. | ||
for (let entityGroup of entityGroups.reverse()) { | ||
const r = yield this._processEntityGroup(entityGroup, transaction, true); | ||
deletedEntities.push(...r); | ||
} | ||
const savedEntities = [...addedUpdatedEntities, ...deletedEntities]; | ||
return savedEntities; | ||
}); | ||
} | ||
_processEntityGroup(entityGroup, transaction, processDeleted) { | ||
let entityType = entityGroup.entityType; | ||
let entityInfos = entityGroup.entityInfos.filter(entityInfo => { | ||
let isDeleted = entityInfo.entityAspect.entityState == "Deleted"; | ||
return processDeleted ? isDeleted : !isDeleted; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let entityType = entityGroup.entityType; | ||
let entityInfos = entityGroup.entityInfos.filter(entityInfo => { | ||
let isDeleted = entityInfo.entityAspect.entityState === "Deleted"; | ||
return processDeleted ? isDeleted : !isDeleted; | ||
}); | ||
let sqModel = this.sequelizeManager.entityTypeSqModelMap[entityType.name]; | ||
entityInfos = toposortEntityInfos(entityType, entityInfos); | ||
if (processDeleted) { | ||
entityInfos = entityInfos.reverse(); | ||
} | ||
const promises = entityInfos.map((entityInfo) => __awaiter(this, void 0, void 0, function* () { | ||
return yield this._saveEntityAsync(entityInfo, sqModel, transaction); | ||
})); | ||
const savedEntities = yield Promise.all(promises); | ||
return savedEntities; | ||
}); | ||
let sqModel = this.sequelizeManager.entityTypeSqModelMap[entityType.name]; | ||
entityInfos = toposortEntityInfos(entityType, entityInfos); | ||
if (processDeleted) { | ||
entityInfos = entityInfos.reverse(); | ||
} | ||
return bluebird_1.Promise.reduce(entityInfos, (savedEntities, entityInfo) => { | ||
} | ||
_saveEntityAsync(entityInfo, sqModel, transaction) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// function returns a promise for this entity | ||
// and updates the results array. | ||
return this._saveEntityAsync(entityInfo, sqModel, transaction).then(savedEntity => { | ||
savedEntities.push(savedEntity); | ||
return savedEntities; | ||
}); | ||
}, []); | ||
} | ||
; | ||
_saveEntityAsync(entityInfo, sqModel, transaction) { | ||
// function returns a promise for this entity | ||
// and updates the results array. | ||
// not a "real" entityAspect - just the salient pieces sent from the client. | ||
let entity = entityInfo.entity; | ||
let entityAspect = entityInfo.entityAspect; | ||
let entityType = entityInfo.entityType; | ||
let entityTypeName = entityType.name; | ||
// TODO: determine if this is needed because we need to strip the entityAspect off the entity for inserts. | ||
entityAspect.entity = entity; | ||
// TODO: we really only need to coerce every field on an insert | ||
// only selected fields are needed for update and delete. | ||
this._coerceData(entity, entityType); | ||
let keyProperties = entityType.keyProperties; | ||
let firstKeyPropName = keyProperties[0].nameOnServer; | ||
let entityState = entityAspect.entityState; | ||
let trxOptions = { transaction: transaction }; | ||
let promise; | ||
if (entityState === "Added") { | ||
let keyMapping = null; | ||
// NOTE: there are two instances of autoGeneratedKeyType available | ||
// one on entityType which is part of the metadata and a second | ||
// on the entityAspect that was sent as part of the save. | ||
// The one on the entityAspect "overrides" the one on the entityType. | ||
let autoGeneratedKey = entityAspect.autoGeneratedKey; | ||
let autoGeneratedKeyType = autoGeneratedKey && autoGeneratedKey.autoGeneratedKeyType; | ||
let tempKeyValue = entity[firstKeyPropName]; | ||
if (autoGeneratedKeyType && autoGeneratedKeyType !== "None") { | ||
let realKeyValue; | ||
if (autoGeneratedKeyType == "KeyGenerator") { | ||
if (this.keyGenerator == null) { | ||
throw new Error("No KeyGenerator was provided for property:" + keyProperties[0].name + " on entityType: " + entityType.name); | ||
} | ||
promise = this.keyGenerator.getNextId(keyProperties[0]).then((nextId) => { | ||
// not a "real" entityAspect - just the salient pieces sent from the client. | ||
let entity = entityInfo.entity; | ||
let entityAspect = entityInfo.entityAspect; | ||
let entityType = entityInfo.entityType; | ||
let entityTypeName = entityType.name; | ||
// TODO: determine if this is needed because we need to strip the entityAspect off the entity for inserts. | ||
entityAspect.entity = entity; | ||
// TODO: we really only need to coerce every field on an insert | ||
// only selected fields are needed for update and delete. | ||
this._coerceData(entity, entityType); | ||
let keyProperties = entityType.keyProperties; | ||
let firstKeyPropName = keyProperties[0].nameOnServer; | ||
let entityState = entityAspect.entityState; | ||
if (entityState === "Added") { | ||
let keyMapping = null; | ||
// NOTE: there are two instances of autoGeneratedKeyType available | ||
// one on entityType which is part of the metadata and a second | ||
// on the entityAspect that was sent as part of the save. | ||
// The one on the entityAspect "overrides" the one on the entityType. | ||
let autoGeneratedKey = entityAspect.autoGeneratedKey; | ||
let autoGeneratedKeyType = autoGeneratedKey && autoGeneratedKey.autoGeneratedKeyType; | ||
let tempKeyValue = entity[firstKeyPropName]; | ||
if (autoGeneratedKeyType && autoGeneratedKeyType !== "None") { | ||
let realKeyValue; | ||
if (autoGeneratedKeyType === "KeyGenerator") { | ||
if (this.keyGenerator == null) { | ||
throw new Error("No KeyGenerator was provided for property:" + keyProperties[0].name + " on entityType: " + entityType.name); | ||
} | ||
const nextId = yield this.keyGenerator.getNextId(keyProperties[0]); | ||
realKeyValue = nextId; | ||
entity[firstKeyPropName] = realKeyValue; | ||
}); | ||
} | ||
else if (autoGeneratedKeyType == "Identity") { | ||
let keyDataTypeName = keyProperties[0].dataType.name; | ||
if (keyDataTypeName === "Guid") { | ||
// handled here instead of one the db server. | ||
realKeyValue = createGuid(); | ||
entity[firstKeyPropName] = realKeyValue; | ||
} | ||
else { | ||
// realValue will be set during 'create' promise resolution below | ||
realKeyValue = null; | ||
// value will be set by server's autoincrement logic | ||
delete entity[firstKeyPropName]; | ||
else if (autoGeneratedKeyType === "Identity") { | ||
let keyDataTypeName = keyProperties[0].dataType.name; | ||
if (keyDataTypeName === "Guid") { | ||
// handled here instead of one the db server. | ||
realKeyValue = createGuid(); | ||
entity[firstKeyPropName] = realKeyValue; | ||
} | ||
else { | ||
// realValue will be set during 'create' promise resolution below | ||
realKeyValue = null; | ||
// value will be set by server's autoincrement logic | ||
delete entity[firstKeyPropName]; | ||
} | ||
} | ||
} | ||
promise = promise || bluebird_1.Promise.resolve(null); | ||
promise = promise.then(() => { | ||
// tempKeyValue will be undefined in entity was created on the server | ||
@@ -196,7 +228,5 @@ if (tempKeyValue != undefined) { | ||
} | ||
}); | ||
} | ||
promise = promise || bluebird_1.Promise.resolve(null); | ||
return promise.then(() => { | ||
return sqModel.create(entity, { transaction: transaction }).then((savedEntity) => { | ||
} | ||
try { | ||
const savedEntity = yield sqModel.create(entity, { transaction: transaction }); | ||
if (keyMapping) { | ||
@@ -211,75 +241,86 @@ if (keyMapping.realValue === null) { | ||
return this._addToResults(savedEntity.dataValues, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
}); | ||
} | ||
else if (entityState === "Modified") { | ||
let whereHash = {}; | ||
keyProperties.forEach(kp => { | ||
whereHash[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
}); | ||
if (entityType.concurrencyProperties && entityType.concurrencyProperties.length > 0) { | ||
entityType.concurrencyProperties.forEach(cp => { | ||
// this is consistent with the client behaviour where it does not update the version property | ||
// if its data type is binary | ||
if (cp.dataType.name === 'Binary') | ||
whereHash[cp.nameOnServer] = entity[cp.nameOnServer]; | ||
else | ||
whereHash[cp.nameOnServer] = entityAspect.originalValuesMap[cp.nameOnServer]; | ||
} | ||
catch (e) { | ||
throw new SequelizeSaveError(e, entity, entityState); | ||
} | ||
} | ||
else if (entityState === "Modified") { | ||
let whereHash = {}; | ||
keyProperties.forEach(kp => { | ||
whereHash[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
}); | ||
} | ||
let setHash; | ||
if (entityInfo.forceUpdate) { | ||
setHash = _.clone(entity); | ||
// remove fields that we don't want to 'set' | ||
delete setHash.entityAspect; | ||
// TODO: should we also remove keyProps here... | ||
} | ||
else { | ||
setHash = {}; | ||
let ovm = entityAspect.originalValuesMap; | ||
if (ovm == null) { | ||
throw new Error("Unable to locate an originalValuesMap for one of the 'Modified' entities to be saved"); | ||
if (entityType.concurrencyProperties && entityType.concurrencyProperties.length > 0) { | ||
entityType.concurrencyProperties.forEach(cp => { | ||
// this is consistent with the client behaviour where it does not update the version property | ||
// if its data type is binary | ||
if (cp.dataType.name === 'Binary') | ||
whereHash[cp.nameOnServer] = entity[cp.nameOnServer]; | ||
else | ||
whereHash[cp.nameOnServer] = entityAspect.originalValuesMap[cp.nameOnServer]; | ||
}); | ||
} | ||
Object.keys(ovm).forEach(k => { | ||
// if k is one of the entityKeys do no allow this | ||
let isKeyPropName = keyProperties.some(kp => { | ||
return kp.nameOnServer == k; | ||
let setHash; | ||
if (entityInfo.forceUpdate) { | ||
setHash = _.clone(entity); | ||
// remove fields that we don't want to 'set' | ||
delete setHash.entityAspect; | ||
// TODO: should we also remove keyProps here... | ||
} | ||
else { | ||
setHash = {}; | ||
let ovm = entityAspect.originalValuesMap; | ||
if (ovm == null) { | ||
throw new Error("Unable to locate an originalValuesMap for one of the 'Modified' entities to be saved"); | ||
} | ||
Object.keys(ovm).forEach(k => { | ||
// if k is one of the entityKeys do no allow this | ||
let isKeyPropName = keyProperties.some(kp => { | ||
return kp.nameOnServer === k; | ||
}); | ||
if (isKeyPropName) { | ||
throw new Error("Breeze does not support updating any part of the entity's key insofar as this changes the identity of the entity"); | ||
} | ||
setHash[k] = entity[k]; | ||
}); | ||
if (isKeyPropName) { | ||
throw new Error("Breeze does not support updating any part of the entity's key insofar as this changes the identity of the entity"); | ||
} | ||
// don't bother executing update statement if nothing to update | ||
// this can happen if setModified is called without any properties being changed. | ||
if (_.isEmpty(setHash)) { | ||
return this._addToResults(entity, entityTypeName); | ||
} | ||
try { | ||
const infoArray = yield sqModel.update(setHash, { where: whereHash, transaction: transaction }); | ||
let itemsSaved = infoArray[0]; | ||
if (itemsSaved !== 1) { | ||
let err = new Error("unable to update entity - concurrency violation"); | ||
err.entity = entity; | ||
err.entityState = entityState; | ||
throw err; | ||
} | ||
setHash[k] = entity[k]; | ||
// HACK: Sequelize 'update' does not return the entity; so | ||
// we are just returning the original entity here. | ||
return this._addToResults(entity, entityTypeName); | ||
} | ||
catch (e) { | ||
throw new SequelizeSaveError(e, entity, entityState); | ||
} | ||
} | ||
else if (entityState === "Deleted") { | ||
let whereHash = {}; | ||
keyProperties.forEach(kp => { | ||
whereHash[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
}); | ||
try { | ||
// we don't bother with concurrency check on deletes | ||
// TODO: we may want to add a 'switch' for this later. | ||
yield sqModel.destroy({ where: whereHash, limit: 1, transaction: transaction }); | ||
// Sequelize 'destroy' does not return the entity; so | ||
// we are just returning the original entity here. | ||
return this._addToResults(entity, entityTypeName); | ||
} | ||
catch (e) { | ||
throw new SequelizeSaveError(e, entity, entityState); | ||
} | ||
} | ||
// don't bother executing update statement if nothing to update | ||
// this can happen if setModified is called without any properties being changed. | ||
if (_.isEmpty(setHash)) { | ||
return bluebird_1.Promise.resolve(this._addToResults(entity, entityTypeName)); | ||
} | ||
return sqModel.update(setHash, { where: whereHash, transaction: transaction }).then(infoArray => { | ||
let itemsSaved = infoArray[0]; | ||
if (itemsSaved != 1) { | ||
let err = new Error("unable to update entity - concurrency violation"); | ||
err.entity = entity; | ||
err.entityState = entityState; | ||
throw err; | ||
} | ||
// HACK: Sequelize 'update' does not return the entity; so | ||
// we are just returning the original entity here. | ||
return this._addToResults(entity, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
} | ||
else if (entityState === "Deleted") { | ||
let whereHash = {}; | ||
keyProperties.forEach(kp => { | ||
whereHash[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
}); | ||
// we don't bother with concurrency check on deletes | ||
// TODO: we may want to add a 'switch' for this later. | ||
return sqModel.destroy({ where: whereHash, limit: 1, transaction: transaction }).then(() => { | ||
// Sequelize 'destroy' does not return the entity; so | ||
// we are just returning the original entity here. | ||
return this._addToResults(entity, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
} | ||
}); | ||
} | ||
@@ -333,3 +374,3 @@ _addToResults(entity, entityTypeName) { | ||
let dependsOnType = fkp.relatedNavigationProperty.entityType; | ||
if (et != dependsOnType) { | ||
if (et !== dependsOnType) { | ||
edges.push([et, dependsOnType]); | ||
@@ -384,14 +425,5 @@ } | ||
} | ||
function handleItemSaveError(entity, entityState) { | ||
return function (err) { | ||
err = typeof (err) == 'string' ? new Error(err) : err; | ||
let detailedMsg = (err.name ? "error name: " + err.name : "") + (err.sql ? " sql: " + err.sql : ""); | ||
err.message = err.message ? err.message + ". " + detailedMsg : detailedMsg; | ||
err.entity = entity; | ||
err.entityState = entityState; | ||
throw err; | ||
}; | ||
} | ||
function createGuid() { | ||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | ||
// tslint:disable-next-line: triple-equals | ||
let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | ||
@@ -398,0 +430,0 @@ return v.toString(16); |
@@ -31,3 +31,3 @@ "use strict"; | ||
} | ||
else if (this.expr1.visitorMethodName == "fnExpr") { | ||
else if (this.expr1.visitorMethodName === "fnExpr") { | ||
p1Value = processFnExpr(this.expr1, context, result); | ||
@@ -47,3 +47,3 @@ } | ||
} | ||
else if (op == "startswith") { | ||
else if (op === "startswith") { | ||
crit = { [like]: p2Value + "%" }; | ||
@@ -63,3 +63,3 @@ } | ||
} | ||
else if (this.expr2.visitorMethodName == "propExpr") { | ||
else if (this.expr2.visitorMethodName === "propExpr") { | ||
let p2Value = this.expr2.propertyPath; | ||
@@ -112,6 +112,6 @@ let props = context.entityType.getPropertiesOnPath(p2Value, context.toNameOnServer, true); | ||
let includes = []; | ||
if (predSqs.length == 0) { | ||
if (predSqs.length === 0) { | ||
return null; | ||
} | ||
else if (predSqs.length == 1) { | ||
else if (predSqs.length === 1) { | ||
return predSqs[0]; | ||
@@ -135,3 +135,3 @@ } | ||
else { | ||
if (include.where == null) { | ||
if (include.where === null) { | ||
include.where = sourceInclude.where; | ||
@@ -144,3 +144,3 @@ } | ||
} | ||
if (include.attributes == null || include.attributes.length == 0) { | ||
if (include.attributes === null || include.attributes.length === 0) { | ||
include.attributes = sourceInclude.attributes; | ||
@@ -162,3 +162,3 @@ } | ||
if (wheres.length > 0) { | ||
result.where = wheres.length == 1 ? wheres[0] : { [sequelize_1.Op.and]: wheres }; | ||
result.where = wheres.length === 1 ? wheres[0] : { [sequelize_1.Op.and]: wheres }; | ||
} | ||
@@ -168,7 +168,7 @@ // q = Sequelize.and(q1, q2); | ||
else { | ||
if (includes.length > 1 || (includes.length == 1 && wheres.length != 0)) { | ||
if (includes.length > 1 || (includes.length === 1 && wheres.length !== 0)) { | ||
throw new Error("Cannot translate a query with nested property paths and 'OR' conditions to Sequelize. (Sorry)."); | ||
} | ||
if (wheres.length > 0) { | ||
result.where = wheres.length == 1 ? wheres[0] : { [sequelize_1.Op.or]: wheres }; | ||
result.where = wheres.length === 1 ? wheres[0] : { [sequelize_1.Op.or]: wheres }; | ||
} | ||
@@ -207,3 +207,3 @@ // q = Sequelize.or(q1, q2); | ||
let where; | ||
if (typeof (p1Value) == 'string') { | ||
if (typeof (p1Value) === 'string') { | ||
where = {}; | ||
@@ -256,3 +256,3 @@ where[p1Value] = crit; | ||
} | ||
else if (expr.visitorMethodName == 'fnExpr') { | ||
else if (expr.visitorMethodName === 'fnExpr') { | ||
let exprVal = processFnExpr(expr, context, result); | ||
@@ -306,6 +306,6 @@ return exprVal; | ||
let errMsg; | ||
if (exprs.length != 1) { | ||
if (exprs.length !== 1) { | ||
errMsg = formatString(errTmpl + " This function only takes a single parameter", fnName); | ||
} | ||
else if (exprs[0].visitorMethodName == 'litExpr') { | ||
else if (exprs[0].visitorMethodName === 'litExpr') { | ||
errMsg = formatString(errTmpl + " The single parameter may not be a literal expression. Param: %2", fnName, exprs[0].toString()); | ||
@@ -319,6 +319,6 @@ } | ||
// format("a %1 and a %2", "cat", "dog") -> "a cat and a dog" | ||
function formatString(string, ...rest) { | ||
function formatString(str, ...rest) { | ||
let args = arguments; | ||
let pattern = RegExp("%([1-" + (arguments.length - 1) + "])", "g"); | ||
return string.replace(pattern, function (match, index) { | ||
return str.replace(pattern, function (match, index) { | ||
return args[index]; | ||
@@ -325,0 +325,0 @@ }); |
import { SequelizeQuery, SequelizeQueryResult, urlToEntityQuery } from "./SequelizeQuery"; | ||
import { SequelizeManager, KeyGenerator } from "./SequelizeManager"; | ||
import { SequelizeSaveHandler, SequelizeSaveResult, ServerEntityInfo, ServerEntityAspect, ServerEntity, ServerEntityState } from "./SequelizeSaveHandler"; | ||
import { SequelizeSaveHandler, ServerSaveResult, ServerEntityInfo, ServerEntityAspect, ServerEntity, ServerEntityState } from "./SequelizeSaveHandler"; | ||
import { SaveMap } from './SaveMap'; | ||
import * as utils from "./utils"; | ||
import * as dbUtils from "./dbUtils"; | ||
import { connect } from "./dbUtils"; | ||
import { breeze } from "breeze-client"; | ||
declare const Sequelize: typeof import("sequelize/types").Sequelize; | ||
export { Sequelize, SequelizeQuery, SequelizeManager, SequelizeSaveHandler, KeyGenerator, SequelizeQueryResult, SequelizeSaveResult, SaveMap, ServerEntity, ServerEntityAspect, ServerEntityInfo, ServerEntityState, urlToEntityQuery, utils, dbUtils, breeze }; | ||
export { Sequelize, SequelizeQuery, SequelizeManager, SequelizeSaveHandler, KeyGenerator, SequelizeQueryResult, ServerSaveResult as SequelizeSaveResult, SaveMap, ServerEntity, ServerEntityAspect, ServerEntityInfo, ServerEntityState, urlToEntityQuery, connect, breeze }; |
@@ -31,4 +31,4 @@ import { Sequelize, Options, SyncOptions } from "sequelize"; | ||
/** Sync the Sequelize model with the database */ | ||
sync(shouldCreateDb: boolean, sequelizeOpts: SyncOptions): Promise<Sequelize>; | ||
sync(shouldCreateDb: boolean, sequelizeOpts: SyncOptions): Promise<any>; | ||
private syncCore; | ||
} |
@@ -1,4 +0,4 @@ | ||
import { Entity, EntityType, KeyMapping, MetadataStore, SaveOptions } from "breeze-client"; | ||
import { EntityType, KeyMapping, MetadataStore, SaveOptions } from "breeze-client"; | ||
import { BaseError, Transaction } from "sequelize"; | ||
import { SaveMap } from "./SaveMap"; | ||
import { Transaction } from "sequelize"; | ||
import { KeyGenerator, SequelizeManager } from "./SequelizeManager"; | ||
@@ -16,6 +16,2 @@ export declare type OpenObj = { | ||
} | ||
export interface ServerEntity { | ||
[k: string]: any; | ||
entityAspect: ServerEntityAspect; | ||
} | ||
/** Server-side representation of entity that came from the client */ | ||
@@ -30,2 +26,6 @@ export interface ServerEntityInfo { | ||
} | ||
export interface ServerEntity { | ||
[k: string]: any; | ||
entityAspect: ServerEntityAspect; | ||
} | ||
export interface ServerEntityAspect { | ||
@@ -44,2 +44,21 @@ entityTypeName: string; | ||
} | ||
export declare type ServerSaveResult = ServerGoodSaveResult | ServerBadSaveResult; | ||
export interface ServerGoodSaveResult { | ||
entities: OpenObj[]; | ||
keyMappings: KeyMapping[]; | ||
} | ||
export interface ServerBadSaveResult { | ||
errors: any[]; | ||
message: string; | ||
[k: string]: any; | ||
} | ||
export declare class ServerSaveError extends Error { | ||
entityErrors: ServerEntityError[]; | ||
constructor(m: string, entityErrors?: ServerEntityError[]); | ||
} | ||
export declare class SequelizeSaveError extends Error { | ||
entity: OpenObj; | ||
entityState: ServerEntityState; | ||
constructor(e: BaseError, entity: OpenObj, entityState?: ServerEntityState); | ||
} | ||
/** Validation error created on the server */ | ||
@@ -53,10 +72,2 @@ export interface ServerEntityError { | ||
} | ||
export interface SequelizeSaveError { | ||
errors: ServerEntityError[]; | ||
message: string; | ||
} | ||
export interface SequelizeSaveResult { | ||
entities: Entity[]; | ||
keyMappings: KeyMapping[]; | ||
} | ||
export declare type BeforeSaveEntityFn = (e: ServerEntityInfo) => boolean; | ||
@@ -82,3 +93,3 @@ export declare type BeforeSaveEntitiesFn = (sm: SaveMap, trx?: Transaction) => Promise<SaveMap>; | ||
/** Save the entities in the save request, returning either the saved entities or an error collection */ | ||
save(): Promise<SequelizeSaveResult>; | ||
save(): Promise<ServerSaveResult>; | ||
private _saveWithTransaction; | ||
@@ -85,0 +96,0 @@ private _saveCore; |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
91740
4
11
1953
0