@balena/odata-to-abstract-sql
Advanced tools
Comparing version 5.1.1 to 5.2.0-named-keys-1aa78f8bcec04b0434bf381e3beb7e4558ce2e3a
@@ -7,5 +7,9 @@ # Change Log | ||
## 5.1.1 - 2020-07-13 | ||
## 5.2.0 - 2020-07-17 | ||
* Add support for specifying named keys [Pagan Gazzard] | ||
## 5.1.1 - 2020-07-10 | ||
<details> | ||
@@ -12,0 +16,0 @@ <summary> Improve typings [Pagan Gazzard] </summary> |
@@ -61,4 +61,5 @@ import * as _ from 'lodash'; | ||
PathSegment(method: string, bodyKeys: string[], path: ODataQuery): Query; | ||
PathKey(method: string, path: ODataQuery, resource: Resource, referencedField: ReferencedFieldNode, bodyKeys: string[]): BooleanTypeNodes | void; | ||
Bind(bind: BindReference, _optional?: boolean): AbstractSqlType | undefined; | ||
PathKey(method: string, path: ODataQuery, resource: Resource, bodyKeys: string[]): BooleanTypeNodes | void; | ||
Bind(bind: BindReference, optional: true): AbstractSqlType | undefined; | ||
Bind(bind: BindReference, optional?: false): AbstractSqlType; | ||
SelectFilter(filter: FilterOption, query: Query, resource: Resource): void; | ||
@@ -98,3 +99,3 @@ OrderBy(orderby: OrderByOption, query: Query, resource: Resource): void; | ||
NumberMatch(match: any): NumberTypeNodes; | ||
NullMatch(match: any): AbstractSqlType | undefined; | ||
NullMatch(match: any, _optional?: true): AbstractSqlType | undefined; | ||
TextMatch(match: any, optional: true): AbstractSqlType | undefined; | ||
@@ -101,0 +102,0 @@ TextMatch(match: any): AbstractSqlType; |
@@ -111,2 +111,14 @@ "use strict"; | ||
}; | ||
const isBindReference = (maybeBind) => { | ||
return (maybeBind != null && | ||
'bind' in maybeBind && | ||
(typeof maybeBind.bind === 'string' || typeof maybeBind.bind === 'number')); | ||
}; | ||
const addBodyKey = (resourceName, fieldName, bind, bodyKeys, extraBodyVars) => { | ||
const qualifiedIDField = resourceName + '.' + fieldName; | ||
if (!bodyKeys.includes(qualifiedIDField) && !bodyKeys.includes(fieldName)) { | ||
bodyKeys.push(qualifiedIDField); | ||
extraBodyVars[qualifiedIDField] = bind; | ||
} | ||
}; | ||
class OData2AbstractSQL { | ||
@@ -236,3 +248,3 @@ constructor(clientModel, methods = {}) { | ||
]; | ||
const pathKeyWhere = this.PathKey(method, path, resource, referencedIdField, bodyKeys); | ||
const pathKeyWhere = this.PathKey(method, path, resource, bodyKeys); | ||
let addPathKey = true; | ||
@@ -270,5 +282,13 @@ if (hasQueryOpts && ((_a = path.options) === null || _a === void 0 ? void 0 : _a.$expand)) { | ||
} | ||
const linkKeyWhere = this.PathKey(method, path.link, linkResource, referencedField, bodyKeys); | ||
if (linkKeyWhere) { | ||
query.where.push(linkKeyWhere); | ||
if (path.link.key != null) { | ||
if (isBindReference(path.link.key)) { | ||
query.where.push([ | ||
comparison.eq, | ||
referencedField, | ||
this.Bind(path.link.key), | ||
]); | ||
} | ||
else { | ||
throw new SyntaxError('Cannot use named keys with $links'); | ||
} | ||
} | ||
@@ -393,25 +413,46 @@ query.select.push(aliasedField); | ||
} | ||
PathKey(method, path, resource, referencedField, bodyKeys) { | ||
PathKey(method, path, resource, bodyKeys) { | ||
if (path.key != null) { | ||
if (method === 'PUT' || method === 'PUT-INSERT' || method === 'POST') { | ||
const qualifiedIDField = resource.resourceName + '.' + resource.idField; | ||
if (!bodyKeys.includes(qualifiedIDField) && | ||
!bodyKeys.includes(resource.idField)) { | ||
bodyKeys.push(qualifiedIDField); | ||
this.extraBodyVars[qualifiedIDField] = path.key; | ||
if (isBindReference(path.key)) { | ||
addBodyKey(resource.resourceName, resource.idField, path.key, bodyKeys, this.extraBodyVars); | ||
} | ||
} | ||
for (const matcher of [this.Bind, this.NumberMatch, this.TextMatch]) { | ||
const key = matcher.call(this, path.key, true); | ||
if (key) { | ||
return [comparison.eq, referencedField, key]; | ||
else { | ||
for (const [fieldName, bind] of Object.entries(path.key)) { | ||
addBodyKey(resource.resourceName, fieldName, bind, bodyKeys, this.extraBodyVars); | ||
} | ||
} | ||
} | ||
throw new SyntaxError('Could not match path key'); | ||
if (isBindReference(path.key)) { | ||
const key = this.Bind(path.key); | ||
const referencedField = [ | ||
'ReferencedField', | ||
resource.tableAlias, | ||
resource.idField, | ||
]; | ||
return [comparison.eq, referencedField, key]; | ||
} | ||
const namedKeys = Object.entries(path.key).map(([fieldName, bind]) => { | ||
const key = this.Bind(bind); | ||
const referencedField = [ | ||
'ReferencedField', | ||
resource.tableAlias, | ||
fieldName, | ||
]; | ||
return [comparison.eq, referencedField, key]; | ||
}); | ||
if (namedKeys.length === 1) { | ||
return namedKeys[0]; | ||
} | ||
return ['And', ...namedKeys]; | ||
} | ||
} | ||
Bind(bind, _optional) { | ||
if (bind != null && bind.bind != null) { | ||
Bind(bind, optional = false) { | ||
if (isBindReference(bind)) { | ||
return ['Bind', bind.bind]; | ||
} | ||
if (optional) { | ||
return; | ||
} | ||
throw new SyntaxError(`Could not match bind reference`); | ||
} | ||
@@ -856,3 +897,3 @@ SelectFilter(filter, query, resource) { | ||
} | ||
NullMatch(match) { | ||
NullMatch(match, _optional) { | ||
if (match === null) { | ||
@@ -859,0 +900,0 @@ return ['Null']; |
{ | ||
"name": "@balena/odata-to-abstract-sql", | ||
"version": "5.1.1", | ||
"version": "5.2.0-named-keys-1aa78f8bcec04b0434bf381e3beb7e4558ce2e3a", | ||
"description": "A consumer of the OData parser, written in OMeta", | ||
@@ -21,3 +21,3 @@ "main": "out/odata-to-abstract-sql.js", | ||
"@balena/abstract-sql-compiler": "^7.0.2", | ||
"@balena/odata-parser": "^2.0.1", | ||
"@balena/odata-parser": "^2.1.0-named-keys-926615afa77b3c67db8429a03ac5437838fbf939", | ||
"@types/lodash": "^4.14.157", | ||
@@ -24,0 +24,0 @@ "@types/memoizee": "^0.4.4", |
@@ -222,2 +222,27 @@ import * as _ from 'lodash'; | ||
const isBindReference = (maybeBind: { | ||
[key: string]: unknown; | ||
}): maybeBind is BindReference => { | ||
return ( | ||
maybeBind != null && | ||
'bind' in maybeBind && | ||
(typeof maybeBind.bind === 'string' || typeof maybeBind.bind === 'number') | ||
); | ||
}; | ||
const addBodyKey = ( | ||
resourceName: string, | ||
fieldName: string, | ||
bind: BindReference, | ||
bodyKeys: string[], | ||
extraBodyVars: _.Dictionary<BindReference>, | ||
) => { | ||
// Add the id field value to the body if it doesn't already exist and we're doing an INSERT or a REPLACE. | ||
const qualifiedIDField = resourceName + '.' + fieldName; | ||
if (!bodyKeys.includes(qualifiedIDField) && !bodyKeys.includes(fieldName)) { | ||
bodyKeys.push(qualifiedIDField); | ||
extraBodyVars[qualifiedIDField] = bind; | ||
} | ||
}; | ||
export class OData2AbstractSQL { | ||
@@ -369,9 +394,3 @@ private extraBodyVars: _.Dictionary<BindReference> = {}; | ||
]; | ||
const pathKeyWhere = this.PathKey( | ||
method, | ||
path, | ||
resource, | ||
referencedIdField, | ||
bodyKeys, | ||
); | ||
const pathKeyWhere = this.PathKey(method, path, resource, bodyKeys); | ||
let addPathKey = true; | ||
@@ -416,11 +435,12 @@ | ||
} | ||
const linkKeyWhere = this.PathKey( | ||
method, | ||
path.link, | ||
linkResource, | ||
referencedField, | ||
bodyKeys, | ||
); | ||
if (linkKeyWhere) { | ||
query.where.push(linkKeyWhere); | ||
if (path.link.key != null) { | ||
if (isBindReference(path.link.key)) { | ||
query.where.push([ | ||
comparison.eq, | ||
referencedField, | ||
this.Bind(path.link.key), | ||
]); | ||
} else { | ||
throw new SyntaxError('Cannot use named keys with $links'); | ||
} | ||
} | ||
@@ -581,3 +601,2 @@ query.select.push(aliasedField); | ||
resource: Resource, | ||
referencedField: ReferencedFieldNode, | ||
bodyKeys: string[], | ||
@@ -587,25 +606,58 @@ ): BooleanTypeNodes | void { | ||
if (method === 'PUT' || method === 'PUT-INSERT' || method === 'POST') { | ||
// Add the id field value to the body if it doesn't already exist and we're doing an INSERT or a REPLACE. | ||
const qualifiedIDField = resource.resourceName + '.' + resource.idField; | ||
if ( | ||
!bodyKeys.includes(qualifiedIDField) && | ||
!bodyKeys.includes(resource.idField) | ||
) { | ||
bodyKeys.push(qualifiedIDField); | ||
this.extraBodyVars[qualifiedIDField] = path.key; | ||
if (isBindReference(path.key)) { | ||
addBodyKey( | ||
resource.resourceName, | ||
resource.idField, | ||
path.key, | ||
bodyKeys, | ||
this.extraBodyVars, | ||
); | ||
} else { | ||
for (const [fieldName, bind] of Object.entries(path.key)) { | ||
addBodyKey( | ||
resource.resourceName, | ||
fieldName, | ||
bind, | ||
bodyKeys, | ||
this.extraBodyVars, | ||
); | ||
} | ||
} | ||
} | ||
for (const matcher of [this.Bind, this.NumberMatch, this.TextMatch]) { | ||
const key = matcher.call(this, path.key, true); | ||
if (key) { | ||
if (isBindReference(path.key)) { | ||
const key = this.Bind(path.key); | ||
const referencedField: ReferencedFieldNode = [ | ||
'ReferencedField', | ||
resource.tableAlias!, | ||
resource.idField, | ||
]; | ||
return [comparison.eq, referencedField, key]; | ||
} | ||
const namedKeys = Object.entries(path.key).map( | ||
([fieldName, bind]): BooleanTypeNodes => { | ||
const key = this.Bind(bind); | ||
const referencedField: ReferencedFieldNode = [ | ||
'ReferencedField', | ||
resource.tableAlias!, | ||
fieldName, | ||
]; | ||
return [comparison.eq, referencedField, key]; | ||
} | ||
}, | ||
); | ||
if (namedKeys.length === 1) { | ||
return namedKeys[0]; | ||
} | ||
throw new SyntaxError('Could not match path key'); | ||
return ['And', ...namedKeys]; | ||
} | ||
} | ||
Bind(bind: BindReference, _optional?: boolean): AbstractSqlType | undefined { | ||
if (bind != null && bind.bind != null) { | ||
Bind(bind: BindReference, optional: true): AbstractSqlType | undefined; | ||
Bind(bind: BindReference, optional?: false): AbstractSqlType; | ||
Bind(bind: BindReference, optional = false): AbstractSqlType | undefined { | ||
if (isBindReference(bind)) { | ||
return ['Bind', bind.bind]; | ||
} | ||
if (optional) { | ||
return; | ||
} | ||
throw new SyntaxError(`Could not match bind reference`); | ||
} | ||
@@ -1116,3 +1168,3 @@ SelectFilter(filter: FilterOption, query: Query, resource: Resource) { | ||
} | ||
NullMatch(match: any): AbstractSqlType | undefined { | ||
NullMatch(match: any, _optional?: true): AbstractSqlType | undefined { | ||
if (match === null) { | ||
@@ -1119,0 +1171,0 @@ return ['Null']; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
377654
2895
2