jaydata
Version:
Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)
688 lines (626 loc) • 29.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _index = require('../TypeSystem/index.js');
var _index2 = _interopRequireDefault(_index);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_index2.default.Class.define('$data.ItemStoreClass', null, null, {
constructor: function constructor() {
var self = this;
self.itemStoreConfig = {
aliases: {},
contextTypes: {}
};
self.resetStoreToDefault('local', true);
_index2.default.addStore = function () {
return self.addItemStoreAlias.apply(self, arguments);
};
_index2.default.implementation = self.implementation;
_index2.default.Entity.addMember('storeToken', {
get: function get() {
if (this.storeConfigs && this.storeConfigs['default']) return this.storeConfigs.stores[this.storeConfigs['default']];
},
set: function set(value) {
self._setTypeStoreConfig(this, 'default', value);
}
}, true);
},
itemStoreConfig: {},
attachMode: _index2.default.EntityAttachMode ? _index2.default.EntityAttachMode.KeepChanges : true,
addItemStoreAlias: function addItemStoreAlias(name, contextFactoryOrToken, isDefault) {
var self = this;
var promise = new _index2.default.PromiseHandler();
var callback = promise.createCallback();
if ('string' === typeof name) {
//storeToken
if ('object' === (typeof contextFactoryOrToken === 'undefined' ? 'undefined' : _typeof(contextFactoryOrToken)) && 'factory' in contextFactoryOrToken) {
var type = _index.Container.resolveType(contextFactoryOrToken.typeName);
self.itemStoreConfig.aliases[name] = contextFactoryOrToken.factory;
self.itemStoreConfig.contextTypes[name] = type;
if (isDefault) {
self.itemStoreConfig['default'] = name;
}
callback.success();
return promise.getPromise();
}
//contextFactory
else if ('function' === typeof contextFactoryOrToken) {
var preContext = contextFactoryOrToken();
var contextPromise;
if (preContext && preContext instanceof _index2.default.EntityContext) {
callback.success(preContext);
contextPromise = promise.getPromise();
} else {
contextPromise = preContext;
}
return contextPromise.then(function (ctx) {
if (typeof ctx === 'function') {
//factory resolve factory
return self.addItemStoreAlias(name, ctx, isDefault);
}
if (ctx instanceof _index2.default.EntityContext) {
return ctx.onReady().then(function (ctx) {
self.itemStoreConfig.aliases[name] = contextFactoryOrToken;
self.itemStoreConfig.contextTypes[name] = ctx.getType();
if (isDefault) {
self.itemStoreConfig['default'] = name;
}
return ctx;
});
} else {
promise = new _index2.default.PromiseHandler();
callback = promise.createCallback();
callback.error(new _index.Exception('factory dont have context instance', 'Invalid arguments'));
return promise.getPromise();
}
});
}
}
callback.error(new _index.Exception('Name or factory missing', 'Invalid arguments'));
return promise.getPromise();
},
resetStoreToDefault: function resetStoreToDefault(name, isDefault) {
this.itemStoreConfig.aliases[name] = this._getDefaultItemStoreFactory;
delete this.itemStoreConfig.contextTypes[name];
if (isDefault) {
this.itemStoreConfig['default'] = name;
}
},
_setStoreAlias: function _setStoreAlias(entity, storeToken) {
if ('object' === (typeof storeToken === 'undefined' ? 'undefined' : _typeof(storeToken)) && !entity.storeToken) entity.storeToken = storeToken;
return entity;
},
_getStoreAlias: function _getStoreAlias(entity, storeAlias) {
var type;
if (entity instanceof _index2.default.Entity) {
var alias = storeAlias || entity.storeToken;
if (alias) {
return alias;
} else {
type = entity.getType();
}
} else {
type = entity;
}
return storeAlias || (type.storeConfigs ? type.storeConfigs['default'] : undefined) || type.storeToken;
},
_getStoreContext: function _getStoreContext(aliasOrToken, type, nullIfInvalid) {
var contextPromise = this._getContextPromise(aliasOrToken, type);
if (!contextPromise || contextPromise instanceof _index2.default.EntityContext) {
var promise = new _index2.default.PromiseHandler();
var callback = promise.createCallback();
callback.success(contextPromise);
contextPromise = promise.getPromise();
}
return contextPromise.then(function (context) {
if (context instanceof _index2.default.EntityContext) {
return context.onReady();
} else if (nullIfInvalid) {
return null;
} else {
var promise = new _index2.default.PromiseHandler();
var callback = promise.createCallback();
callback.error(new _index.Exception('factory return type error', 'Error'));
return promise.getPromise();
}
});
},
_getContextPromise: function _getContextPromise(aliasOrToken, type) {
/*Token*/
if (aliasOrToken && 'object' === (typeof aliasOrToken === 'undefined' ? 'undefined' : _typeof(aliasOrToken)) && 'function' === typeof aliasOrToken.factory) {
return aliasOrToken.factory(type);
} else if (aliasOrToken && 'object' === (typeof aliasOrToken === 'undefined' ? 'undefined' : _typeof(aliasOrToken)) && 'object' === _typeof(aliasOrToken.args) && 'string' === typeof aliasOrToken.typeName) {
var type = _index.Container.resolveType(aliasOrToken.typeName);
return new type(JSON.parse(JSON.stringify(aliasOrToken.args)));
}
/*resolve alias from type (Token)*/
else if (aliasOrToken && 'string' === typeof aliasOrToken && type.storeConfigs && type.storeConfigs.stores[aliasOrToken] && typeof type.storeConfigs.stores[aliasOrToken].factory === 'function') {
return type.storeConfigs.stores[aliasOrToken].factory();
}
/*resolve alias from type (constructor options)*/
else if (aliasOrToken && 'string' === typeof aliasOrToken && type.storeConfigs && type.storeConfigs.stores[aliasOrToken]) {
return this._getDefaultItemStoreFactory(type, type.storeConfigs.stores[aliasOrToken]);
}
/*resolve alias from ItemStore (factories)*/
else if (aliasOrToken && 'string' === typeof aliasOrToken && this.itemStoreConfig.aliases[aliasOrToken]) {
return this.itemStoreConfig.aliases[aliasOrToken](type);
}
/*token is factory*/
else if (aliasOrToken && 'function' === typeof aliasOrToken) {
return aliasOrToken();
}
/*default no hint*/
else {
return this.itemStoreConfig.aliases[this.itemStoreConfig['default']](type);
}
},
_getStoreEntitySet: function _getStoreEntitySet(storeAlias, instanceOrType) {
var aliasOrToken = this._getStoreAlias(instanceOrType, storeAlias);
var type = "function" === typeof instanceOrType ? instanceOrType : instanceOrType.getType();;
return this._getStoreContext(aliasOrToken, type).then(function (ctx) {
var entitySet = ctx.getEntitySetFromElementType(type);
if (!entitySet) {
var d = new _index2.default.PromiseHandler();
var callback = d.createCallback();
callback.error("EntitySet not exist for " + type.fullName);
return d.getPromise();
}
return entitySet;
});
},
_getDefaultItemStoreFactory: function _getDefaultItemStoreFactory(instanceOrType, initStoreConfig) {
if (instanceOrType) {
var type = "function" === typeof instanceOrType ? instanceOrType : instanceOrType.getType();
var typeName = _index2.default.Container.resolveName(type) + "_items";
var typeName = typeName.replace(/\./g, "_");
var storeConfig = _index2.default.typeSystem.extend({
collectionName: initStoreConfig && initStoreConfig.collectionName ? initStoreConfig.collectionName : 'Items',
tableName: typeName,
initParam: { provider: 'local', databaseName: typeName }
}, initStoreConfig);
var contextDef = {};
contextDef[storeConfig.collectionName] = { type: _index2.default.EntitySet, elementType: type };
if (storeConfig.tableName) contextDef[storeConfig.collectionName]['tableName'] = storeConfig.tableName;
var inMemoryType = _index2.default.EntityContext.extend(typeName, contextDef);
var ctx = new inMemoryType(storeConfig.initParam);
if (initStoreConfig && (typeof initStoreConfig === 'undefined' ? 'undefined' : _typeof(initStoreConfig)) === 'object') initStoreConfig.factory = ctx._storeToken.factory;
return ctx;
}
return undefined;
},
implementation: function implementation(name, contextOrAlias) {
var self = _index2.default.ItemStore;
var result;
if (typeof contextOrAlias === 'string') {
contextOrAlias = self.itemStoreConfig.contextTypes[contextOrAlias];
} else if (contextOrAlias instanceof _index2.default.EntityContext) {
contextOrAlias = contextOrAlias.getType();
} else if (!(typeof contextOrAlias === 'function' && contextOrAlias.isAssignableTo)) {
contextOrAlias = self.itemStoreConfig.contextTypes[self.itemStoreConfig['default']];
}
if (contextOrAlias) {
result = self._resolveFromContext(contextOrAlias, name);
}
if (!result) {
result = _index.Container.resolveType(name);
}
return result;
},
_resolveFromContext: function _resolveFromContext(contextType, name) {
var memDefs = contextType.memberDefinitions.getPublicMappedProperties();
for (var i = 0; i < memDefs.length; i++) {
var memDef = memDefs[i];
if (memDef.type) {
var memDefType = _index.Container.resolveType(memDef.type);
if (memDefType.isAssignableTo && memDefType.isAssignableTo(_index2.default.EntitySet)) {
var elementType = _index.Container.resolveType(memDef.elementType);
if (elementType.name === name) {
return elementType;
}
}
}
}
return null;
},
//Entity Instance
EntityInstanceSave: function EntityInstanceSave(storeAlias, hint, attachMode) {
var self = _index2.default.ItemStore;
var entity = this;
return self._getStoreEntitySet(storeAlias, entity).then(function (entitySet) {
return self._getSaveMode(entity, entitySet, hint, storeAlias).then(function (mode) {
mode = mode || 'add';
switch (mode) {
case 'add':
entitySet.add(entity);
break;
case 'attach':
entitySet.attach(entity, attachMode || true);
break;
default:
var d = new _index2.default.PromiseHandler();
var callback = d.createCallback();
callback.error('save mode not supported: ' + mode);
return d.getPromise();
}
return entitySet.entityContext.saveChanges().then(function () {
self._setStoreAlias(entity, entitySet.entityContext.storeToken);return entity;
});
});
});
},
EntityInstanceRemove: function EntityInstanceRemove(storeAlias) {
var self = _index2.default.ItemStore;
var entity = this;
return self._getStoreEntitySet(storeAlias, entity).then(function (entitySet) {
entitySet.remove(entity);
return entitySet.entityContext.saveChanges().then(function () {
return entity;
});
});
},
EntityInstanceRefresh: function EntityInstanceRefresh(storeAlias, keepStore) {
var self = _index2.default.ItemStore;
var entity = this;
var entityType = entity.getType();
var key = self._getKeyObjectFromEntity(entity, entityType);
return entityType.read(key, storeAlias).then(function (loadedEntity) {
entityType.memberDefinitions.getPublicMappedProperties().forEach(function (memDef) {
entity[memDef.name] = loadedEntity[memDef.name];
});
entity.storeToken = (keepStore ? entity.storeToken : undefined) || loadedEntity.storeToken;
entity.changedProperties = undefined;
return entity;
});
},
//Entity Type
EntityInheritedTypeProcessor: function EntityInheritedTypeProcessor(type) {
var self = _index2.default.ItemStore;
type.readAll = self.EntityTypeReadAll(type);
type.read = self.EntityTypeRead(type);
type.removeAll = self.EntityTypeRemoveAll(type);
type.remove = self.EntityTypeRemove(type);
type.get = self.EntityTypeGet(type); //Not complete
type.save = self.EntityTypeSave(type);
type.addMany = self.EntityTypeAddMany(type);
type.itemCount = self.EntityTypeItemCount(type);
type.query = self.EntityTypeQuery(type);
type.takeFirst = self.EntityTypeTakeFirst(type);
type.setStore = self.EntityTypeSetStore(type);
},
EntityTypeReadAll: function EntityTypeReadAll(type) {
return function (storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
return entitySet.forEach(function (item) {
self._setStoreAlias(item, entitySet.entityContext.storeToken);
});
});
};
},
EntityTypeRemoveAll: function EntityTypeRemoveAll(type) {
return function (storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
return entitySet.toArray().then(function (items) {
items.forEach(function (item) {
entitySet.remove(item);
});
return entitySet.entityContext.saveChanges().then(function () {
return items;
});
});
});
};
},
EntityTypeRead: function EntityTypeRead(type) {
return function (key, storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
try {
var singleParam = self._findByIdQueryable(entitySet, key);
return entitySet.single(singleParam.predicate, singleParam.thisArgs).then(function (item) {
return self._setStoreAlias(item, entitySet.entityContext.storeToken);
});
} catch (e) {
var d = new _index2.default.PromiseHandler();
var callback = d.createCallback();
callback.error(e);
return d.getPromise();
}
});
};
},
EntityTypeGet: function EntityTypeGet(type) {
return function (key, storeAlias) {
var self = _index2.default.ItemStore;
var item = new type(self._getKeyObjectFromEntity(key));
item.refresh(storeAlias);
return item;
};
},
EntityTypeSave: function EntityTypeSave(type) {
return function (initData, storeAlias, hint) {
var self = _index2.default.ItemStore;
var instance = new type(initData);
return instance.save(storeAlias, hint);
};
},
EntityTypeAddMany: function EntityTypeAddMany(type) {
return function (initDatas, storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
var items = entitySet.addMany(initDatas);
return entitySet.entityContext.saveChanges().then(function () {
return items;
});
});
};
},
EntityTypeRemove: function EntityTypeRemove(type) {
return function (key, storeAlias) {
var self = _index2.default.ItemStore;
var entityPk = type.memberDefinitions.getKeyProperties();
var entity;
if (entityPk.length === 1) {
var obj = {};
obj[entityPk[0].name] = key;
entity = new type(obj);
} else {
entity = new type(key);
}
return entity.remove(storeAlias);
};
},
EntityTypeItemCount: function EntityTypeItemCount(type) {
return function (storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
return entitySet.length();
});
};
},
EntityTypeQuery: function EntityTypeQuery(type) {
return function (predicate, thisArg, storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
return entitySet.filter(predicate, thisArg).forEach(function (item) {
self._setStoreAlias(item, entitySet.entityContext.storeToken);
});
});
};
},
EntityTypeTakeFirst: function EntityTypeTakeFirst(type) {
return function (predicate, thisArg, storeAlias) {
var self = _index2.default.ItemStore;
return self._getStoreEntitySet(storeAlias, type).then(function (entitySet) {
return entitySet.first(predicate, thisArg).then(function (item) {
return self._setStoreAlias(item, entitySet.entityContext.storeToken);
});
});
};
},
EntityTypeSetStore: function EntityTypeSetStore(type) {
return function (name, config) {
if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object' && typeof config === 'undefined') {
config = name;
name = 'default';
}
var self = _index2.default.ItemStore;
var defStoreConfig = {};
if (config) {
if (config.tableName) {
defStoreConfig.tableName = config.tableName;
delete config.tableName;
}
if (config.collectionName) {
defStoreConfig.collectionName = config.collectionName;
delete config.collectionName;
}
if (typeof config.dataSource === 'string') {
var ds = config.dataSource;
if (ds.lastIndexOf('/') === ds.length - 1) {
ds = ds.substring(0, ds.lastIndexOf('/'));
}
var parsedApiUrl = ds.substring(0, ds.lastIndexOf('/'));
if (!defStoreConfig.tableName) defStoreConfig.tableName = ds.substring(ds.lastIndexOf('/') + 1);
var provider = config.provider || config.name;
switch (provider) {
case 'oData':
config.oDataServiceHost = config.oDataServiceHost || parsedApiUrl;
break;
case 'webApi':
config.apiUrl = config.apiUrl || parsedApiUrl;
break;
default:
break;
}
}
} else {
config = { name: 'local' };
}
defStoreConfig.initParam = config;
self._setTypeStoreConfig(type, name, defStoreConfig);
return type;
};
},
_setTypeStoreConfig: function _setTypeStoreConfig(type, name, config) {
if (!type.storeConfigs) {
type.storeConfigs = {
stores: {}
};
}
type.storeConfigs.stores[name] = config;
if (name === 'default') {
type.storeConfigs['default'] = name;
}
},
_findByIdQueryable: function _findByIdQueryable(set, keys) {
var keysProps = set.defaultType.memberDefinitions.getKeyProperties();
if (keysProps.length > 1 && keys && 'object' === (typeof keys === 'undefined' ? 'undefined' : _typeof(keys))) {
var predicate = "",
thisArgs = {};
for (var i = 0; i < keysProps.length; i++) {
if (i > 0) predicate += " && ";
var key = keysProps[i];
predicate += "it." + key.name + " == this." + key.name;
thisArgs[key.name] = keys[key.name];
}
return {
predicate: predicate,
thisArgs: thisArgs
};
} else if (keysProps.length === 1) {
return {
predicate: "it." + keysProps[0].name + " == this.value",
thisArgs: { value: keys }
};
} else {
throw 'invalid keys';
}
},
_getKeyObjectFromEntity: function _getKeyObjectFromEntity(obj, entityType) {
var key;
var keyDefs = entityType.memberDefinitions.getKeyProperties();
if (keyDefs.length === 1) key = obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' ? obj[keyDefs[0].name] : obj;else {
key = {};
for (var i = 0; i < keyDefs.length; i++) {
key[keyDefs[0].name] = obj ? obj[keyDefs[0].name] : obj;
}
}
return key;
},
_getSaveMode: function _getSaveMode(entity, entitySet, hint, storeAlias) {
var self = this;
var promise = new _index2.default.PromiseHandler();
var callback = promise.createCallback();
var entityType = entity.getType();
switch (true) {
case hint === 'update':
callback.success('attach');break;
case hint === 'new':
callback.success('add');break;
case false === entityType.memberDefinitions.getKeyProperties().every(function (keyDef) {
return entity[keyDef.name];
}):
callback.success('add');break;
case !!entity.storeToken:
callback.success('attach');break;
break;
default:
//use the current entity store informations
storeAlias = this._getStoreAlias(entity, storeAlias);
entityType.read(self._getKeyObjectFromEntity(entity, entityType), storeAlias).then(function () {
callback.success('attach');
}, function () {
callback.success('add');
});
break;
}
return promise.getPromise();
},
//EntityContext
ContextRegister: function ContextRegister(storageProviderCfg) {
//context instance
var self = this;
if (typeof storageProviderCfg.name === "string") {
storageProviderCfg.name = [storageProviderCfg.name];
}
var args = JSON.parse(JSON.stringify(storageProviderCfg));
this.storeToken = {
typeName: this.getType().fullName,
args: args,
factory: function factory() {
return new (self.getType())(args);
}
};
//set elementType storetoken
var members = this.getType().memberDefinitions.getPublicMappedProperties();
for (var i = 0; i < members.length; i++) {
var item = members[i];
if (item.type) {
var itemResolvedDataType = _index.Container.resolveType(item.type);
if (itemResolvedDataType && itemResolvedDataType.isAssignableTo && itemResolvedDataType.isAssignableTo(_index2.default.EntitySet)) {
var elementType = _index.Container.resolveType(item.elementType);
if (!elementType.storeToken) {
elementType.storeToken = this.storeToken;
}
}
}
}
},
QueryResultModifier: function QueryResultModifier(query) {
var self = _index2.default.ItemStore;
var context = query.context;
var type = query.modelBinderConfig.$type;
if ('string' === typeof type) {
type = _index.Container.resolveType(type);
}
if (type === _index2.default.Array && query.modelBinderConfig.$item && query.modelBinderConfig.$item.$type) {
type = query.modelBinderConfig.$item.$type;
}
//TODO: runs when model binding missed (inmemory)
if (typeof type === 'undefined' && query.result && query.result[0] instanceof _index2.default.Entity) {
var navProps = !type ? [] : type.memberDefinitions.getPublicMappedProperties().filter(function (memDef) {
return !!memDef.inverseProperty;
});
for (var i = 0; i < query.result.length; i++) {
self._setStoreAlias(query.result[i], context.storeToken);
for (var j = 0; j < navProps.length; j++) {
var navProp = navProps[j];
if (query.result[i][navProp.name] instanceof _index2.default.Entity) {
self._setStoreAlias(query.result[i][navProp.name], context.storeToken);
} else if (Array.isArray(query.result[i][navProp.name])) {
for (var k = 0; k < query.result[i][navProp.name].length; k++) {
if (query.result[i][navProp.name][k] instanceof _index2.default.Entity) {
self._setStoreAlias(query.result[i][navProp.name][k], context.storeToken);
}
}
}
}
}
}
}
});
_index2.default.ItemStore = new _index2.default.ItemStoreClass();
_index2.default.Entity.addMember('field', function (propName) {
var def = this.memberDefinitions.getMember(propName);
if (def) {
if (def.definedBy === this) {
return new _index2.default.MemberWrapper(def);
} else {
_index.Guard.raise(new _index.Exception("Member '" + propName + "' defined on '" + def.definedBy.fullName + "'!", 'Invalid Operation'));
}
} else {
_index.Guard.raise(new _index.Exception("Member '" + propName + "' not exists!", 'Invalid Operation'));
}
return this;
}, true);
_index2.default.Class.define('$data.MemberWrapper', null, null, {
constructor: function constructor(memberDefinition) {
this.memberDefinition = memberDefinition;
},
setKey: function setKey(value) {
this.memberDefinition.key = value || value === undefined ? true : false;
return this;
},
setComputed: function setComputed(value) {
this.memberDefinition.computed = value || value === undefined ? true : false;
return this;
},
setRequired: function setRequired(value) {
this.memberDefinition.required = value || value === undefined ? true : false;
return this;
},
setNullable: function setNullable(value) {
this.memberDefinition.nullable = value || value === undefined ? true : false;
return this;
},
changeDefinition: function changeDefinition(attr, value) {
this.memberDefinition[attr] = value;
return this;
}
});
exports.default = _index2.default;
module.exports = exports['default'];