electrodb
Advanced tools
Comparing version 0.9.19 to 0.9.20
{ | ||
"name": "electrodb", | ||
"version": "0.9.19", | ||
"version": "0.9.20", | ||
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -340,3 +340,3 @@ const { QueryTypes, MethodTypes } = require("./types"); | ||
} | ||
return entity.go(state.query.method, params, options); | ||
return entity.go(state.query.method, params, options) | ||
}, | ||
@@ -343,0 +343,0 @@ children: [], |
"use strict"; | ||
const { Schema } = require("./schema"); | ||
const { ElectroInstance, KeyTypes, QueryTypes, MethodTypes, Comparisons, ExpressionTypes } = require("./types"); | ||
const { ElectroInstance, KeyTypes, QueryTypes, MethodTypes, Comparisons, ExpressionTypes, ModelVersions } = require("./types"); | ||
const { FilterFactory, FilterTypes } = require("./filters"); | ||
const { WhereFactory } = require("./where"); | ||
const { clauses } = require("./clauses"); | ||
const validations = require("./validations"); | ||
const { clauses } = require("./clauses"); | ||
const utilities = require("./util"); | ||
@@ -13,17 +14,10 @@ class Entity { | ||
this.client = config.client; | ||
this.model = this._parseModel(model); | ||
this._filterBuilder = new FilterFactory( | ||
this.model.schema.attributes, | ||
FilterTypes, | ||
); | ||
this._whereBuilder = new WhereFactory( | ||
this.model.schema.attributes, | ||
FilterTypes | ||
) | ||
this._clausesWithFilters = this._filterBuilder.injectFilterClauses( | ||
clauses, | ||
this.model.filters, | ||
); | ||
this.model = this._parseModel(model, config); | ||
/** start beta/v1 condition **/ | ||
this.model.table = config.table || model.table; | ||
/** end beta/v1 condition **/ | ||
this._filterBuilder = new FilterFactory(this.model.schema.attributes, FilterTypes); | ||
this._whereBuilder = new WhereFactory(this.model.schema.attributes, FilterTypes); | ||
this._clausesWithFilters = this._filterBuilder.injectFilterClauses(clauses, this.model.filters); | ||
this._clausesWithFilters = this._whereBuilder.injectWhereClauses(this._clausesWithFilters); | ||
this.scan = this._makeChain("", this._clausesWithFilters, clauses.index).scan(); | ||
@@ -34,11 +28,24 @@ this.query = {}; | ||
this.query[accessPattern] = (...values) => { | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index).query( | ||
...values, | ||
); | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index).query(...values); | ||
}; | ||
} | ||
this.modelAttributeIdentifier = "__edb_e__" | ||
config.identifiers = config.identifiers || {}; | ||
this.identifiers = { | ||
entity: config.identifiers.entity || "__edb_e__", | ||
version: config.identifiers.version || "__edb_v__", | ||
}; | ||
this._instance = ElectroInstance.entity; | ||
} | ||
setIdentifier(type = "", identifier = "") { | ||
if (!this.identifiers[type]) { | ||
throw new Error(`Invalid identifier type: ${type}. Valid indentifiers include ${Object.keys(this.identifiers[type]).join(", ")}`); | ||
} | ||
if (typeof identifier === "string" && identifier.length > 0) { | ||
this.identifiers[type] = identifier; | ||
} else { | ||
throw new Error(`Invalid Identifier. Value must be string with length greater than zero.`); | ||
} | ||
} | ||
find(facets = {}) { | ||
@@ -71,3 +78,10 @@ let match = this._findBestIndexKeyMatch(facets); | ||
collection(collection = "", clauses = {}, facets = {}) { | ||
collection(collection = "", clauses = {}, facets = {}, expressions = {}) { | ||
let options = { | ||
expressions: { | ||
names: expressions.names || {}, | ||
values: expressions.values|| {}, | ||
expression: expressions.expression || "" | ||
} | ||
}; | ||
let index = this.model.translations.collections.fromCollectionToIndex[ | ||
@@ -79,5 +93,5 @@ collection | ||
} | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index).collection( | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index, options).collection( | ||
collection, | ||
facets, | ||
facets | ||
); | ||
@@ -111,3 +125,3 @@ } | ||
} | ||
} | ||
}; | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index, options).create(attributes); | ||
@@ -127,3 +141,3 @@ } | ||
} | ||
} | ||
}; | ||
return this._makeChain(index, this._clausesWithFilters, clauses.index, options).patch(facets); | ||
@@ -225,4 +239,4 @@ } | ||
} | ||
if (config.pager) { | ||
@@ -274,3 +288,3 @@ let nextPage = response.LastEvaluatedKey || null; | ||
let match = key.match(regex); | ||
let results = {} | ||
let results = {}; | ||
if (!match) { | ||
@@ -312,3 +326,3 @@ if (Object.keys(backupFacets || {}).length === 0) { | ||
} | ||
let pager = this._deconstructIndex(index, lastEvaluated, lastReturned); | ||
@@ -318,7 +332,7 @@ let tableIndex = ""; | ||
if (index !== tableIndex) { | ||
pager = {...pager, ...this._deconstructIndex(tableIndex, lastEvaluated, lastReturned)}; | ||
pager = {...pager, ...this._deconstructIndex(tableIndex, lastEvaluated, lastReturned)}; | ||
} | ||
if (Object.keys(pager).length === 0) { | ||
// In this case no suitable record could be found be the deconstructed pager. | ||
// In this case no suitable record could be found be the deconstructed pager. | ||
// This can be valid in cases where a scan is performed but returns no results. | ||
@@ -332,4 +346,4 @@ return null; | ||
_constructPagerIndex(index = "", item) { | ||
let pk = this._expectFacets(item, this.model.facets.byIndex[index].pk) | ||
let sk = this._expectFacets(item, this.model.facets.byIndex[index].sk) | ||
let pk = this._expectFacets(item, this.model.facets.byIndex[index].pk); | ||
let sk = this._expectFacets(item, this.model.facets.byIndex[index].sk); | ||
let keys = this._makeIndexKeys(index, pk, sk); | ||
@@ -350,3 +364,3 @@ return this._makeParameterKey(index, keys.pk, ...keys.sk); | ||
} | ||
_applyParameterOptions(params, ...options) { | ||
@@ -423,3 +437,3 @@ let config = { | ||
_makeCreateConditions(index) { | ||
let filter = [`attribute_not_exists(pk)`] | ||
let filter = [`attribute_not_exists(pk)`]; | ||
if (this.model.lookup.indexHasSortKeys[index]) { | ||
@@ -432,3 +446,3 @@ filter.push(`attribute_not_exists(sk)`); | ||
_makePatchConditions(index) { | ||
let filter = [`attribute_exists(pk)`] | ||
let filter = [`attribute_exists(pk)`]; | ||
if (this.model.lookup.indexHasSortKeys[index]) { | ||
@@ -473,3 +487,2 @@ filter.push(`attribute_exists(sk)`); | ||
case MethodTypes.patch: | ||
case MethodTypes.patch: | ||
params = this._makeUpdateParams( | ||
@@ -505,2 +518,16 @@ update, | ||
getIdentifierExpressions() { | ||
return { | ||
names: { | ||
[`#${this.identifiers.entity}_${this.model.entity}`]: this.identifiers.entity, | ||
[`#${this.identifiers.version}_${this.model.entity}`]: this.identifiers.version, | ||
}, | ||
values: { | ||
[`:${this.identifiers.entity}_${this.model.entity}`]: this.model.entity, | ||
[`:${this.identifiers.version}_${this.model.entity}`]: this.model.version, | ||
}, | ||
expression: `(#${this.identifiers.entity}_${this.model.entity} = :${this.identifiers.entity}_${this.model.entity} AND #${this.identifiers.version}_${this.model.entity} = :${this.identifiers.version}_${this.model.entity})` | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -531,5 +558,7 @@ _makeScanParam(filter = {}) { | ||
}; | ||
params.ExpressionAttributeNames["#" + this.modelAttributeIdentifier] = this.modelAttributeIdentifier; | ||
params.ExpressionAttributeValues[":" + this.modelAttributeIdentifier] = this.model.entity; | ||
params.FilterExpression = `${params.FilterExpression} AND #${this.modelAttributeIdentifier} = :${this.modelAttributeIdentifier}` | ||
params.ExpressionAttributeNames["#" + this.identifiers.entity] = this.identifiers.entity; | ||
params.ExpressionAttributeNames["#" + this.identifiers.version] = this.identifiers.version; | ||
params.ExpressionAttributeValues[":" + this.identifiers.entity] = this.model.entity; | ||
params.ExpressionAttributeValues[":" + this.identifiers.version] = this.model.version; | ||
params.FilterExpression = `${params.FilterExpression} AND #${this.identifiers.entity} = :${this.identifiers.entity} AND #${this.identifiers.version} = :${this.identifiers.version}`; | ||
if (hasSortKey) { | ||
@@ -549,4 +578,3 @@ params.FilterExpression = `${params.FilterExpression} AND begins_with(#sk, :sk))`; | ||
let TableName = this.model.table; | ||
let params = {Key, TableName}; | ||
return params; | ||
return {Key, TableName}; | ||
} | ||
@@ -569,3 +597,3 @@ | ||
let params = { | ||
return { | ||
UpdateExpression, | ||
@@ -577,3 +605,2 @@ ExpressionAttributeNames, | ||
}; | ||
return params; | ||
} | ||
@@ -586,11 +613,11 @@ | ||
let transatedFields = this.model.schema.translateToFields(setAttributes); | ||
let params = { | ||
return { | ||
Item: { | ||
...transatedFields, | ||
...updatedKeys, | ||
[this.modelAttributeIdentifier]: this.model.entity, | ||
[this.identifiers.entity]: this.model.entity, | ||
[this.identifiers.version]: this.model.version, | ||
}, | ||
TableName: this.model.table, | ||
}; | ||
return params; | ||
} | ||
@@ -629,3 +656,3 @@ | ||
/* istanbul ignore next */ | ||
_expressionAttributeBuilder(item = {}, options = {}, {noDuplicateNames} = {}) { | ||
_expressionAttributeBuilder(item = {}, options = {}) { | ||
let { | ||
@@ -706,2 +733,3 @@ require = [], | ||
parameters = this._makeBeginsWithQueryParams( | ||
chainState.options, | ||
chainState.index, | ||
@@ -715,2 +743,3 @@ chainState.filter, | ||
parameters = this._makeBeginsWithQueryParams( | ||
chainState.options, | ||
chainState.index, | ||
@@ -776,3 +805,3 @@ chainState.filter, | ||
_makeBeginsWithQueryParams(index, filter, pk, sk) { | ||
_makeBeginsWithQueryParams(options, index, filter, pk, sk) { | ||
let keyExpressions = this._queryKeyExpressionAttributeBuilder(index, pk, sk); | ||
@@ -783,7 +812,12 @@ let KeyConditionExpression = "#pk = :pk"; | ||
} | ||
let customExpressions = { | ||
names: (options.expressions && options.expressions.names) || {}, | ||
values: (options.expressions && options.expressions.values) || {}, | ||
expression: (options.expressions && options.expressions.expression) || "" | ||
}; | ||
let params = { | ||
KeyConditionExpression, | ||
TableName: this.model.table, | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes(filter.ExpressionAttributeNames, keyExpressions.ExpressionAttributeNames), | ||
ExpressionAttributeValues: this._mergeExpressionsAttributes(filter.ExpressionAttributeValues, keyExpressions.ExpressionAttributeValues), | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes(filter.ExpressionAttributeNames, keyExpressions.ExpressionAttributeNames, customExpressions.names), | ||
ExpressionAttributeValues: this._mergeExpressionsAttributes(filter.ExpressionAttributeValues, keyExpressions.ExpressionAttributeValues, customExpressions.values), | ||
}; | ||
@@ -793,4 +827,5 @@ if (index) { | ||
} | ||
if (filter.FilterExpression) { | ||
params.FilterExpression = filter.FilterExpression; | ||
let expressions = [customExpressions.expression, filter.FilterExpression].filter(Boolean).join(" AND "); | ||
if (expressions.length) { | ||
params.FilterExpression = expressions; | ||
} | ||
@@ -1035,3 +1070,3 @@ return params; | ||
_makeKeyPrefixes(service, entity, version = "1", tableIndex) { | ||
_makeKeyPrefixes(service, entity, version = "1", tableIndex, modelVersion) { | ||
/* | ||
@@ -1042,3 +1077,3 @@ Collections will prefix the sort key so they can be queried with | ||
of a customKey AND a collection, the collection is ignored to favor | ||
the custom key. | ||
the custom key. | ||
*/ | ||
@@ -1055,5 +1090,5 @@ | ||
} | ||
} | ||
}; | ||
let pk = `$${service}_${version}`; | ||
let pk = `$${service}`; | ||
let sk = ""; | ||
@@ -1068,2 +1103,10 @@ | ||
/** start beta/v1 condition **/ | ||
if (modelVersion === ModelVersions.v1) { | ||
sk = `${sk}_${version}`; | ||
} else { | ||
pk = `${pk}_${version}`; | ||
} | ||
/** end beta/v1 condition **/ | ||
// If no sk, append the sk properties to the pk | ||
@@ -1100,47 +1143,47 @@ if (Object.keys(tableIndex.sk).length === 0) { | ||
/* istanbul ignore next */ | ||
_getPrefixes({ collection = "", customFacets = {}, sk } = {}) { | ||
/* | ||
Collections will prefix the sort key so they can be queried with | ||
a "begins_with" operator when crossing entities. It is also possible | ||
that the user defined a custom key on either the PK or SK. In the case | ||
of a customKey AND a collection, the collection is ignored to favor | ||
the custom key. | ||
*/ | ||
// _getPrefixes({ collection = "", customFacets = {}, sk } = {}) { | ||
// /* | ||
// Collections will prefix the sort key so they can be queried with | ||
// a "begins_with" operator when crossing entities. It is also possible | ||
// that the user defined a custom key on either the PK or SK. In the case | ||
// of a customKey AND a collection, the collection is ignored to favor | ||
// the custom key. | ||
// */ | ||
// | ||
// let keys = { | ||
// pk: { | ||
// prefix: "", | ||
// isCustom: false, | ||
// }, | ||
// sk: { | ||
// prefix: "", | ||
// isCustom: false, | ||
// }, | ||
// }; | ||
// | ||
// if (collection) { | ||
// keys.pk.prefix = this.model.prefixes.pk; | ||
// keys.sk.prefix = `$${collection}#${this.model.entity}`; | ||
// } else { | ||
// keys.pk.prefix = this.model.prefixes.pk; | ||
// keys.sk.prefix = this.model.prefixes.sk; | ||
// } | ||
// | ||
// if (sk === undefined) { | ||
// keys.pk.prefix += keys.sk.prefix; | ||
// } | ||
// | ||
// if (customFacets.pk) { | ||
// keys.pk.prefix = ""; | ||
// keys.pk.isCustom = customFacets.pk; | ||
// } | ||
// | ||
// if (customFacets.sk) { | ||
// keys.sk.prefix = ""; | ||
// keys.sk.isCustom = customFacets.sk; | ||
// } | ||
// | ||
// return keys; | ||
// } | ||
let keys = { | ||
pk: { | ||
prefix: "", | ||
isCustom: false, | ||
}, | ||
sk: { | ||
prefix: "", | ||
isCustom: false, | ||
}, | ||
}; | ||
if (collection) { | ||
keys.pk.prefix = this.model.prefixes.pk; | ||
keys.sk.prefix = `$${collection}#${this.model.entity}`; | ||
} else { | ||
keys.pk.prefix = this.model.prefixes.pk; | ||
keys.sk.prefix = this.model.prefixes.sk; | ||
} | ||
if (sk === undefined) { | ||
keys.pk.prefix += keys.sk.prefix; | ||
} | ||
if (customFacets.pk) { | ||
keys.pk.prefix = ""; | ||
keys.pk.isCustom = customFacets.pk; | ||
} | ||
if (customFacets.sk) { | ||
keys.sk.prefix = ""; | ||
keys.sk.isCustom = customFacets.sk; | ||
} | ||
return keys; | ||
} | ||
/* istanbul ignore next */ | ||
@@ -1336,5 +1379,5 @@ _makeIndexKeys(index = "", pkFacets = {}, ...skFacets) { | ||
customFacets.pk = parsedPKFacets.isCustom; | ||
// labels can be set via the attribute definiton or as part of the facetTemplate. | ||
// labels can be set via the attribute definiton or as part of the facetTemplate. | ||
facets.labels = Object.assign({}, facets.labels, facetLabels); | ||
let pk = { | ||
@@ -1350,3 +1393,3 @@ accessPattern, | ||
let sk = {}; | ||
let parsedSKFacets = {} | ||
let parsedSKFacets = {}; | ||
if (hasSk) { | ||
@@ -1431,4 +1474,4 @@ parsedSKFacets = this._parseFacets(index.sk.facets); | ||
}; | ||
attributes.forEach(({index, type, name}, j) => { | ||
@@ -1452,3 +1495,3 @@ let next = attributes[j + 1] !== undefined ? attributes[j + 1].name : ""; | ||
} | ||
return { | ||
@@ -1482,7 +1525,7 @@ facets, | ||
_normalizePrefixes(service, entity, version, indexes) { | ||
_normalizePrefixes(service, entity, version, indexes, modelVersion) { | ||
let prefixes = {}; | ||
for (let accessPattern of Object.keys(indexes)) { | ||
let item = indexes[accessPattern]; | ||
prefixes[item.index] = this._makeKeyPrefixes(service, entity, version, item); | ||
prefixes[item.index] = this._makeKeyPrefixes(service, entity, version, item, modelVersion); | ||
} | ||
@@ -1492,5 +1535,27 @@ return prefixes; | ||
_parseModel(model) { | ||
let { service, entity, table, version = "1" } = model; | ||
_parseModel(model, config = {}) { | ||
/** start beta/v1 condition **/ | ||
let modelVersion = utilities.getModelVersion(model); | ||
let service, entity, version, table; | ||
switch(modelVersion) { | ||
case ModelVersions.beta: | ||
service = model.service; | ||
entity = model.entity; | ||
version = model.version; | ||
table = config.table || model.table; | ||
break; | ||
case ModelVersions.v1: | ||
service = model.model && model.model.service; | ||
entity = model.model && model.model.entity; | ||
version = model.model && model.model.version; | ||
table = config.table || model.table; | ||
break; | ||
default: | ||
throw new Error("Invalid model"); | ||
} | ||
if(typeof table !== "string" || table.length === 0) { | ||
throw new Error(`config.table must be string`); | ||
} | ||
/** end beta/v1 condition **/ | ||
let { | ||
@@ -1507,4 +1572,5 @@ facets, | ||
let filters = this._normalizeFilters(model.filters); | ||
let prefixes = this._normalizePrefixes(service, entity, version, indexes); | ||
let prefixes = this._normalizePrefixes(service, entity, version, indexes, modelVersion); | ||
return { | ||
modelVersion, | ||
service, | ||
@@ -1511,0 +1577,0 @@ version, |
const { Entity } = require("./entity"); | ||
const { clauses } = require("./clauses"); | ||
const { ElectroInstance } = require("./types"); | ||
const { ElectroInstance, ElectroInstanceTypes, ModelVersions } = require("./types"); | ||
const { FilterFactory, FilterTypes } = require("./filters"); | ||
const { getInstanceType, getModelVersion, applyBetaModelOverrides } = require("./util"); | ||
const v = require("./validations"); | ||
class Service { | ||
constructor(service = {}, config = {}) { | ||
this.service = { | ||
name: service.service, | ||
table: service.table, | ||
version: service.version, | ||
}; | ||
constructor(service = "", config = {}) { | ||
this.service = {}; | ||
/** start beta/v1 condition **/ | ||
this._modelOverrides = {}; | ||
this._modelVersion = ModelVersions.v1; | ||
if (v.isObjectHasLength(service)) { | ||
this._modelVersion = ModelVersions.beta; | ||
this._modelOverrides = { | ||
table: service.table, | ||
service: service.service, | ||
version: service.version, | ||
}; | ||
} else if (v.isStringHasLength(service)) { | ||
this._modelVersion = ModelVersions.v1; | ||
this.service.name = service; | ||
this.service.table = config.table; | ||
this._modelOverrides.table = config.table; | ||
} else { | ||
throw new Error(`Invalid service name: ${JSON.stringify(service)}. Service name must have length greater than zero`); | ||
} | ||
/** end beta/v1 condition **/ | ||
this.config = config; | ||
@@ -22,14 +39,51 @@ this.client = config.client; | ||
join(model = {}, config = {}) { | ||
let name = model.entity; | ||
model.service = this.service.name; | ||
model.table = this.service.table; | ||
model.version = this.service.version; | ||
join(instance = {}, config = {}) { | ||
let options = { ...config, ...this.config }; | ||
this.entities[name] = new Entity(model, options); | ||
let entity = {}; | ||
let type = getInstanceType(instance); | ||
/** start beta/v1 condition **/ | ||
let modelVersion = getModelVersion(instance); | ||
/** end beta/v1 condition **/ | ||
switch(type) { | ||
case ElectroInstanceTypes.model: | ||
entity = new Entity(instance, options); | ||
break; | ||
case ElectroInstanceTypes.entity: | ||
entity = instance; | ||
break; | ||
default: | ||
/** start beta/v1 condition **/ | ||
if (modelVersion !== this._modelVersion) { | ||
throw new Error("Invalid instance: Valid instances to join include Models and Entity instances. Additionally, all models must be in the same format (v1 vs beta). Review https://github.com/tywalch/electrodb#version-v1-migration for more detail."); | ||
} else if (modelVersion === ModelVersions.beta) { | ||
instance = applyBetaModelOverrides(instance, this._modelOverrides); | ||
} else { | ||
throw new Error(`Invalid instance: Valid instances to join include Models and Entity instances.`); | ||
} | ||
entity = new Entity(instance, options); | ||
/** end beta/v1 condition **/ | ||
break; | ||
} | ||
let name = entity.model.entity; | ||
if (this.service.name !== this.service.name) { | ||
throw new Error(``) | ||
} | ||
if (this.service.table) { | ||
entity.table = this.service.table; | ||
} | ||
if (this.service.version) { | ||
entity.model.version = this.service.version; | ||
} | ||
this.entities[name] = entity; | ||
for (let collection of this.entities[name].model.collections) { | ||
this._addCollectionEntity(collection, name, this.entities[name]); | ||
this.collections[collection] = (...facets) => { | ||
let { entities, attributes } = this.collectionSchema[collection]; | ||
return this._makeCollectionChain(collection, attributes, clauses, Object.values(entities)[0], ...facets); | ||
let { entities, attributes, identifiers } = this.collectionSchema[collection]; | ||
return this._makeCollectionChain(collection, attributes, clauses, identifiers, Object.values(entities)[0], ...facets); | ||
}; | ||
@@ -41,6 +95,6 @@ } | ||
_makeCollectionChain(name = "", attributes = {}, clauses = {}, entity = {}, facets = {}) { | ||
_makeCollectionChain(name = "", attributes = {}, clauses = {}, identifiers = {}, entity = {}, facets = {}) { | ||
let filterBuilder = new FilterFactory(attributes, FilterTypes); | ||
clauses = filterBuilder.injectFilterClauses(clauses); | ||
return new Proxy(entity.collection(name, clauses, facets), { | ||
return new Proxy(entity.collection(name, clauses, facets, identifiers), { | ||
get: (target, prop) => { | ||
@@ -174,9 +228,32 @@ if (prop === "go") { | ||
attributes: {}, | ||
identifiers: { | ||
names: {}, | ||
values: {}, | ||
expression: "" | ||
} | ||
}; | ||
if (this.collectionSchema[collection].entities[name] !== undefined) { | ||
throw new Error(`Entity with name ${name} has already been joined to this service.`); | ||
} | ||
this.collectionSchema[collection].keys = this._processEntityKeys(this.collectionSchema[collection].keys, providedIndex); | ||
this.collectionSchema[collection].attributes = this._processEntityAttributes(this.collectionSchema[collection].attributes, entity.model.schema.attributes); | ||
this.collectionSchema[collection].entities[name] = entity; | ||
this.collectionSchema[collection].identifiers = this._processEntityIdentifiers(this.collectionSchema[collection].identifiers, entity.getIdentifierExpressions()); | ||
} | ||
_processEntityIdentifiers(existing = {}, {names, values, expression} = {}) { | ||
let identifiers = {}; | ||
if (names) { | ||
identifiers.names = Object.assign({}, existing.names, names); | ||
} | ||
if (values) { | ||
identifiers.values = Object.assign({}, existing.values, values); | ||
} | ||
if (expression) { | ||
identifiers.expression = [existing.expression, expression].filter(Boolean).join(" OR "); | ||
} | ||
return identifiers; | ||
} | ||
} | ||
module.exports = { Service }; |
@@ -53,9 +53,22 @@ const KeyTypes = { | ||
FilterExpression: "FilterExpression" | ||
} | ||
}; | ||
const ElectroInstance = { | ||
entity: Symbol("entity"), | ||
service: Symbol("service") | ||
} | ||
service: Symbol("service"), | ||
electro: Symbol("electro"), | ||
}; | ||
const ElectroInstanceTypes = { | ||
electro: "electro", | ||
service: "service", | ||
entity: "entity", | ||
model: "model" | ||
}; | ||
const ModelVersions = { | ||
beta: "beta", | ||
v1: "v1" | ||
}; | ||
module.exports = { | ||
@@ -67,5 +80,7 @@ KeyTypes, | ||
Comparisons, | ||
ModelVersions, | ||
AttributeTypes, | ||
ExpressionTypes, | ||
ElectroInstance, | ||
ElectroInstanceTypes, | ||
}; |
@@ -104,6 +104,45 @@ const Validator = require("jsonschema").Validator; | ||
const Model = { | ||
const Modelv1= { | ||
type: "object", | ||
required: true, | ||
properties: { | ||
model: { | ||
type: "object", | ||
required: true, | ||
properties: { | ||
entity: { | ||
type: "string", | ||
required: true | ||
}, | ||
version: { | ||
type: "string", | ||
required: true | ||
}, | ||
service: { | ||
type: "string", | ||
required: true | ||
} | ||
} | ||
}, | ||
attributes: { | ||
type: "object", | ||
patternProperties: { | ||
["."]: { $ref: "/Attribute" }, | ||
}, | ||
}, | ||
indexes: { | ||
type: "object", | ||
minProperties: 1, | ||
patternProperties: { | ||
["."]: { $ref: "/Index" }, | ||
}, | ||
}, | ||
filters: { $ref: "/Filters" }, | ||
}, | ||
}; | ||
const ModelBeta = { | ||
type: "object", | ||
required: true, | ||
properties: { | ||
service: { | ||
@@ -119,3 +158,2 @@ type: "string", | ||
type: "string", | ||
required: true, | ||
}, | ||
@@ -157,29 +195,63 @@ version: { | ||
v.addSchema(Filters, "/Filters"); | ||
v.addSchema(Model, "/Model"); | ||
v.addSchema(ModelBeta, "/ModelBeta"); | ||
v.addSchema(Modelv1, "/Modelv1"); | ||
function validateModel(model = {}) { | ||
let errors = v.validate(model, "/Model").errors; | ||
if (errors.length) { | ||
throw new Error( | ||
errors | ||
.map((err) => { | ||
let message = `${err.property}`; | ||
switch (err.argument) { | ||
case "isFunction": | ||
return `${message} must be a function`; | ||
case "isFunctionOrString": | ||
return `${message} must be either a function or string`; | ||
case "isFunctionOrRegexp": | ||
return `${message} must be either a function or Regexp`; | ||
default: | ||
return `${message} ${err.message}`; | ||
} | ||
}) | ||
.join(", "), | ||
); | ||
/** start beta/v1 condition **/ | ||
let betaErrors = v.validate(model, "/ModelBeta").errors; | ||
if (betaErrors.length) { | ||
/** end/v1 condition **/ | ||
let errors = v.validate(model, "/Modelv1").errors; | ||
if (errors.length) { | ||
throw new Error( | ||
errors | ||
.map((err) => { | ||
let message = `${err.property}`; | ||
switch (err.argument) { | ||
case "isFunction": | ||
return `${message} must be a function`; | ||
case "isFunctionOrString": | ||
return `${message} must be either a function or string`; | ||
case "isFunctionOrRegexp": | ||
return `${message} must be either a function or Regexp`; | ||
default: | ||
return `${message} ${err.message}`; | ||
} | ||
}) | ||
.join(", "), | ||
); | ||
} | ||
} | ||
} | ||
function testModel(model) { | ||
let isModel = false; | ||
let error = ""; | ||
try { | ||
validateModel(model); | ||
isModel = true; | ||
} catch(err) { | ||
error = err.message; | ||
} | ||
return [isModel, error]; | ||
} | ||
function isStringHasLength(str) { | ||
return typeof str === "string" && str.length > 0; | ||
} | ||
function isObjectHasLength(obj) { | ||
return typeof obj === "object" && Object.keys(obj).length > 0; | ||
} | ||
function isArrayHasLength(arr) { | ||
return Array.isArray(arr) && arr.length > 0; | ||
} | ||
module.exports = { | ||
model: validateModel, | ||
testModel, | ||
isArrayHasLength, | ||
isStringHasLength, | ||
isObjectHasLength, | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
219411
21
3256
2344