breeze-sequelize
Advanced tools
Comparing version 0.4.1 to 0.5.2
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var sequelize_1 = require("sequelize"); | ||
var utils = require('./utils.js'); | ||
var log = utils.log; | ||
const sequelize_1 = require("sequelize"); | ||
let utils = require('./utils.js'); | ||
let log = utils.log; | ||
exports.connect = connect; | ||
@@ -11,4 +11,4 @@ exports.createDb = createDb; | ||
function connect(dbConfig, sequelizeOptions) { | ||
var sequelize = new sequelize_1.Sequelize(dbConfig.dbName, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
var statement = 'SELECT 1'; | ||
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) { | ||
@@ -27,7 +27,7 @@ log("Connected to database: " + dbConfig.dbName); | ||
function createDb(dbConfig, sequelizeOptions) { | ||
var sequelize = new sequelize_1.Sequelize(null, dbConfig.user, dbConfig.password, sequelizeOptions); | ||
var statement = 'CREATE DATABASE ' + dbConfig.dbName; | ||
return sequelize.query(statement, { type: sequelize_1.QueryTypes.RAW }).then(function () { | ||
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(function (err) { | ||
}).error(err => { | ||
if (err.message && err.message.indexOf("ER_DB_CREATE_EXISTS") >= 0) { | ||
@@ -34,0 +34,0 @@ log("Database already exists: " + dbConfig.dbName); |
18
main.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var SequelizeQuery_1 = require("./SequelizeQuery"); | ||
const SequelizeQuery_1 = require("./SequelizeQuery"); | ||
exports.SequelizeQuery = SequelizeQuery_1.SequelizeQuery; | ||
exports.entityQueryFromUrl = SequelizeQuery_1.entityQueryFromUrl; | ||
var SequelizeManager_1 = require("./SequelizeManager"); | ||
exports.urlToEntityQuery = SequelizeQuery_1.urlToEntityQuery; | ||
const SequelizeManager_1 = require("./SequelizeManager"); | ||
exports.SequelizeManager = SequelizeManager_1.SequelizeManager; | ||
var SequelizeSaveHandler_1 = require("./SequelizeSaveHandler"); | ||
const SequelizeSaveHandler_1 = require("./SequelizeSaveHandler"); | ||
exports.SequelizeSaveHandler = SequelizeSaveHandler_1.SequelizeSaveHandler; | ||
var utils = require("./utils"); | ||
const SaveMap_1 = require("./SaveMap"); | ||
exports.SaveMap = SaveMap_1.SaveMap; | ||
const utils = require("./utils"); | ||
exports.utils = utils; | ||
var dbUtils = require("./dbUtils"); | ||
const dbUtils = require("./dbUtils"); | ||
exports.dbUtils = dbUtils; | ||
var breeze_client_1 = require("breeze-client"); | ||
const breeze_client_1 = require("breeze-client"); | ||
exports.breeze = breeze_client_1.breeze; | ||
var Sequelize = SequelizeManager_1.SequelizeManager.Sequelize; | ||
const Sequelize = SequelizeManager_1.SequelizeManager.Sequelize; | ||
exports.Sequelize = Sequelize; | ||
//# sourceMappingURL=main.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var breeze_client_1 = require("breeze-client"); | ||
var sequelize_1 = require("sequelize"); | ||
var _ = require("lodash"); | ||
var utils = require("./utils"); | ||
var log = utils.log; | ||
const breeze_client_1 = require("breeze-client"); | ||
const sequelize_1 = require("sequelize"); | ||
const _ = require("lodash"); | ||
const utils = require("./utils"); | ||
let log = utils.log; | ||
; | ||
// TODO: still need to handle inherited entity types - TPT | ||
/** Maps Breeze metadata to Sequelize Models */ | ||
var MetadataMapper = /** @class */ (function () { | ||
function MetadataMapper(breezeMetadata, sequelize) { | ||
class MetadataMapper { | ||
constructor(breezeMetadata, sequelize) { | ||
this.sequelize = sequelize; | ||
var ms; | ||
let ms; | ||
if (breezeMetadata instanceof breeze_client_1.MetadataStore) { | ||
@@ -26,21 +26,20 @@ ms = breezeMetadata; | ||
/** creates entityTypeSqModelMap and resourceNameSqModelMap */ | ||
MetadataMapper.prototype._createMaps = function () { | ||
var _this = this; | ||
var ms = this.metadataStore; | ||
var allTypes = ms.getEntityTypes(); | ||
var typeMap = _.groupBy(allTypes, function (t) { | ||
_createMaps() { | ||
let ms = this.metadataStore; | ||
let allTypes = ms.getEntityTypes(); | ||
let typeMap = _.groupBy(allTypes, t => { | ||
return t.isComplexType ? "complexType" : "entityType"; | ||
}); | ||
// let complexTypes = typeMap["complexType"]; | ||
var entityTypes = typeMap["entityType"]; | ||
let entityTypes = typeMap["entityType"]; | ||
// map of entityTypeName to sqModel | ||
var entityTypeSqModelMap = this.entityTypeSqModelMap = {}; | ||
let entityTypeSqModelMap = this.entityTypeSqModelMap = {}; | ||
// first create all of the sequelize types with just data properties | ||
entityTypes.forEach(function (entityType) { | ||
var typeConfig = _this.mapToSqModelConfig(entityType); | ||
var options = { | ||
entityTypes.forEach(entityType => { | ||
let typeConfig = this.mapToSqModelConfig(entityType); | ||
let options = { | ||
// NOTE: case sensitivity of the table name may not be the same on some sql databases. | ||
modelName: entityType.shortName, | ||
}; | ||
var sqModel = _this.sequelize.define(entityType.shortName, typeConfig, options); | ||
let sqModel = this.sequelize.define(entityType.shortName, typeConfig, options); | ||
entityTypeSqModelMap[entityType.name] = sqModel; | ||
@@ -51,6 +50,6 @@ }, this); | ||
// map of breeze resourceName to sequelize model | ||
this.resourceNameSqModelMap = _.mapValues(ms._resourceEntityTypeMap, function (value, key) { | ||
this.resourceNameSqModelMap = _.mapValues(ms._resourceEntityTypeMap, (value, key) => { | ||
return entityTypeSqModelMap[value]; | ||
}); | ||
}; | ||
} | ||
// source.fn(target, { foreignKey: }) | ||
@@ -61,11 +60,11 @@ // hasOne - adds a foreign key to target | ||
/** Adds relationships to the Models based on Breeze NavigationProperties */ | ||
MetadataMapper.prototype.createNavProps = function (entityTypes, entityTypeSqModelMap) { | ||
createNavProps(entityTypes, entityTypeSqModelMap) { | ||
// TODO: we only support single column foreignKeys for now. | ||
entityTypes.forEach(function (entityType) { | ||
var navProps = entityType.navigationProperties; | ||
var sqModel = entityTypeSqModelMap[entityType.name]; | ||
navProps.forEach(function (np) { | ||
var npName = np.nameOnServer; | ||
var targetEntityType = np.entityType; | ||
var targetSqModel = entityTypeSqModelMap[targetEntityType.name]; | ||
entityTypes.forEach(entityType => { | ||
let navProps = entityType.navigationProperties; | ||
let sqModel = entityTypeSqModelMap[entityType.name]; | ||
navProps.forEach(np => { | ||
let npName = np.nameOnServer; | ||
let targetEntityType = np.entityType; | ||
let targetSqModel = entityTypeSqModelMap[targetEntityType.name]; | ||
if (np.isScalar) { | ||
@@ -90,5 +89,5 @@ if (np.foreignKeyNamesOnServer.length > 0) { | ||
}); | ||
}; | ||
} | ||
/** Creates a set of Sequelize attributes based on DataProperties */ | ||
MetadataMapper.prototype.mapToSqModelConfig = function (entityOrComplexType) { | ||
mapToSqModelConfig(entityOrComplexType) { | ||
// propConfig looks like | ||
@@ -99,21 +98,20 @@ // { firstProp: { type: Sequelize.XXX, ... }, | ||
// } | ||
var _this = this; | ||
var typeConfig = {}; | ||
entityOrComplexType.dataProperties.forEach(function (dataProperty) { | ||
var propConfig = _this.mapToSqPropConfig(dataProperty); | ||
let typeConfig = {}; | ||
entityOrComplexType.dataProperties.forEach(dataProperty => { | ||
let propConfig = this.mapToSqPropConfig(dataProperty); | ||
_.merge(typeConfig, propConfig); | ||
}); | ||
return typeConfig; | ||
}; | ||
} | ||
/** Creates Sequelize column attributes based on a DataProperty */ | ||
MetadataMapper.prototype.mapToSqPropConfig = function (dataProperty) { | ||
mapToSqPropConfig(dataProperty) { | ||
if (dataProperty.isComplexProperty) { | ||
return this.mapToSqModelConfig(dataProperty.dataType); | ||
} | ||
var propConfig = {}; | ||
var attributes = {}; | ||
let propConfig = {}; | ||
let attributes = {}; | ||
propConfig[dataProperty.nameOnServer] = attributes; | ||
var sqModel = _dataTypeMap[dataProperty.dataType.name]; | ||
let sqModel = _dataTypeMap[dataProperty.dataType.name]; | ||
if (sqModel == null) { | ||
var template = _.template("Unable to map the dataType '${ dataType }' of dataProperty: '${ dataProperty }'"); | ||
let template = _.template("Unable to map the dataType '${ dataType }' of dataProperty: '${ dataProperty }'"); | ||
throw new Error(template({ dataProperty: dataProperty.parentType.shortName + "." + dataProperty.name, dataType: dataProperty.dataType.name })); | ||
@@ -131,3 +129,3 @@ } | ||
if (dataProperty.parentType.autoGeneratedKeyType == breeze_client_1.breeze.AutoGeneratedKeyType.Identity) { | ||
var dt = attributes.type; | ||
let dt = attributes.type; | ||
if (dt.key == "INTEGER" || dt.key == "BIGINT") { | ||
@@ -143,7 +141,6 @@ attributes.autoIncrement = true; | ||
return propConfig; | ||
}; | ||
return MetadataMapper; | ||
}()); | ||
} | ||
} | ||
exports.MetadataMapper = MetadataMapper; | ||
var _dataTypeMap = { | ||
let _dataTypeMap = { | ||
String: sequelize_1.DataTypes.STRING, | ||
@@ -150,0 +147,0 @@ Boolean: sequelize_1.DataTypes.BOOLEAN, |
{ | ||
"name": "breeze-sequelize", | ||
"version": "0.4.1", | ||
"version": "0.5.2", | ||
"description": "Breeze Sequelize server implementation", | ||
@@ -38,7 +38,14 @@ "keywords": [ | ||
"rimraf": "^3.0.1", | ||
"typescript": "^3.7.5" | ||
"typescript": "^3.7.5", | ||
"bluebird": "^3.7.2", | ||
"breeze-client": ">=2.0.4", | ||
"lodash": "^4.17.15", | ||
"sequelize": "^5.21.3" | ||
}, | ||
"scripts": { | ||
"test": "mocha", | ||
"build": "tsc && npm pack", | ||
"tsc": "tsc", | ||
"watch-tsc": "tsc -w", | ||
"build": "tsc && npm pack && npm run install-to-demo", | ||
"install-to-demo": "cd ../test/BreezeExpressDemo && npm install ../../src/breeze-sequelize-0.5.2.tgz", | ||
"clean": "rimraf *.js && rimraf *.map && rimraf types" | ||
@@ -45,0 +52,0 @@ }, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** Maps EntityType names to arrays of EntityInfo */ | ||
var SaveMap = /** @class */ (function () { | ||
function SaveMap(sequelizeSaveHandler) { | ||
class SaveMap { | ||
constructor(sequelizeSaveHandler) { | ||
// make sequelizeSaveHandler non-enumerable so it won't be in Object.keys() | ||
Object.defineProperty(this, "sequelizeSaveHandler", { value: sequelizeSaveHandler }); | ||
} | ||
SaveMap.prototype.getEntityType = function (entityTypeName) { | ||
getEntityType(entityTypeName) { | ||
return this.sequelizeSaveHandler.metadataStore.getEntityType(entityTypeName); | ||
}; | ||
SaveMap.prototype.getEntityInfosOfType = function (entityTypeName) { | ||
var entityType = this.getEntityType(entityTypeName); | ||
} | ||
getEntityInfosOfType(entityTypeName) { | ||
const entityType = this.getEntityType(entityTypeName); | ||
// entityType.name is fully qualified. | ||
return this[entityType.name] || []; | ||
}; | ||
} | ||
/** Add an entity to the map */ | ||
SaveMap.prototype.addEntity = function (entityTypeName, entity, entityState) { | ||
var entityType = this.getEntityType(entityTypeName); | ||
addEntity(entityTypeName, entity, entityState = "Added") { | ||
const entityType = this.getEntityType(entityTypeName); | ||
entityTypeName = entityType.name; // fully qualified now. | ||
var entityInfo = { | ||
const entityInfo = { | ||
entity: entity, entityType: entityType, wasAddedOnServer: true, | ||
entityAspect: { | ||
entityTypeName: entityTypeName, | ||
entityState: entityState || "Added" | ||
entityState: entityState | ||
} | ||
}; | ||
var entityInfoList = this[entityTypeName]; | ||
const entityInfoList = this[entityTypeName]; | ||
if (entityInfoList) { | ||
@@ -36,10 +36,10 @@ entityInfoList.push(entityInfo); | ||
return entityInfo; | ||
}; | ||
} | ||
/** Add an error to the entityErrors collection */ | ||
SaveMap.prototype.addEntityError = function (entityInfo, errorName, errorMessage, propertyName) { | ||
addEntityError(entityInfo, errorName, errorMessage, propertyName) { | ||
if (!this.entityErrors) { | ||
this.entityErrors = []; | ||
} | ||
var entityType = entityInfo.entityType; | ||
var keyValues = entityType.keyProperties.map(function (kp) { | ||
const entityType = entityInfo.entityType; | ||
const keyValues = entityType.keyProperties.map(kp => { | ||
return entityInfo.entity[kp.nameOnServer]; | ||
@@ -54,10 +54,9 @@ }); | ||
}); | ||
}; | ||
} | ||
/** Set the error message to return to the client */ | ||
SaveMap.prototype.setErrorMessage = function (errorMessage) { | ||
setErrorMessage(errorMessage) { | ||
this.errorMessage = errorMessage; | ||
}; | ||
return SaveMap; | ||
}()); | ||
} | ||
} | ||
exports.SaveMap = SaveMap; | ||
//# sourceMappingURL=SaveMap.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var sequelize_1 = require("sequelize"); | ||
var dbUtils_1 = require("./dbUtils"); | ||
var MetadataMapper_1 = require("./MetadataMapper"); | ||
var _ = require("lodash"); | ||
var utils = require("./utils"); | ||
var log = utils.log; | ||
const sequelize_1 = require("sequelize"); | ||
const dbUtils_1 = require("./dbUtils"); | ||
const MetadataMapper_1 = require("./MetadataMapper"); | ||
const _ = require("lodash"); | ||
const utils = require("./utils"); | ||
let log = utils.log; | ||
/** Manages the Sequelize instance for Breeze query and save operations */ | ||
var SequelizeManager = /** @class */ (function () { | ||
function SequelizeManager(dbConfig, sequelizeOptions) { | ||
var defaultOptions = { | ||
class SequelizeManager { | ||
constructor(dbConfig, sequelizeOptions) { | ||
let defaultOptions = { | ||
dialect: "mysql", | ||
@@ -23,3 +23,3 @@ port: 3306, | ||
}; | ||
var define = defaultOptions.define; | ||
let define = defaultOptions.define; | ||
this.sequelizeOptions = _.extend(defaultOptions, sequelizeOptions || {}); | ||
@@ -31,18 +31,18 @@ this.sequelizeOptions.define = _.extend(define, (sequelizeOptions && sequelizeOptions.define) || {}); | ||
/** Connect to the database */ | ||
SequelizeManager.prototype.authenticate = function () { | ||
authenticate() { | ||
// check database connection | ||
return this.sequelize.authenticate().then(function () { | ||
return this.sequelize.authenticate().then(() => { | ||
log('Connection has been established successfully.'); | ||
}).error(function (err) { | ||
}).error(err => { | ||
log('Unable to connect to the database:', err); | ||
throw err; | ||
}); | ||
}; | ||
} | ||
/** Create a new database */ | ||
SequelizeManager.prototype.createDb = function () { | ||
createDb() { | ||
return dbUtils_1.createDb(this.dbConfig, this.sequelizeOptions); | ||
}; | ||
} | ||
/** Convert Breeze metadata to Sequelize models */ | ||
SequelizeManager.prototype.importMetadata = function (breezeMetadata) { | ||
var metadataMapper = new MetadataMapper_1.MetadataMapper(breezeMetadata, this.sequelize); | ||
importMetadata(breezeMetadata) { | ||
let metadataMapper = new MetadataMapper_1.MetadataMapper(breezeMetadata, this.sequelize); | ||
// TODO: should we merge here instead ; i.e. allow multiple imports... | ||
@@ -52,9 +52,8 @@ this.models = this.resourceNameSqModelMap = metadataMapper.resourceNameSqModelMap; | ||
this.metadataStore = metadataMapper.metadataStore; | ||
}; | ||
} | ||
/** Sync the Sequelize model with the database */ | ||
SequelizeManager.prototype.sync = function (shouldCreateDb, sequelizeOpts) { | ||
var _this = this; | ||
sync(shouldCreateDb, sequelizeOpts) { | ||
if (shouldCreateDb) { | ||
return this.createDb().then(function () { | ||
return _this.syncCore(_this.sequelize, sequelizeOpts); | ||
return this.createDb().then(() => { | ||
return this.syncCore(this.sequelize, sequelizeOpts); | ||
}); | ||
@@ -65,18 +64,17 @@ } | ||
} | ||
}; | ||
SequelizeManager.prototype.syncCore = function (sequelize, sequelizeOpts) { | ||
var defaultOptions = { force: true }; | ||
} | ||
syncCore(sequelize, sequelizeOpts) { | ||
let defaultOptions = { force: true }; | ||
sequelizeOpts = _.extend(defaultOptions, sequelizeOpts || {}); | ||
return sequelize.sync(sequelizeOpts).then(function () { | ||
return sequelize.sync(sequelizeOpts).then(() => { | ||
log("schema created"); | ||
return sequelize; | ||
}).catch(function (err) { | ||
}).catch(err => { | ||
console.log("schema creation failed"); | ||
throw err; | ||
}); | ||
}; | ||
SequelizeManager.Sequelize = sequelize_1.Sequelize; | ||
return SequelizeManager; | ||
}()); | ||
} | ||
} | ||
exports.SequelizeManager = SequelizeManager; | ||
SequelizeManager.Sequelize = sequelize_1.Sequelize; | ||
//# sourceMappingURL=SequelizeManager.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var breeze_client_1 = require("breeze-client"); | ||
var _ = require("lodash"); | ||
var sequelize_1 = require("sequelize"); | ||
var urlUtils = require("url"); | ||
var SQVisitor_1 = require("./SQVisitor"); | ||
const breeze_client_1 = require("breeze-client"); | ||
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 | ||
@@ -12,4 +12,4 @@ * @param url - url containing query, e.g. `/orders?{freight:{">":100}}` | ||
*/ | ||
function entityQueryFromUrl(url, resourceName) { | ||
var parsedUrl = urlUtils.parse(url, true); | ||
function urlToEntityQuery(url, resourceName) { | ||
let parsedUrl = urlUtils.parse(url, true); | ||
resourceName = resourceName || parsedUrl.pathname; | ||
@@ -19,6 +19,6 @@ // this is because everything after the '?' is turned into a query object with a single key | ||
// So we want the key and not the value. | ||
var keys = Object.keys(parsedUrl.query); | ||
var jsonQueryString = keys.length ? keys[0] : '{}'; | ||
var jsonQuery = JSON.parse(jsonQueryString); | ||
var entityQuery = new breeze_client_1.EntityQuery(jsonQuery); | ||
let keys = Object.keys(parsedUrl.query); | ||
let jsonQueryString = keys.length ? keys[0] : '{}'; | ||
let jsonQuery = JSON.parse(jsonQueryString); | ||
let entityQuery = new breeze_client_1.EntityQuery(jsonQuery); | ||
entityQuery = entityQuery.from(resourceName).useNameOnServer(true); | ||
@@ -29,8 +29,11 @@ // for debugging | ||
} | ||
exports.entityQueryFromUrl = entityQueryFromUrl; | ||
exports.urlToEntityQuery = urlToEntityQuery; | ||
// legacy support | ||
// export { urlToEntityQuery as entityQueryFromUrl }; | ||
// patch Breeze EntityQuery for server-side use | ||
// TODO make this a method on SequelizeQuery, so we don't have to patch Breeze? | ||
breeze_client_1.EntityQuery['fromUrl'] = entityQueryFromUrl; | ||
// Bad idea because this means we can have two different versions of EntityQuery | ||
breeze_client_1.EntityQuery['fromUrl'] = urlToEntityQuery; | ||
// TODO: still need to add support for fns like toUpper, length etc. | ||
// TODO: still need to add support for any/all | ||
// TODO: still need to add support for some portions of any/all | ||
// config.url: | ||
@@ -41,5 +44,5 @@ // config.pathName: if null - url | ||
/** Converts Breeze queries to Sequelize queries */ | ||
var SequelizeQuery = /** @class */ (function () { | ||
class SequelizeQuery { | ||
/** Create instance for the given EntityQuery, and process the query into Sequelize form */ | ||
function SequelizeQuery(sequelizeManager, serverSideEntityQuery) { | ||
constructor(sequelizeManager, serverSideEntityQuery) { | ||
this.sequelizeManager = sequelizeManager; | ||
@@ -52,14 +55,13 @@ this.metadataStore = sequelizeManager.metadataStore; | ||
/** Execute the current query and return data objects */ | ||
SequelizeQuery.prototype.execute = function (options) { | ||
var _this = this; | ||
return this.executeRaw(options).then(function (r) { | ||
var result = _this._reshapeResults(r); | ||
execute(options) { | ||
return this.executeRaw(options).then(r => { | ||
let result = this._reshapeResults(r); | ||
return Promise.resolve(result); | ||
}); | ||
}; | ||
} | ||
/** Execute the current query and return the Sequelize Models */ | ||
SequelizeQuery.prototype.executeRaw = function (options) { | ||
var self = this; | ||
var model = self.sequelizeManager.resourceNameSqModelMap[self.entityQuery.resourceName]; | ||
var methodName = self.entityQuery.inlineCountEnabled ? "findAndCountAll" : "findAll"; | ||
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 }; | ||
@@ -94,8 +96,8 @@ return (function () { | ||
}); | ||
}; | ||
} | ||
// pass in either a query string or a urlQuery object | ||
// a urlQuery object is what is returned by node's url.parse(aUrl, true).query; | ||
SequelizeQuery.prototype._processQuery = function () { | ||
var entityQuery = this.entityQuery; | ||
var sqQuery = this.sqQuery = {}; | ||
_processQuery() { | ||
let entityQuery = this.entityQuery; | ||
let sqQuery = this.sqQuery = {}; | ||
sqQuery.include = []; | ||
@@ -106,3 +108,3 @@ this._processWhere(); | ||
this._processExpand(); | ||
var section = entityQuery.takeCount; | ||
let section = entityQuery.takeCount; | ||
// not ok to ignore top: 0 | ||
@@ -124,8 +126,8 @@ if (section != null) { | ||
return this.sqQuery; | ||
}; | ||
SequelizeQuery.prototype._processWhere = function () { | ||
var wherePredicate = this.entityQuery.wherePredicate; | ||
} | ||
_processWhere() { | ||
let wherePredicate = this.entityQuery.wherePredicate; | ||
if (wherePredicate == null) | ||
return; | ||
var sqQuery = wherePredicate.visit({ | ||
let sqQuery = wherePredicate.visit({ | ||
entityType: this.entityType, | ||
@@ -141,16 +143,15 @@ toNameOnServer: this.entityQuery.usesNameOnServer, | ||
processAndOr(this.sqQuery); | ||
}; | ||
SequelizeQuery.prototype._processSelect = function () { | ||
var _this = this; | ||
var selectClause = this.entityQuery.selectClause; | ||
var usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
} | ||
_processSelect() { | ||
let selectClause = this.entityQuery.selectClause; | ||
let usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
if (selectClause == null) | ||
return; | ||
// extract any nest paths and move them onto the include | ||
var navPropertyPaths = []; | ||
this.sqQuery.attributes = selectClause.propertyPaths.map(function (pp) { | ||
var props = _this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
var isNavPropertyPath = props[0].isNavigationProperty; | ||
let navPropertyPaths = []; | ||
this.sqQuery.attributes = selectClause.propertyPaths.map(pp => { | ||
let props = this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
let isNavPropertyPath = props[0].isNavigationProperty; | ||
if (isNavPropertyPath) { | ||
_this._addFetchInclude(_this.sqQuery, props, false); | ||
this._addFetchInclude(this.sqQuery, props, false); | ||
} | ||
@@ -160,25 +161,24 @@ if (isNavPropertyPath) | ||
return usesNameOnServer ? pp : _.map(props, "nameOnServer").join("."); | ||
}, this).filter(function (pp) { | ||
}, this).filter(pp => { | ||
return pp != null; | ||
}); | ||
}; | ||
SequelizeQuery.prototype._processOrderBy = function () { | ||
var _this = this; | ||
var orderByClause = this.entityQuery.orderByClause; | ||
var usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
} | ||
_processOrderBy() { | ||
let orderByClause = this.entityQuery.orderByClause; | ||
let usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
if (orderByClause == null) | ||
return; | ||
var orders = this.sqQuery.order = []; | ||
orderByClause.items.forEach(function (item) { | ||
var pp = item.propertyPath; | ||
var props = _this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
var isNavPropertyPath = props[0].isNavigationProperty; | ||
let orders = this.sqQuery.order = []; | ||
orderByClause.items.forEach(item => { | ||
let pp = item.propertyPath; | ||
let props = this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
let isNavPropertyPath = props[0].isNavigationProperty; | ||
if (isNavPropertyPath) { | ||
_this._addInclude(_this.sqQuery, props); | ||
this._addInclude(this.sqQuery, props); | ||
} | ||
var r = []; | ||
let r = []; | ||
orders.push(r); | ||
props.forEach(function (prop) { | ||
props.forEach((prop) => { | ||
if (prop.isNavigationProperty) { | ||
var modelAs = _this._getModelAs(prop); | ||
let modelAs = this._getModelAs(prop); | ||
r.push(modelAs); | ||
@@ -192,17 +192,16 @@ } | ||
} | ||
}, _this); | ||
}, this); | ||
}, this); | ||
}; | ||
SequelizeQuery.prototype._processExpand = function () { | ||
var _this = this; | ||
var expandClause = this.entityQuery.expandClause; | ||
var usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
} | ||
_processExpand() { | ||
let expandClause = this.entityQuery.expandClause; | ||
let usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
if (expandClause == null) | ||
return; | ||
expandClause.propertyPaths.forEach(function (pp) { | ||
var props = _this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
_this._addFetchInclude(_this.sqQuery, props, true); | ||
expandClause.propertyPaths.forEach(pp => { | ||
let props = this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
this._addFetchInclude(this.sqQuery, props, true); | ||
}, this); | ||
}; | ||
SequelizeQuery.prototype._reshapeResults = function (sqResults) { | ||
} | ||
_reshapeResults(sqResults) { | ||
// -) nested projections need to be promoted up to the top level | ||
@@ -213,3 +212,2 @@ // because sequelize will have them appearing on nested objects. | ||
// -) inlineCount handling | ||
var _this = this; | ||
this._nextId = 1; | ||
@@ -221,3 +219,3 @@ this._keyMap = {}; | ||
} | ||
var inlineCount; | ||
let inlineCount; | ||
if (this.entityQuery.inlineCountEnabled && sqResults.count) { | ||
@@ -227,9 +225,9 @@ inlineCount = sqResults.count; | ||
} | ||
var expandClause = this.entityQuery.expandClause; | ||
var usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
var expandPaths = []; | ||
let expandClause = this.entityQuery.expandClause; | ||
let usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
let expandPaths = []; | ||
if (expandClause) { | ||
// each expand path consist of an array of expand props. | ||
expandPaths = expandClause.propertyPaths.map(function (pp) { | ||
return _this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
expandPaths = expandClause.propertyPaths.map(pp => { | ||
return this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
}, this); | ||
@@ -241,9 +239,9 @@ } | ||
} | ||
var results = sqResults.map(function (sqResult) { | ||
var result = _this._createResult(sqResult, _this.entityType, expandClause != null); | ||
let results = sqResults.map(sqResult => { | ||
let result = this._createResult(sqResult, this.entityType, expandClause != null); | ||
// each expandPath is a collection of expandProps | ||
// if (!result.$ref) { | ||
expandPaths.forEach(function (expandProps) { | ||
_this._populateExpand(result, sqResult, expandProps); | ||
}, _this); | ||
expandPaths.forEach(expandProps => { | ||
this._populateExpand(result, sqResult, expandProps); | ||
}, this); | ||
// } | ||
@@ -258,6 +256,5 @@ return result; | ||
} | ||
}; | ||
SequelizeQuery.prototype._reshapeSelectResults = function (sqResults) { | ||
var _this = this; | ||
var inlineCount; | ||
} | ||
_reshapeSelectResults(sqResults) { | ||
let inlineCount; | ||
if (this.entityQuery.inlineCountEnabled) { | ||
@@ -267,14 +264,14 @@ inlineCount = sqResults.count; | ||
} | ||
var propertyPaths = this.entityQuery.selectClause.propertyPaths; | ||
var usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
var results = sqResults.map(function (sqResult) { | ||
let propertyPaths = this.entityQuery.selectClause.propertyPaths; | ||
let usesNameOnServer = this.entityQuery.usesNameOnServer; | ||
let results = sqResults.map(sqResult => { | ||
// start with the sqResult and then promote nested properties up to the top level | ||
// while removing nested path. | ||
var result = sqResult.dataValues; | ||
var parent; | ||
propertyPaths.forEach(function (pp) { | ||
let result = sqResult.dataValues; | ||
let parent; | ||
propertyPaths.forEach(pp => { | ||
parent = sqResult; | ||
var props = _this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
var nextProp = props[0]; | ||
var remainingProps = props.slice(0); | ||
let props = this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true); | ||
let nextProp = props[0]; | ||
let remainingProps = props.slice(0); | ||
while (remainingProps.length > 1 && nextProp.isNavigationProperty) { | ||
@@ -285,3 +282,3 @@ parent = parent[nextProp.nameOnServer]; | ||
} | ||
var val = parent && parent[nextProp.nameOnServer]; | ||
let val = parent && parent[nextProp.nameOnServer]; | ||
// if last property in path is a nav prop then we need to wrap the results | ||
@@ -291,8 +288,8 @@ // as either an entity or entities. | ||
if (nextProp.isScalar) { | ||
val = _this._createResult(val, nextProp.entityType, true); | ||
val = this._createResult(val, nextProp.entityType, true); | ||
} | ||
else { | ||
val = val.map(function (v) { | ||
return _this._createResult(v, nextProp.entityType, true); | ||
}, _this); | ||
val = val.map((v) => { | ||
return this._createResult(v, nextProp.entityType, true); | ||
}, this); | ||
} | ||
@@ -305,3 +302,3 @@ } | ||
result[pp] = val; | ||
}, _this); | ||
}, this); | ||
return result; | ||
@@ -315,11 +312,10 @@ }, this); | ||
} | ||
return results; | ||
}; | ||
SequelizeQuery.prototype._createResult = function (sqResult, entityType, checkCache) { | ||
} | ||
_createResult(sqResult, entityType, checkCache) { | ||
if (!sqResult) | ||
return null; | ||
var result = sqResult.dataValues; | ||
let result = sqResult.dataValues; | ||
if (checkCache) { | ||
var key = getKey(sqResult, entityType); | ||
var cachedItem = this._keyMap[key]; | ||
let key = getKey(sqResult, entityType); | ||
let cachedItem = this._keyMap[key]; | ||
if (cachedItem) { | ||
@@ -336,6 +332,6 @@ return { $ref: cachedItem.$id }; | ||
result.$type = entityType.name; | ||
var nps = entityType.navigationProperties; | ||
let nps = entityType.navigationProperties; | ||
// first remove all nav props | ||
nps.forEach(function (np) { | ||
var navValue = sqResult[np.nameOnServer]; | ||
nps.forEach(np => { | ||
let navValue = sqResult[np.nameOnServer]; | ||
if (navValue) { | ||
@@ -346,5 +342,4 @@ result[np.nameOnServer] = undefined; | ||
return result; | ||
}; | ||
SequelizeQuery.prototype._populateExpand = function (result, sqResult, expandProps) { | ||
var _this = this; | ||
} | ||
_populateExpand(result, sqResult, expandProps) { | ||
if (result.$ref) { | ||
@@ -357,12 +352,12 @@ result = this._refMap[result.$ref]; | ||
// each expand path consist of an array of expand props. | ||
var npName = expandProps[0].nameOnServer; | ||
var nextResult = result[npName]; | ||
var nextEntityType = expandProps[0].entityType; | ||
var nextSqResult = sqResult[npName]; | ||
let npName = expandProps[0].nameOnServer; | ||
let nextResult = result[npName]; | ||
let nextEntityType = expandProps[0].entityType; | ||
let nextSqResult = sqResult[npName]; | ||
// if it doesn't already exist then create it | ||
if (nextResult == null) { | ||
if (_.isArray(nextSqResult)) { | ||
nextResult = nextSqResult.map(function (nextSqr) { | ||
return _this._createResult(nextSqr, nextEntityType, true); | ||
}, this).filter(function (r) { | ||
nextResult = nextSqResult.map(nextSqr => { | ||
return this._createResult(nextSqr, nextEntityType, true); | ||
}, this).filter(r => { | ||
return r != null; | ||
@@ -377,4 +372,4 @@ }); | ||
if (_.isArray(nextSqResult)) { | ||
nextSqResult.forEach(function (nextSqr, ix) { | ||
_this._populateExpand(nextResult[ix], nextSqr, expandProps.slice(1)); | ||
nextSqResult.forEach((nextSqr, ix) => { | ||
this._populateExpand(nextResult[ix], nextSqr, expandProps.slice(1)); | ||
}, this); | ||
@@ -387,6 +382,6 @@ } | ||
} | ||
}; | ||
} | ||
// Add an include for a where or order by clause. Returns last include in the props chain. | ||
SequelizeQuery.prototype._addInclude = function (parent, props) { | ||
var include = this._getIncludeFor(parent, props[0]); | ||
_addInclude(parent, props) { | ||
let include = this._getIncludeFor(parent, props[0]); | ||
// empty attributes array tells sequelize not to retrieve the entity data | ||
@@ -402,5 +397,5 @@ if (!include['$disallowAttributes']) | ||
return include; | ||
}; | ||
} | ||
// Add an include for a select or expand clause. Returns last include in the props chain. | ||
SequelizeQuery.prototype._addFetchInclude = function (parent, props, isExpand) { | ||
_addFetchInclude(parent, props, isExpand) { | ||
// $disallowAttributes code is used to insure two things | ||
@@ -411,3 +406,3 @@ // 1) if a navigation property is declared as the last prop of a select or expand expression | ||
// violate #1 above. | ||
var include = this._getIncludeFor(parent, props[0]); | ||
let include = this._getIncludeFor(parent, props[0]); | ||
props = props.slice(1); | ||
@@ -447,9 +442,9 @@ if (props.length > 0) { | ||
return include; | ||
}; | ||
} | ||
// Find or create an include object, and attach it to parent | ||
SequelizeQuery.prototype._getIncludeFor = function (parent, prop) { | ||
var sqModel = this.sequelizeManager.entityTypeSqModelMap[prop.entityType.name]; | ||
var includes = parent.include = parent.include || []; | ||
var findInclude = { model: sqModel, as: prop.nameOnServer }; | ||
var include = _.find(includes, findInclude); | ||
_getIncludeFor(parent, prop) { | ||
let sqModel = this.sequelizeManager.entityTypeSqModelMap[prop.entityType.name]; | ||
let includes = parent.include = parent.include || []; | ||
let findInclude = { model: sqModel, as: prop.nameOnServer }; | ||
let include = _.find(includes, findInclude); | ||
if (!include) { | ||
@@ -460,12 +455,11 @@ includes.push(findInclude); | ||
return include; | ||
}; | ||
SequelizeQuery.prototype._getModelAs = function (prop) { | ||
var sqModel = this.sequelizeManager.entityTypeSqModelMap[prop.entityType.name]; | ||
} | ||
_getModelAs(prop) { | ||
let sqModel = this.sequelizeManager.entityTypeSqModelMap[prop.entityType.name]; | ||
return { model: sqModel, as: prop.nameOnServer }; | ||
}; | ||
return SequelizeQuery; | ||
}()); | ||
} | ||
} | ||
exports.SequelizeQuery = SequelizeQuery; | ||
function getKey(sqResult, entityType) { | ||
var key = entityType.keyProperties.map(function (kp) { | ||
let key = entityType.keyProperties.map(function (kp) { | ||
return sqResult[kp.nameOnServer]; | ||
@@ -489,6 +483,6 @@ }).join("::") + "^" + entityType.name; | ||
console.log("processAndOrClause", where); | ||
var ands = (where[sequelize_1.Op.and] || where['and']); | ||
var ors = (where[sequelize_1.Op.or] || where['or']); | ||
let ands = (where[sequelize_1.Op.and] || where['and']); | ||
let ors = (where[sequelize_1.Op.or] || where['or']); | ||
if (ands) { | ||
var clauses = ands.map(function (clause) { | ||
let clauses = ands.map(function (clause) { | ||
return processAndOrClause(clause); | ||
@@ -500,3 +494,3 @@ }); | ||
else if (ors) { | ||
var clauses = ors.map(function (clause) { | ||
let clauses = ors.map(function (clause) { | ||
return processAndOrClause(clause); | ||
@@ -503,0 +497,0 @@ }); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var bluebird_1 = require("bluebird"); | ||
var _ = require("lodash"); | ||
var SaveMap_1 = require("./SaveMap"); | ||
var toposort = require("toposort"); | ||
const bluebird_1 = require("bluebird"); | ||
const _ = require("lodash"); | ||
const SaveMap_1 = require("./SaveMap"); | ||
let toposort = require("toposort"); | ||
/** Handles saving entities from Breeze SaveChanges requests */ | ||
var SequelizeSaveHandler = /** @class */ (function () { | ||
class SequelizeSaveHandler { | ||
/** Create an instance for the given save request */ | ||
function SequelizeSaveHandler(sequelizeManager, req) { | ||
var reqBody = req.body; | ||
constructor(sequelizeManager, req) { | ||
let reqBody = req.body; | ||
this.sequelizeManager = sequelizeManager; | ||
@@ -22,15 +22,14 @@ this.metadataStore = sequelizeManager.metadataStore; | ||
/** Save the entities in the save request, returning either the saved entities or an error collection */ | ||
SequelizeSaveHandler.prototype.save = function () { | ||
var _this = this; | ||
var beforeSaveEntity = (this.beforeSaveEntity || noopBeforeSaveEntity).bind(this); | ||
var entityTypeMap = {}; | ||
var entityInfos = this.entitiesFromClient.map(function (entity) { | ||
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. | ||
var entityAspect = entity.entityAspect; | ||
var entityTypeName = entityAspect.entityTypeName; | ||
var entityType = entityTypeMap[entityTypeName]; | ||
let entityAspect = entity.entityAspect; | ||
let entityTypeName = entityAspect.entityTypeName; | ||
let entityType = entityTypeMap[entityTypeName]; | ||
if (!entityType) { | ||
entityType = _this.metadataStore.getEntityType(entityTypeName); | ||
entityType = this.metadataStore.getEntityType(entityTypeName); | ||
if (entityType) { | ||
@@ -43,4 +42,4 @@ entityTypeMap[entityTypeName] = entityType; | ||
} | ||
var unmapped = entity.__unmapped; | ||
var ei = { entity: entity, entityType: entityType, entityAspect: entityAspect, unmapped: unmapped }; | ||
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. | ||
@@ -51,3 +50,3 @@ delete entity.entityAspect; | ||
// create the saveMap (entities to be saved) grouped by entityType | ||
var saveMapData = _.groupBy(entityInfos, function (entityInfo) { | ||
let saveMapData = _.groupBy(entityInfos, entityInfo => { | ||
// _.groupBy will bundle all undefined returns together. | ||
@@ -61,17 +60,16 @@ if (beforeSaveEntity(entityInfo)) { | ||
// want to have SaveMap functions available | ||
var saveMap = _.extend(new SaveMap_1.SaveMap(this), saveMapData); | ||
let saveMap = _.extend(new SaveMap_1.SaveMap(this), saveMapData); | ||
return this._saveWithTransaction(saveMap); | ||
}; | ||
SequelizeSaveHandler.prototype._saveWithTransaction = function (saveMap) { | ||
var _this = this; | ||
var sequelize = this.sequelizeManager.sequelize; | ||
return sequelize.transaction().then(function (trx) { | ||
} | ||
_saveWithTransaction(saveMap) { | ||
let sequelize = this.sequelizeManager.sequelize; | ||
return sequelize.transaction().then(trx => { | ||
// this.transaction = trx; | ||
var beforeSaveEntities = (_this.beforeSaveEntities || noopBeforeSaveEntities).bind(_this); | ||
let beforeSaveEntities = (this.beforeSaveEntities || noopBeforeSaveEntities).bind(this); | ||
// beforeSaveEntities will either return nothing or a promise. | ||
var nextPromise = bluebird_1.Promise.resolve(beforeSaveEntities(saveMap, trx)); | ||
let nextPromise = bluebird_1.Promise.resolve(beforeSaveEntities(saveMap, trx)); | ||
// saveCore returns either a list of entities or an object with an errors property. | ||
return nextPromise.then(function (sm) { | ||
return _this._saveCore(saveMap, trx); | ||
}).then(function (r) { | ||
return nextPromise.then(sm => { | ||
return this._saveCore(saveMap, trx); | ||
}).then((r) => { | ||
if (r.errors) { | ||
@@ -83,5 +81,5 @@ trx.rollback(); | ||
trx.commit(); | ||
return { entities: r, keyMappings: _this._keyMappings }; | ||
return { entities: r, keyMappings: this._keyMappings }; | ||
} | ||
}).catch(function (e) { | ||
}).catch((e) => { | ||
trx.rollback(); | ||
@@ -91,15 +89,14 @@ throw e; | ||
}); | ||
}; | ||
} | ||
; | ||
SequelizeSaveHandler.prototype._saveCore = function (saveMap, transaction) { | ||
var _this = this; | ||
_saveCore(saveMap, transaction) { | ||
if (saveMap.entityErrors || saveMap.errorMessage) { | ||
return bluebird_1.Promise.resolve({ errors: saveMap.entityErrors || [], message: saveMap.errorMessage }); | ||
} | ||
var entityTypes = _.keys(saveMap).map(function (entityTypeName) { | ||
let entityTypes = _.keys(saveMap).map((entityTypeName) => { | ||
// guaranteed to succeed because these have all been looked up earlier. | ||
return _this.metadataStore.getEntityType(entityTypeName); | ||
return this.metadataStore.getEntityType(entityTypeName); | ||
}, this); | ||
var sortedEntityTypes = toposortEntityTypes(entityTypes); | ||
var entityGroups = sortedEntityTypes.map(function (entityType) { | ||
let sortedEntityTypes = toposortEntityTypes(entityTypes); | ||
let entityGroups = sortedEntityTypes.map((entityType) => { | ||
return { entityType: entityType, entityInfos: saveMap[entityType.name] }; | ||
@@ -111,10 +108,10 @@ }); | ||
// children have been moved somewhere else. | ||
return bluebird_1.Promise.reduce(entityGroups, function (savedEntities, entityGroup) { | ||
return _this._processEntityGroup(entityGroup, transaction, false).then(function (entities) { | ||
return bluebird_1.Promise.reduce(entityGroups, (savedEntities, entityGroup) => { | ||
return this._processEntityGroup(entityGroup, transaction, false).then(entities => { | ||
Array.prototype.push.apply(savedEntities, entities); | ||
return savedEntities; | ||
}); | ||
}, []).then(function (entitiesHandledSoFar) { | ||
return bluebird_1.Promise.reduce(entityGroups.reverse(), function (savedEntities, entityGroup) { | ||
return _this._processEntityGroup(entityGroup, transaction, true).then(function (entities) { | ||
}, []).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); | ||
@@ -125,11 +122,10 @@ return savedEntities; | ||
}); | ||
}; | ||
SequelizeSaveHandler.prototype._processEntityGroup = function (entityGroup, transaction, processDeleted) { | ||
var _this = this; | ||
var entityType = entityGroup.entityType; | ||
var entityInfos = entityGroup.entityInfos.filter(function (entityInfo) { | ||
var isDeleted = entityInfo.entityAspect.entityState == "Deleted"; | ||
} | ||
_processEntityGroup(entityGroup, transaction, processDeleted) { | ||
let entityType = entityGroup.entityType; | ||
let entityInfos = entityGroup.entityInfos.filter(entityInfo => { | ||
let isDeleted = entityInfo.entityAspect.entityState == "Deleted"; | ||
return processDeleted ? isDeleted : !isDeleted; | ||
}); | ||
var sqModel = this.sequelizeManager.entityTypeSqModelMap[entityType.name]; | ||
let sqModel = this.sequelizeManager.entityTypeSqModelMap[entityType.name]; | ||
entityInfos = toposortEntityInfos(entityType, entityInfos); | ||
@@ -139,6 +135,6 @@ if (processDeleted) { | ||
} | ||
return bluebird_1.Promise.reduce(entityInfos, function (savedEntities, entityInfo) { | ||
return bluebird_1.Promise.reduce(entityInfos, (savedEntities, entityInfo) => { | ||
// function returns a promise for this entity | ||
// and updates the results array. | ||
return _this._saveEntityAsync(entityInfo, sqModel, transaction).then(function (savedEntity) { | ||
return this._saveEntityAsync(entityInfo, sqModel, transaction).then(savedEntity => { | ||
savedEntities.push(savedEntity); | ||
@@ -148,13 +144,12 @@ return savedEntities; | ||
}, []); | ||
}; | ||
} | ||
; | ||
SequelizeSaveHandler.prototype._saveEntityAsync = function (entityInfo, sqModel, transaction) { | ||
_saveEntityAsync(entityInfo, sqModel, transaction) { | ||
// function returns a promise for this entity | ||
// and updates the results array. | ||
var _this = this; | ||
// not a "real" entityAspect - just the salient pieces sent from the client. | ||
var entity = entityInfo.entity; | ||
var entityAspect = entityInfo.entityAspect; | ||
var entityType = entityInfo.entityType; | ||
var entityTypeName = entityType.name; | ||
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. | ||
@@ -165,9 +160,9 @@ entityAspect.entity = entity; | ||
this._coerceData(entity, entityType); | ||
var keyProperties = entityType.keyProperties; | ||
var firstKeyPropName = keyProperties[0].nameOnServer; | ||
var entityState = entityAspect.entityState; | ||
var trxOptions = { transaction: transaction }; | ||
var promise; | ||
let keyProperties = entityType.keyProperties; | ||
let firstKeyPropName = keyProperties[0].nameOnServer; | ||
let entityState = entityAspect.entityState; | ||
let trxOptions = { transaction: transaction }; | ||
let promise; | ||
if (entityState === "Added") { | ||
var keyMapping_1 = null; | ||
let keyMapping = null; | ||
// NOTE: there are two instances of autoGeneratedKeyType available | ||
@@ -177,7 +172,7 @@ // one on entityType which is part of the metadata and a second | ||
// The one on the entityAspect "overrides" the one on the entityType. | ||
var autoGeneratedKey = entityAspect.autoGeneratedKey; | ||
var autoGeneratedKeyType = autoGeneratedKey && autoGeneratedKey.autoGeneratedKeyType; | ||
var tempKeyValue_1 = entity[firstKeyPropName]; | ||
let autoGeneratedKey = entityAspect.autoGeneratedKey; | ||
let autoGeneratedKeyType = autoGeneratedKey && autoGeneratedKey.autoGeneratedKeyType; | ||
let tempKeyValue = entity[firstKeyPropName]; | ||
if (autoGeneratedKeyType && autoGeneratedKeyType !== "None") { | ||
var realKeyValue_1; | ||
let realKeyValue; | ||
if (autoGeneratedKeyType == "KeyGenerator") { | ||
@@ -187,17 +182,17 @@ if (this.keyGenerator == null) { | ||
} | ||
promise = this.keyGenerator.getNextId(keyProperties[0]).then(function (nextId) { | ||
realKeyValue_1 = nextId; | ||
entity[firstKeyPropName] = realKeyValue_1; | ||
promise = this.keyGenerator.getNextId(keyProperties[0]).then((nextId) => { | ||
realKeyValue = nextId; | ||
entity[firstKeyPropName] = realKeyValue; | ||
}); | ||
} | ||
else if (autoGeneratedKeyType == "Identity") { | ||
var keyDataTypeName = keyProperties[0].dataType.name; | ||
let keyDataTypeName = keyProperties[0].dataType.name; | ||
if (keyDataTypeName === "Guid") { | ||
// handled here instead of one the db server. | ||
realKeyValue_1 = createGuid(); | ||
entity[firstKeyPropName] = realKeyValue_1; | ||
realKeyValue = createGuid(); | ||
entity[firstKeyPropName] = realKeyValue; | ||
} | ||
else { | ||
// realValue will be set during 'create' promise resolution below | ||
realKeyValue_1 = null; | ||
realKeyValue = null; | ||
// value will be set by server's autoincrement logic | ||
@@ -208,6 +203,6 @@ delete entity[firstKeyPropName]; | ||
promise = promise || bluebird_1.Promise.resolve(null); | ||
promise = promise.then(function () { | ||
promise = promise.then(() => { | ||
// tempKeyValue will be undefined in entity was created on the server | ||
if (tempKeyValue_1 != undefined) { | ||
keyMapping_1 = { entityTypeName: entityTypeName, tempValue: tempKeyValue_1, realValue: realKeyValue_1 }; | ||
if (tempKeyValue != undefined) { | ||
keyMapping = { entityTypeName: entityTypeName, tempValue: tempKeyValue, realValue: realKeyValue }; | ||
} | ||
@@ -217,13 +212,13 @@ }); | ||
promise = promise || bluebird_1.Promise.resolve(null); | ||
return promise.then(function () { | ||
return sqModel.create(entity, { transaction: transaction }).then(function (savedEntity) { | ||
if (keyMapping_1) { | ||
if (keyMapping_1.realValue === null) { | ||
keyMapping_1.realValue = savedEntity[firstKeyPropName]; | ||
return promise.then(() => { | ||
return sqModel.create(entity, { transaction: transaction }).then((savedEntity) => { | ||
if (keyMapping) { | ||
if (keyMapping.realValue === null) { | ||
keyMapping.realValue = savedEntity[firstKeyPropName]; | ||
} | ||
var tempKeyString = buildKeyString(entityType, tempKeyValue_1); | ||
_this._fkFixupMap[tempKeyString] = keyMapping_1.realValue; | ||
_this._keyMappings.push(keyMapping_1); | ||
let tempKeyString = buildKeyString(entityType, tempKeyValue); | ||
this._fkFixupMap[tempKeyString] = keyMapping.realValue; | ||
this._keyMappings.push(keyMapping); | ||
} | ||
return _this._addToResults(savedEntity.dataValues, entityTypeName); | ||
return this._addToResults(savedEntity.dataValues, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
@@ -233,32 +228,32 @@ }); | ||
else if (entityState === "Modified") { | ||
var whereHash_1 = {}; | ||
keyProperties.forEach(function (kp) { | ||
whereHash_1[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
let whereHash = {}; | ||
keyProperties.forEach(kp => { | ||
whereHash[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
}); | ||
if (entityType.concurrencyProperties && entityType.concurrencyProperties.length > 0) { | ||
entityType.concurrencyProperties.forEach(function (cp) { | ||
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_1[cp.nameOnServer] = entity[cp.nameOnServer]; | ||
whereHash[cp.nameOnServer] = entity[cp.nameOnServer]; | ||
else | ||
whereHash_1[cp.nameOnServer] = entityAspect.originalValuesMap[cp.nameOnServer]; | ||
whereHash[cp.nameOnServer] = entityAspect.originalValuesMap[cp.nameOnServer]; | ||
}); | ||
} | ||
var setHash_1; | ||
let setHash; | ||
if (entityInfo.forceUpdate) { | ||
setHash_1 = _.clone(entity); | ||
setHash = _.clone(entity); | ||
// remove fields that we don't want to 'set' | ||
delete setHash_1.entityAspect; | ||
delete setHash.entityAspect; | ||
// TODO: should we also remove keyProps here... | ||
} | ||
else { | ||
setHash_1 = {}; | ||
var ovm = entityAspect.originalValuesMap; | ||
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(function (k) { | ||
Object.keys(ovm).forEach(k => { | ||
// if k is one of the entityKeys do no allow this | ||
var isKeyPropName = keyProperties.some(function (kp) { | ||
let isKeyPropName = keyProperties.some(kp => { | ||
return kp.nameOnServer == k; | ||
@@ -269,3 +264,3 @@ }); | ||
} | ||
setHash_1[k] = entity[k]; | ||
setHash[k] = entity[k]; | ||
}); | ||
@@ -275,9 +270,9 @@ } | ||
// this can happen if setModified is called without any properties being changed. | ||
if (_.isEmpty(setHash_1)) { | ||
if (_.isEmpty(setHash)) { | ||
return bluebird_1.Promise.resolve(this._addToResults(entity, entityTypeName)); | ||
} | ||
return sqModel.update(setHash_1, { where: whereHash_1, transaction: transaction }).then(function (infoArray) { | ||
var itemsSaved = infoArray[0]; | ||
return sqModel.update(setHash, { where: whereHash, transaction: transaction }).then(infoArray => { | ||
let itemsSaved = infoArray[0]; | ||
if (itemsSaved != 1) { | ||
var err = new Error("unable to update entity - concurrency violation"); | ||
let err = new Error("unable to update entity - concurrency violation"); | ||
err.entity = entity; | ||
@@ -289,28 +284,28 @@ err.entityState = entityState; | ||
// we are just returning the original entity here. | ||
return _this._addToResults(entity, entityTypeName); | ||
return this._addToResults(entity, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
} | ||
else if (entityState = "Deleted") { | ||
var whereHash_2 = {}; | ||
keyProperties.forEach(function (kp) { | ||
whereHash_2[kp.nameOnServer] = entity[kp.nameOnServer]; | ||
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_2, limit: 1, transaction: transaction }).then(function () { | ||
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); | ||
return this._addToResults(entity, entityTypeName); | ||
}).catch(handleItemSaveError(entity, entityState)); | ||
} | ||
}; | ||
SequelizeSaveHandler.prototype._addToResults = function (entity, entityTypeName) { | ||
} | ||
_addToResults(entity, entityTypeName) { | ||
entity.$type = entityTypeName; | ||
entity.entityAspect = undefined; | ||
this._savedEntities.push(entity); | ||
return entity; | ||
}; | ||
SequelizeSaveHandler.prototype._coerceData = function (entity, entityType) { | ||
var _this = this; | ||
entityType.dataProperties.forEach(function (dp) { | ||
var val = entity[dp.nameOnServer]; | ||
} | ||
_coerceData(entity, entityType) { | ||
entityType.dataProperties.forEach(dp => { | ||
let val = entity[dp.nameOnServer]; | ||
if (val != null) { | ||
@@ -320,4 +315,4 @@ if (dp.relatedNavigationProperty != null) { | ||
// check if there is a fixed up value. | ||
var key = buildKeyString(dp.relatedNavigationProperty.entityType, val); | ||
var newVal = _this._fkFixupMap[key]; | ||
let key = buildKeyString(dp.relatedNavigationProperty.entityType, val); | ||
let newVal = this._fkFixupMap[key]; | ||
if (newVal) { | ||
@@ -327,3 +322,3 @@ entity[dp.nameOnServer] = newVal; | ||
} | ||
var dtName = dp.dataType.name; | ||
let dtName = dp.dataType.name; | ||
if (dtName === "DateTime" || dtName === "DateTimeOffset") { | ||
@@ -340,5 +335,4 @@ entity[dp.nameOnServer] = new Date(Date.parse(val)); | ||
}); | ||
}; | ||
return SequelizeSaveHandler; | ||
}()); | ||
} | ||
} | ||
exports.SequelizeSaveHandler = SequelizeSaveHandler; | ||
@@ -353,7 +347,7 @@ function noopBeforeSaveEntities(saveMap, trx) { | ||
function toposortEntityTypes(entityTypes) { | ||
var edges = []; | ||
entityTypes.forEach(function (et) { | ||
et.foreignKeyProperties.forEach(function (fkp) { | ||
let edges = []; | ||
entityTypes.forEach(et => { | ||
et.foreignKeyProperties.forEach(fkp => { | ||
if (fkp.relatedNavigationProperty) { | ||
var dependsOnType = fkp.relatedNavigationProperty.entityType; | ||
let dependsOnType = fkp.relatedNavigationProperty.entityType; | ||
if (et != dependsOnType) { | ||
@@ -368,7 +362,7 @@ edges.push([et, dependsOnType]); | ||
// so use this instead. | ||
var allSortedTypes = toposort(edges).reverse(); | ||
let allSortedTypes = toposort(edges).reverse(); | ||
allSortedTypes.forEach(function (st, ix) { | ||
st.index = ix; | ||
}); | ||
var sortedEntityTypes = entityTypes.sort(function (a, b) { | ||
let sortedEntityTypes = entityTypes.sort(function (a, b) { | ||
return a.index - b.index; | ||
@@ -380,13 +374,13 @@ }); | ||
function toposortEntityInfos(entityType, entityInfos) { | ||
var edges = []; | ||
var selfReferenceNavProp = _.find(entityType.navigationProperties, function (navProp) { return navProp.entityType === entityType; }); | ||
let edges = []; | ||
let selfReferenceNavProp = _.find(entityType.navigationProperties, navProp => navProp.entityType === entityType); | ||
if (!selfReferenceNavProp || !selfReferenceNavProp.relatedDataProperties) { | ||
return entityInfos; | ||
} | ||
var fkDataProp = selfReferenceNavProp.relatedDataProperties[0].name; | ||
var keyProp = entityType.keyProperties[0].name; | ||
let fkDataProp = selfReferenceNavProp.relatedDataProperties[0].name; | ||
let keyProp = entityType.keyProperties[0].name; | ||
entityInfos.forEach(function (entityInfo) { | ||
var dependsOn = entityInfo.entity[fkDataProp]; | ||
let dependsOn = entityInfo.entity[fkDataProp]; | ||
if (dependsOn) { | ||
var dependsOnInfo = _.find(entityInfos, function (x) { return x.entity[keyProp] === dependsOn && x.entity !== entityInfo.entity; }); // avoid referencing the same object | ||
let dependsOnInfo = _.find(entityInfos, x => x.entity[keyProp] === dependsOn && x.entity !== entityInfo.entity); // avoid referencing the same object | ||
if (dependsOnInfo) | ||
@@ -399,7 +393,7 @@ edges.push([entityInfo, dependsOnInfo]); | ||
} | ||
var allSortedEntityInfos = toposort(edges).reverse(); | ||
let allSortedEntityInfos = toposort(edges).reverse(); | ||
allSortedEntityInfos.forEach(function (st, ix) { | ||
st.__index = ix; | ||
}); | ||
var sortedEntityInfos = entityInfos.sort(function (a, b) { | ||
let sortedEntityInfos = entityInfos.sort(function (a, b) { | ||
return a.__index - b.__index; | ||
@@ -415,3 +409,3 @@ }); | ||
err = typeof (err) == 'string' ? new Error(err) : err; | ||
var detailedMsg = (err.name ? "error name: " + err.name : "") + (err.sql ? " sql: " + err.sql : ""); | ||
let detailedMsg = (err.name ? "error name: " + err.name : "") + (err.sql ? " sql: " + err.sql : ""); | ||
err.message = err.message ? err.message + ". " + detailedMsg : detailedMsg; | ||
@@ -425,3 +419,3 @@ err.entity = entity; | ||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | ||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | ||
let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | ||
return v.toString(16); | ||
@@ -428,0 +422,0 @@ }); |
190
SQVisitor.js
"use strict"; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var _ = require("lodash"); | ||
var sequelize_1 = require("sequelize"); | ||
const _ = require("lodash"); | ||
const sequelize_1 = require("sequelize"); | ||
/** Visit the nodes in a Breeze query, converting it to a Sequelize query */ | ||
var toSQVisitor = (function () { | ||
var visitor = { | ||
const toSQVisitor = (function () { | ||
let visitor = { | ||
passthruPredicate: function () { | ||
@@ -13,3 +12,3 @@ return this.value; | ||
unaryPredicate: function (context) { | ||
var predSq = this.pred.visit(context); | ||
let predSq = this.pred.visit(context); | ||
if (this.op.key !== "not") { | ||
@@ -25,8 +24,7 @@ throw new Error("Not yet implemented: Unary operation: " + this.op.key + " pred: " + JSON.stringify(this.pred)); | ||
binaryPredicate: function (context) { | ||
var _a, _b, _c, _d, _e, _f; | ||
var result = {}; | ||
var op = this.op.key; | ||
let result = {}; | ||
let op = this.op.key; | ||
// TODO: right now only handling case where e1 : PropExpr and e2 : LitExpr | PropExpr | ||
// not yet handled: e1: FnExpr | e2: FnExpr | ||
var where, p1Value, p2Value; | ||
let where, p1Value, p2Value; | ||
if (this.expr1.visitorMethodName === "propExpr") { | ||
@@ -42,4 +40,4 @@ p1Value = processPropExpr(this.expr1, context, result); | ||
} | ||
var crit; | ||
var like = _boolOpMap.like.sequelizeOp; | ||
let crit; | ||
let like = _boolOpMap.like.sequelizeOp; | ||
if (this.expr2.visitorMethodName === "litExpr") { | ||
@@ -52,13 +50,13 @@ p2Value = this.expr2.value; | ||
else if (op == "startswith") { | ||
crit = (_a = {}, _a[like] = p2Value + "%", _a); | ||
crit = { [like]: p2Value + "%" }; | ||
} | ||
else if (op === "endswith") { | ||
crit = (_b = {}, _b[like] = "%" + p2Value, _b); | ||
crit = { [like]: "%" + p2Value }; | ||
} | ||
else if (op === "contains") { | ||
crit = (_c = {}, _c[like] = "%" + p2Value + "%", _c); | ||
crit = { [like]: "%" + p2Value + "%" }; | ||
} | ||
else { | ||
crit = {}; | ||
var mop = _boolOpMap[op].sequelizeOp; | ||
let mop = _boolOpMap[op].sequelizeOp; | ||
crit[mop] = p2Value; | ||
@@ -68,8 +66,8 @@ } | ||
else if (this.expr2.visitorMethodName == "propExpr") { | ||
var p2Value_1 = this.expr2.propertyPath; | ||
var props = context.entityType.getPropertiesOnPath(p2Value_1, context.toNameOnServer, true); | ||
p2Value_1 = props.map(function (p) { | ||
let p2Value = this.expr2.propertyPath; | ||
let props = context.entityType.getPropertiesOnPath(p2Value, context.toNameOnServer, true); | ||
p2Value = props.map(function (p) { | ||
return p.nameOnServer; | ||
}).join("."); | ||
var colVal = sequelize_1.Sequelize.col(p2Value_1); | ||
let colVal = sequelize_1.Sequelize.col(p2Value); | ||
if (op === "eq") { | ||
@@ -79,13 +77,13 @@ crit = colVal; | ||
else if (op === "startswith") { | ||
crit = (_d = {}, _d[like] = sequelize_1.Sequelize.literal("concat(" + p2Value_1 + ",'%')"), _d); | ||
crit = { [like]: sequelize_1.Sequelize.literal("concat(" + p2Value + ",'%')") }; | ||
} | ||
else if (op === "endswith") { | ||
crit = (_e = {}, _e[like] = sequelize_1.Sequelize.literal("concat('%'," + p2Value_1 + ")"), _e); | ||
crit = { [like]: sequelize_1.Sequelize.literal("concat('%'," + p2Value + ")") }; | ||
} | ||
else if (op === "contains") { | ||
crit = (_f = {}, _f[like] = sequelize_1.Sequelize.literal("concat('%'," + p2Value_1 + ",'%')"), _f); | ||
crit = { [like]: sequelize_1.Sequelize.literal("concat('%'," + p2Value + ",'%')") }; | ||
} | ||
else { | ||
crit = {}; | ||
var mop = _boolOpMap[op].sequelizeOp; | ||
let mop = _boolOpMap[op].sequelizeOp; | ||
crit[mop] = colVal; | ||
@@ -111,9 +109,8 @@ } | ||
andOrPredicate: function (context) { | ||
var _a, _b; | ||
var result = {}; | ||
var predSqs = this.preds.map(function (pred) { | ||
let result = {}; | ||
let predSqs = this.preds.map(function (pred) { | ||
return pred.visit(context); | ||
}); | ||
var wheres = []; | ||
var includes = []; | ||
let wheres = []; | ||
let includes = []; | ||
if (predSqs.length == 0) { | ||
@@ -126,3 +123,3 @@ return null; | ||
else { | ||
var that_1 = this; | ||
let that = this; | ||
predSqs.forEach(function (predSq) { | ||
@@ -133,7 +130,7 @@ if (!_.isEmpty(predSq.where)) { | ||
if (!_.isEmpty(predSq.include)) { | ||
var processIncludes_1 = function (sourceIncludes, targetIncludes) { | ||
let processIncludes = function (sourceIncludes, targetIncludes) { | ||
sourceIncludes.forEach(function (sourceInclude) { | ||
if (!targetIncludes) | ||
targetIncludes = []; | ||
var include = _.find(targetIncludes, { model: sourceInclude.model }); | ||
let include = _.find(targetIncludes, { model: sourceInclude.model }); | ||
if (!include) { | ||
@@ -147,4 +144,4 @@ targetIncludes.push(sourceInclude); | ||
else if (sourceInclude.where != null) { | ||
var where = {}; | ||
where[that_1.op.key] = [include.where, sourceInclude.where]; | ||
let where = {}; | ||
where[that.op.key] = [include.where, sourceInclude.where]; | ||
include.where = where; | ||
@@ -159,7 +156,7 @@ } | ||
if (!_.isEmpty(sourceInclude.include)) | ||
processIncludes_1(sourceInclude.include, include.include); | ||
processIncludes(sourceInclude.include, include.include); | ||
} | ||
}); | ||
}; | ||
processIncludes_1(predSq.include, includes); | ||
processIncludes(predSq.include, includes); | ||
} | ||
@@ -170,3 +167,3 @@ }); | ||
if (wheres.length > 0) { | ||
result.where = wheres.length == 1 ? wheres[0] : (_a = {}, _a[sequelize_1.Op.and] = wheres, _a); | ||
result.where = wheres.length == 1 ? wheres[0] : { [sequelize_1.Op.and]: wheres }; | ||
} | ||
@@ -180,3 +177,3 @@ // q = Sequelize.and(q1, q2); | ||
if (wheres.length > 0) { | ||
result.where = wheres.length == 1 ? wheres[0] : (_b = {}, _b[sequelize_1.Op.or] = wheres, _b); | ||
result.where = wheres.length == 1 ? wheres[0] : { [sequelize_1.Op.or]: wheres }; | ||
} | ||
@@ -192,10 +189,10 @@ // q = Sequelize.or(q1, q2); | ||
} | ||
var props = context.entityType.getPropertiesOnPath(this.expr.propertyPath, context.toNameOnServer, true); | ||
var parent = {}; | ||
var include = context.sequelizeQuery._addInclude(parent, props); | ||
var newContext = _.clone(context); | ||
let props = context.entityType.getPropertiesOnPath(this.expr.propertyPath, context.toNameOnServer, true); | ||
let parent = {}; | ||
let include = context.sequelizeQuery._addInclude(parent, props); | ||
let newContext = _.clone(context); | ||
newContext.entityType = this.expr.dataType; | ||
// after this line the logic below will apply to the include instead of the top level where. | ||
// predicate is applied to inner context | ||
var r = this.pred.visit(newContext); | ||
let r = this.pred.visit(newContext); | ||
include.where = r.where || {}; | ||
@@ -215,3 +212,3 @@ include.required = true; | ||
function makeWhere(p1Value, crit) { | ||
var where; | ||
let where; | ||
if (typeof (p1Value) == 'string') { | ||
@@ -227,10 +224,10 @@ where = {}; | ||
function processPropExpr(expr, context, result) { | ||
var exprVal; | ||
var pp = expr.propertyPath; | ||
var props = context.entityType.getPropertiesOnPath(pp, context.toNameOnServer, true); | ||
let exprVal; | ||
let pp = expr.propertyPath; | ||
let props = context.entityType.getPropertiesOnPath(pp, context.toNameOnServer, true); | ||
if (props.length > 1) { | ||
// handle a nested property path on the LHS - query gets moved into the include | ||
// context.include starts out null at top level | ||
var parent = {}; | ||
var include = context.sequelizeQuery._addInclude(parent, props); | ||
let parent = {}; | ||
let include = context.sequelizeQuery._addInclude(parent, props); | ||
include.where = {}; | ||
@@ -248,4 +245,4 @@ result.include = parent.include; | ||
function processFnExpr(expr, context, result) { | ||
var fnName = expr.fnName; | ||
var methodInfo = translateMap[fnName]; | ||
let fnName = expr.fnName; | ||
let methodInfo = translateMap[fnName]; | ||
if (methodInfo == null) { | ||
@@ -255,10 +252,10 @@ throw new Error('Unable to locate fn: ' + fnName); | ||
methodInfo.validate && methodInfo.validate(expr.exprs); | ||
var exprs = expr.exprs.map(function (ex) { | ||
let exprs = expr.exprs.map(function (ex) { | ||
return processNestedExpr(ex, context, result); | ||
}); | ||
var exprVal = methodInfo.fn(exprs); | ||
let exprVal = methodInfo.fn(exprs); | ||
return exprVal; | ||
} | ||
function processNestedExpr(expr, context, result) { | ||
var exprVal; | ||
let exprVal; | ||
if (expr.visitorMethodName === 'propExpr') { | ||
@@ -269,4 +266,4 @@ exprVal = processPropExpr(expr, context, result); | ||
else if (expr.visitorMethodName == 'fnExpr') { | ||
var exprVal_1 = processFnExpr(expr, context, result); | ||
return exprVal_1; | ||
let exprVal = processFnExpr(expr, context, result); | ||
return exprVal; | ||
} | ||
@@ -280,3 +277,3 @@ else if (expr.visitorMethodName = 'litExpr') { | ||
} | ||
var translateMap = { | ||
let translateMap = { | ||
toupper: { | ||
@@ -305,3 +302,3 @@ fn: function (sqArgs) { | ||
}; | ||
var simpleFnNames = ['length', 'trim', 'ceiling', 'floor', 'round', 'second', 'minute', 'hour', 'day', 'month', 'year']; | ||
let simpleFnNames = ['length', 'trim', 'ceiling', 'floor', 'round', 'second', 'minute', 'hour', 'day', 'month', 'year']; | ||
simpleFnNames.forEach(function (fnName) { | ||
@@ -318,4 +315,4 @@ translateMap[fnName] = { | ||
function validateMonadicFn(fnName, exprs) { | ||
var errTmpl = "Error with call to the '%1' function."; | ||
var errMsg; | ||
let errTmpl = "Error with call to the '%1' function."; | ||
let errMsg; | ||
if (exprs.length != 1) { | ||
@@ -333,9 +330,5 @@ errMsg = formatString(errTmpl + " This function only takes a single parameter", fnName); | ||
// format("a %1 and a %2", "cat", "dog") -> "a cat and a dog" | ||
function formatString(string) { | ||
var rest = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
rest[_i - 1] = arguments[_i]; | ||
} | ||
var args = arguments; | ||
var pattern = RegExp("%([1-" + (arguments.length - 1) + "])", "g"); | ||
function formatString(string, ...rest) { | ||
let args = arguments; | ||
let pattern = RegExp("%([1-" + (arguments.length - 1) + "])", "g"); | ||
return string.replace(pattern, function (match, index) { | ||
@@ -354,13 +347,11 @@ return args[index]; | ||
// not { or { a: 1, b: 2 } -> { and: [ a: { $ne: 1 }, b: { $ne 2 }]} | ||
var _a, _b, _c, _d; | ||
var results = [], result; | ||
var keys = Reflect.ownKeys(q1); | ||
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { | ||
var k = keys_1[_i]; | ||
var v = q1[k]; | ||
let results = [], result; | ||
let keys = Reflect.ownKeys(q1); | ||
for (let k of keys) { | ||
let v = q1[k]; | ||
if (k === sequelize_1.Op.or) { | ||
result = (_a = {}, _a[sequelize_1.Op.and] = [applyNot(v[0]), applyNot(v[1])], _a); | ||
result = { [sequelize_1.Op.and]: [applyNot(v[0]), applyNot(v[1])] }; | ||
} | ||
else if (k === sequelize_1.Op.and) { | ||
result = (_b = {}, _b[sequelize_1.Op.or] = [applyNot(v[0]), applyNot(v[1])], _b); | ||
result = { [sequelize_1.Op.or]: [applyNot(v[0]), applyNot(v[1])] }; | ||
} | ||
@@ -377,3 +368,3 @@ else if (_notOps[k]) { | ||
else { | ||
result[k] = (_c = {}, _c[sequelize_1.Op.ne] = v, _c); | ||
result[k] = { [sequelize_1.Op.ne]: v }; | ||
} | ||
@@ -389,6 +380,6 @@ } | ||
// queries should only have a single node | ||
return _d = {}, _d[sequelize_1.Op.or] = results, _d; | ||
return { [sequelize_1.Op.or]: results }; | ||
} | ||
} | ||
var _boolOpMap = { | ||
let _boolOpMap = { | ||
eq: { not: sequelize_1.Op.ne }, | ||
@@ -403,24 +394,23 @@ gt: { sequelizeOp: sequelize_1.Op.gt, not: sequelize_1.Op.lte }, | ||
}; | ||
var _notOps = (_a = { | ||
gt: "lte", | ||
lte: "gt", | ||
gte: "lt", | ||
lt: "gte", | ||
ne: "eq", | ||
eq: "ne", | ||
like: "nlike", | ||
nlike: "like", | ||
in: "notIn", | ||
notIn: "in" | ||
}, | ||
_a[sequelize_1.Op.gt] = sequelize_1.Op.lte, | ||
_a[sequelize_1.Op.lte] = sequelize_1.Op.gt, | ||
_a[sequelize_1.Op.gte] = sequelize_1.Op.lt, | ||
_a[sequelize_1.Op.lt] = sequelize_1.Op.gte, | ||
_a[sequelize_1.Op.ne] = sequelize_1.Op.eq, | ||
_a[sequelize_1.Op.like] = sequelize_1.Op.notLike, | ||
_a[sequelize_1.Op.notLike] = sequelize_1.Op.like, | ||
_a[sequelize_1.Op.in] = sequelize_1.Op.notIn, | ||
_a[sequelize_1.Op.notIn] = sequelize_1.Op.in, | ||
_a); | ||
let _notOps = { | ||
gt: "lte", | ||
lte: "gt", | ||
gte: "lt", | ||
lt: "gte", | ||
ne: "eq", | ||
eq: "ne", | ||
like: "nlike", | ||
nlike: "like", | ||
in: "notIn", | ||
notIn: "in", | ||
[sequelize_1.Op.gt]: sequelize_1.Op.lte, | ||
[sequelize_1.Op.lte]: sequelize_1.Op.gt, | ||
[sequelize_1.Op.gte]: sequelize_1.Op.lt, | ||
[sequelize_1.Op.lt]: sequelize_1.Op.gte, | ||
[sequelize_1.Op.ne]: sequelize_1.Op.eq, | ||
[sequelize_1.Op.like]: sequelize_1.Op.notLike, | ||
[sequelize_1.Op.notLike]: sequelize_1.Op.like, | ||
[sequelize_1.Op.in]: sequelize_1.Op.notIn, | ||
[sequelize_1.Op.notIn]: sequelize_1.Op.in | ||
}; | ||
// Used to determine if a clause is the result of a Sequelize.and/or method call. | ||
@@ -427,0 +417,0 @@ // Not currently need because of processAndOr method below |
@@ -1,4 +0,5 @@ | ||
import { SequelizeQuery, entityQueryFromUrl } from "./SequelizeQuery"; | ||
import { SequelizeManager } from "./SequelizeManager"; | ||
import { SequelizeSaveHandler } from "./SequelizeSaveHandler"; | ||
import { SequelizeQuery, SequelizeQueryResult, urlToEntityQuery } from "./SequelizeQuery"; | ||
import { SequelizeManager, KeyGenerator } from "./SequelizeManager"; | ||
import { SequelizeSaveHandler, SequelizeSaveResult, ServerEntityInfo, ServerEntityAspect, ServerEntity, ServerEntityState } from "./SequelizeSaveHandler"; | ||
import { SaveMap } from './SaveMap'; | ||
import * as utils from "./utils"; | ||
@@ -8,2 +9,2 @@ import * as dbUtils from "./dbUtils"; | ||
declare const Sequelize: typeof import("sequelize/types").Sequelize; | ||
export { SequelizeQuery, entityQueryFromUrl, SequelizeManager, Sequelize, SequelizeSaveHandler, utils, dbUtils, breeze }; | ||
export { Sequelize, SequelizeQuery, SequelizeManager, SequelizeSaveHandler, KeyGenerator, SequelizeQueryResult, SequelizeSaveResult, SaveMap, ServerEntity, ServerEntityAspect, ServerEntityInfo, ServerEntityState, urlToEntityQuery, utils, dbUtils, breeze }; |
@@ -1,29 +0,3 @@ | ||
import { Entity, EntityState, EntityType, StructuralType } from "breeze-client"; | ||
import { SequelizeSaveHandler } from "./SequelizeSaveHandler"; | ||
/** Server-side representation of entity that came from the client */ | ||
export interface EntityInfo { | ||
entity: Entity; | ||
entityType: EntityType; | ||
wasAddedOnServer: boolean; | ||
forceUpdate: boolean; | ||
entityAspect: { | ||
entityTypeName: string; | ||
entityState: EntityState | string; | ||
entity?: Entity; | ||
autoGeneratedKey?: { | ||
autoGeneratedKeyType: string; | ||
}; | ||
originalValuesMap?: { | ||
[prop: string]: any; | ||
}; | ||
}; | ||
} | ||
/** Validation error created on the server */ | ||
export interface ServerEntityError { | ||
entityTypeName: string; | ||
errorName: string; | ||
errorMessage: string; | ||
propertyName: string; | ||
keyValues: any[]; | ||
} | ||
import { StructuralType } from "breeze-client"; | ||
import { SequelizeSaveHandler, ServerEntityError, ServerEntityInfo, ServerEntityState } from "./SequelizeSaveHandler"; | ||
/** Maps EntityType names to arrays of EntityInfo */ | ||
@@ -36,9 +10,9 @@ export declare class SaveMap { | ||
getEntityType(entityTypeName: string): StructuralType; | ||
getEntityInfosOfType(entityTypeName: string): EntityInfo[]; | ||
getEntityInfosOfType(entityTypeName: string): ServerEntityInfo[]; | ||
/** Add an entity to the map */ | ||
addEntity(entityTypeName: string, entity: Entity, entityState: EntityState): EntityInfo; | ||
addEntity(entityTypeName: string, entity: object, entityState?: ServerEntityState): ServerEntityInfo; | ||
/** Add an error to the entityErrors collection */ | ||
addEntityError(entityInfo: EntityInfo, errorName: string, errorMessage: string, propertyName: string): void; | ||
addEntityError(entityInfo: ServerEntityInfo, errorName: string, errorMessage: string, propertyName: string): void; | ||
/** Set the error message to return to the client */ | ||
setErrorMessage(errorMessage: string): void; | ||
} |
@@ -8,3 +8,3 @@ import { EntityQuery, EntityType, MetadataStore, NavigationProperty, VisitContext } from "breeze-client"; | ||
*/ | ||
export declare function entityQueryFromUrl(url: string, resourceName?: string): EntityQuery; | ||
export declare function urlToEntityQuery(url: string, resourceName?: string): EntityQuery; | ||
export interface SequelizeQueryOptions { | ||
@@ -19,2 +19,7 @@ useTransaction: boolean; | ||
} | ||
export declare type SequelizeRawQueryResult = CountModel | Model[]; | ||
export declare type SequelizeQueryResult = { | ||
results: any[]; | ||
inlineCount: number; | ||
} | any[]; | ||
export interface SqVisitContext extends VisitContext { | ||
@@ -37,8 +42,5 @@ sequelizeQuery: SequelizeQuery; | ||
/** Execute the current query and return data objects */ | ||
execute(options: SequelizeQueryOptions): Promise<any[] | { | ||
results: any[]; | ||
inlineCount: number; | ||
}>; | ||
execute(options?: SequelizeQueryOptions): Promise<SequelizeQueryResult>; | ||
/** Execute the current query and return the Sequelize Models */ | ||
executeRaw(options: SequelizeQueryOptions): Promise<CountModel | Model[]>; | ||
executeRaw(options?: SequelizeQueryOptions): Promise<SequelizeRawQueryResult>; | ||
private _processQuery; | ||
@@ -45,0 +47,0 @@ private _processWhere; |
@@ -1,12 +0,60 @@ | ||
import { Entity, MetadataStore, SaveOptions } from "breeze-client"; | ||
import { EntityInfo, SaveMap, ServerEntityError } from "./SaveMap"; | ||
import { Entity, EntityType, KeyMapping, MetadataStore, SaveOptions } from "breeze-client"; | ||
import { SaveMap } from "./SaveMap"; | ||
import { Transaction } from "sequelize"; | ||
import { KeyGenerator, SequelizeManager } from "./SequelizeManager"; | ||
export declare type OpenObj = { | ||
[k: string]: any; | ||
}; | ||
export declare type ServerEntityState = "Added" | "Deleted" | "Modified"; | ||
/** Save bundle from breeze client */ | ||
export interface SaveRequest { | ||
body: { | ||
entities: Entity[]; | ||
entities: ServerEntity[]; | ||
saveOptions?: SaveOptions; | ||
}; | ||
} | ||
export interface ServerEntity { | ||
[k: string]: any; | ||
entityAspect: ServerEntityAspect; | ||
} | ||
/** Server-side representation of entity that came from the client */ | ||
export interface ServerEntityInfo { | ||
entity: ServerEntity; | ||
entityType: EntityType; | ||
wasAddedOnServer?: boolean; | ||
forceUpdate?: boolean; | ||
unmapped?: any; | ||
entityAspect: ServerEntityAspect; | ||
} | ||
export interface ServerEntityAspect { | ||
entityTypeName: string; | ||
defaultResourceName: string; | ||
entityState: ServerEntityState; | ||
entity?: ServerEntity; | ||
autoGeneratedKey?: { | ||
autoGeneratedKeyType: string; | ||
propertyName?: string; | ||
}; | ||
originalValuesMap?: { | ||
[prop: string]: any; | ||
}; | ||
} | ||
/** Validation error created on the server */ | ||
export interface ServerEntityError { | ||
entityTypeName: string; | ||
errorName: string; | ||
errorMessage: string; | ||
propertyName: string; | ||
keyValues: any[]; | ||
} | ||
export interface SequelizeSaveError { | ||
errors: ServerEntityError[]; | ||
message: string; | ||
} | ||
export interface SequelizeSaveResult { | ||
entities: Entity[]; | ||
keyMappings: KeyMapping[]; | ||
} | ||
export declare type BeforeSaveEntityFn = (e: ServerEntityInfo) => boolean; | ||
export declare type BeforeSaveEntitiesFn = (sm: SaveMap, trx?: Transaction) => Promise<SaveMap>; | ||
/** Handles saving entities from Breeze SaveChanges requests */ | ||
@@ -16,3 +64,3 @@ export declare class SequelizeSaveHandler { | ||
readonly metadataStore: MetadataStore; | ||
readonly entitiesFromClient: Entity[]; | ||
readonly entitiesFromClient: ServerEntity[]; | ||
saveOptions: SaveOptions; | ||
@@ -25,12 +73,9 @@ private _keyMappings; | ||
/** Process an entity before save. If false is returned, entity is not saved. */ | ||
beforeSaveEntity: (ei: EntityInfo) => boolean; | ||
beforeSaveEntity: BeforeSaveEntityFn; | ||
/** Process all entities before save. The entities in the returned SaveMap are saved. */ | ||
beforeSaveEntities: (sm: SaveMap, trx?: Transaction) => SaveMap; | ||
beforeSaveEntities: BeforeSaveEntitiesFn; | ||
/** Create an instance for the given save request */ | ||
constructor(sequelizeManager: SequelizeManager, req: SaveRequest); | ||
/** Save the entities in the save request, returning either the saved entities or an error collection */ | ||
save(): Promise<{ | ||
errors: ServerEntityError[]; | ||
message: string; | ||
}> | Promise<Entity[]>; | ||
save(): Promise<SequelizeSaveResult>; | ||
private _saveWithTransaction; | ||
@@ -37,0 +82,0 @@ private _saveCore; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** Wrapper around console.log. Use `log.enabled` to enable/disable */ | ||
function log(s) { | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments[_i]; | ||
} | ||
function log(s, ...args) { | ||
if (!log['enabled']) | ||
@@ -10,0 +6,0 @@ return; |
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
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
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
87422
12
1909
1