Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sap-ux/annotation-converter

Package Overview
Dependencies
Maintainers
3
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap-ux/annotation-converter - npm Package Compare versions

Comparing version 0.6.16 to 0.7.0

12

CHANGELOG.md
# @sap-ux/annotation-converter
## 0.7.0
### Minor Changes
- e70d625: - NavigationPropertyBindings are now resolved by the annotation converter. This is a breaking change for consumers of types `RawSingleton` or `RawEntitySet` from package @sap-ux/vocabularies-types (the type of property `navigationPropertyBinding` changed).
- Annotations of action parameters are now also resolved for unbound actions and unbound functions. The fully-qualified name of unbound actions and unbound functions changed - they now always include their overloads. E.g., in case of unbound actions: old `myAction`, new: `myAction()` - `()` denotes the "unbound overload".
### Patch Changes
- Updated dependencies [e70d625]
- @sap-ux/vocabularies-types@0.8.0
## 0.6.16

@@ -4,0 +16,0 @@

105

dist/converter.js

@@ -463,13 +463,13 @@ "use strict";

(0, utils_1.lazy)(record, 'ActionTarget', () => {
var _a, _b, _c;
const actionTargetFQN = converter.unalias((_a = record.Action) === null || _a === void 0 ? void 0 : _a.toString());
var _a, _b;
const actionName = converter.unalias((_a = record.Action) === null || _a === void 0 ? void 0 : _a.toString());
// (1) Bound action of the annotation target?
let actionTarget = (_b = currentTarget.actions) === null || _b === void 0 ? void 0 : _b[actionTargetFQN];
let actionTarget = currentTarget.actions[actionName];
if (!actionTarget) {
// (2) ActionImport (= unbound action)?
actionTarget = (_c = converter.getConvertedActionImport(actionTargetFQN)) === null || _c === void 0 ? void 0 : _c.action;
actionTarget = (_b = converter.getConvertedActionImport(actionName)) === null || _b === void 0 ? void 0 : _b.action;
}
if (!actionTarget) {
// (3) Bound action of a different EntityType
actionTarget = converter.getConvertedAction(actionTargetFQN);
// (3) Bound action of a different EntityType (the actionName is fully qualified in this case)
actionTarget = converter.getConvertedAction(actionName);
if (!(actionTarget === null || actionTarget === void 0 ? void 0 : actionTarget.isBound)) {

@@ -480,3 +480,3 @@ actionTarget = undefined;

if (!actionTarget) {
converter.logError(`${record.fullyQualifiedName}: Unable to resolve '${record.Action}' ('${actionTargetFQN}')`);
converter.logError(`${record.fullyQualifiedName}: Unable to resolve '${record.Action}' ('${actionName}')`);
}

@@ -728,18 +728,9 @@ return actionTarget;

}
function resolveNavigationPropertyBindings(converter, rawNavigationPropertyBindings, rawElement) {
return () => Object.keys(rawNavigationPropertyBindings).reduce((navigationPropertyBindings, bindingName) => {
const rawBindingTarget = rawNavigationPropertyBindings[bindingName];
(0, utils_1.lazy)(navigationPropertyBindings, bindingName, () => {
let resolvedBindingTarget;
if (rawBindingTarget._type === 'Singleton') {
resolvedBindingTarget = converter.getConvertedSingleton(rawBindingTarget.fullyQualifiedName);
}
else {
resolvedBindingTarget = converter.getConvertedEntitySet(rawBindingTarget.fullyQualifiedName);
}
if (!resolvedBindingTarget) {
converter.logError(`${rawElement._type} '${rawElement.fullyQualifiedName}': Failed to resolve NavigationPropertyBinding ${bindingName}`);
resolvedBindingTarget = {};
}
return resolvedBindingTarget;
function resolveNavigationPropertyBindings(converter, rawNavigationPropertyBindings) {
return () => Object.keys(rawNavigationPropertyBindings).reduce((navigationPropertyBindings, bindingPath) => {
const rawBindingTarget = rawNavigationPropertyBindings[bindingPath];
(0, utils_1.lazy)(navigationPropertyBindings, bindingPath, () => {
var _a;
// the NavigationPropertyBinding will lead to either an EntitySet or a Singleton, it cannot be undefined
return (((_a = converter.getConvertedEntitySet(rawBindingTarget)) !== null && _a !== void 0 ? _a : converter.getConvertedSingleton(rawBindingTarget)));
});

@@ -812,5 +803,5 @@ return navigationPropertyBindings;

(0, utils_1.lazy)(convertedSingleton, 'entityType', resolveEntityType(converter, rawSingleton.entityTypeName));
(0, utils_1.lazy)(convertedSingleton, 'annotations', resolveAnnotations(converter, rawSingleton));
(0, utils_1.lazy)(convertedSingleton, 'annotations', resolveAnnotations(converter, convertedSingleton));
const _rawNavigationPropertyBindings = rawSingleton.navigationPropertyBinding;
(0, utils_1.lazy)(convertedSingleton, 'navigationPropertyBinding', resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings, rawSingleton));
(0, utils_1.lazy)(convertedSingleton, 'navigationPropertyBinding', resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings));
return convertedSingleton;

@@ -828,5 +819,5 @@ }

(0, utils_1.lazy)(convertedEntitySet, 'entityType', resolveEntityType(converter, rawEntitySet.entityTypeName));
(0, utils_1.lazy)(convertedEntitySet, 'annotations', resolveAnnotations(converter, rawEntitySet));
(0, utils_1.lazy)(convertedEntitySet, 'annotations', resolveAnnotations(converter, convertedEntitySet));
const _rawNavigationPropertyBindings = rawEntitySet.navigationPropertyBinding;
(0, utils_1.lazy)(convertedEntitySet, 'navigationPropertyBinding', resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings, rawEntitySet));
(0, utils_1.lazy)(convertedEntitySet, 'navigationPropertyBinding', resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings));
return convertedEntitySet;

@@ -919,3 +910,12 @@ }

(0, utils_1.lazy)(convertedActionImport, 'annotations', resolveAnnotations(converter, rawActionImport));
(0, utils_1.lazy)(convertedActionImport, 'action', () => converter.getConvertedAction(rawActionImport.actionName));
(0, utils_1.lazy)(convertedActionImport, 'action', () => {
const rawActions = converter.rawSchema.actions.filter((rawAction) => !rawAction.isBound && rawAction.fullyQualifiedName.startsWith(rawActionImport.actionName));
// this always resolves to a unique unbound action, but resolution of unbound functions can be ambiguous:
// unbound function FQNs have overloads depending on all of their parameters
if (rawActions.length > 1) {
converter.logError(`Ambiguous reference in action import: ${rawActionImport.fullyQualifiedName}`);
}
// return the first matching action or function
return converter.getConvertedAction(rawActions[0].fullyQualifiedName);
});
return convertedActionImport;

@@ -940,15 +940,26 @@ }

(0, utils_1.lazy)(convertedAction, 'annotations', () => {
const action = (0, utils_1.substringBeforeFirst)(rawAction.fullyQualifiedName, '(');
// if the action is unbound (e.g. "myAction"), the annotation target is "myAction()"
const annotationTargetFQN = rawAction.isBound
? rawAction.fullyQualifiedName
: `${rawAction.fullyQualifiedName}()`;
const rawAnnotations = converter.getAnnotations(annotationTargetFQN);
const baseAnnotations = converter.getAnnotations(action);
for (const baseAnnotation of baseAnnotations) {
if (!rawAnnotations.some((annotation) => annotation.term === baseAnnotation.term && annotation.qualifier === baseAnnotation.qualifier)) {
rawAnnotations.push(baseAnnotation);
/*
Annotation resolution rule for actions:
(1) annotation target: the specific unbound or bound overload, e.g.
- for actions: "x.y.z.unboundAction()" / "x.y.z.boundAction(x.y.z.Entity)"
- for functions: "x.y.z.unboundFunction(Edm.String)" / "x.y.z.unboundFunction(x.y.z.Entity,Edm.String)"
(2) annotation target: unspecified overload, e.g.
- for actions: "x.y.z.unboundAction" / "x.y.z.boundAction"
- for functions: "x.y.z.unboundFunction" / "x.y.z.unboundFunction"
When resolving (1) takes precedence over (2). That is, annotations on the specific overload overwrite
annotations on the unspecific overload, on term/qualifier level.
*/
const unspecificOverloadTarget = (0, utils_1.substringBeforeFirst)(rawAction.fullyQualifiedName, '(');
const specificOverloadTarget = rawAction.fullyQualifiedName;
const effectiveAnnotations = converter.getAnnotations(specificOverloadTarget);
const unspecificAnnotations = converter.getAnnotations(unspecificOverloadTarget);
for (const unspecificAnnotation of unspecificAnnotations) {
if (!effectiveAnnotations.some((annotation) => annotation.term === unspecificAnnotation.term &&
annotation.qualifier === unspecificAnnotation.qualifier)) {
effectiveAnnotations.push(unspecificAnnotation);
}
}
return createAnnotationsObject(converter, rawAction, rawAnnotations);
return createAnnotationsObject(converter, rawAction, effectiveAnnotations);
});

@@ -970,3 +981,17 @@ return convertedAction;

});
(0, utils_1.lazy)(convertedActionParameter, 'annotations', resolveAnnotations(converter, rawActionParameter));
(0, utils_1.lazy)(convertedActionParameter, 'annotations', () => {
// annotations on action parameters are resolved following the rules for actions
const unspecificOverloadTarget = rawActionParameter.fullyQualifiedName.substring(0, rawActionParameter.fullyQualifiedName.indexOf('(')) +
rawActionParameter.fullyQualifiedName.substring(rawActionParameter.fullyQualifiedName.indexOf(')') + 1);
const specificOverloadTarget = rawActionParameter.fullyQualifiedName;
const effectiveAnnotations = converter.getAnnotations(specificOverloadTarget);
const unspecificAnnotations = converter.getAnnotations(unspecificOverloadTarget);
for (const unspecificAnnotation of unspecificAnnotations) {
if (!effectiveAnnotations.some((annotation) => annotation.term === unspecificAnnotation.term &&
annotation.qualifier === unspecificAnnotation.qualifier)) {
effectiveAnnotations.push(unspecificAnnotation);
}
}
return createAnnotationsObject(converter, rawActionParameter, effectiveAnnotations);
});
return convertedActionParameter;

@@ -973,0 +998,0 @@ }

{
"name": "@sap-ux/annotation-converter",
"version": "0.6.16",
"version": "0.7.0",
"description": "SAP Fiori OData - Annotation converter",

@@ -17,6 +17,6 @@ "repository": {

"dependencies": {
"@sap-ux/vocabularies-types": "0.7.6"
"@sap-ux/vocabularies-types": "0.8.0"
},
"devDependencies": {
"@sap-ux/edmx-parser": "0.5.16"
"@sap-ux/edmx-parser": "0.6.0"
},

@@ -23,0 +23,0 @@ "scripts": {

@@ -30,2 +30,3 @@ import type {

RawMetadata,
RawNavigationPropertyBinding,
RawProperty,

@@ -709,15 +710,15 @@ RawSchema,

lazy(record, 'ActionTarget', () => {
const actionTargetFQN = converter.unalias(record.Action?.toString());
const actionName = converter.unalias(record.Action?.toString());
// (1) Bound action of the annotation target?
let actionTarget = currentTarget.actions?.[actionTargetFQN];
let actionTarget = currentTarget.actions[actionName];
if (!actionTarget) {
// (2) ActionImport (= unbound action)?
actionTarget = converter.getConvertedActionImport(actionTargetFQN)?.action;
actionTarget = converter.getConvertedActionImport(actionName)?.action;
}
if (!actionTarget) {
// (3) Bound action of a different EntityType
actionTarget = converter.getConvertedAction(actionTargetFQN);
// (3) Bound action of a different EntityType (the actionName is fully qualified in this case)
actionTarget = converter.getConvertedAction(actionName);
if (!actionTarget?.isBound) {

@@ -730,3 +731,3 @@ actionTarget = undefined;

converter.logError(
`${record.fullyQualifiedName}: Unable to resolve '${record.Action}' ('${actionTargetFQN}')`
`${record.fullyQualifiedName}: Unable to resolve '${record.Action}' ('${actionName}')`
);

@@ -1108,24 +1109,16 @@ }

converter: Converter,
rawNavigationPropertyBindings: Singleton['navigationPropertyBinding'] | EntitySet['navigationPropertyBinding'],
rawElement: RawSingleton | RawEntitySet
rawNavigationPropertyBindings: RawNavigationPropertyBinding
) {
return () =>
Object.keys(rawNavigationPropertyBindings).reduce((navigationPropertyBindings, bindingName) => {
const rawBindingTarget = rawNavigationPropertyBindings[bindingName];
Object.keys(rawNavigationPropertyBindings).reduce((navigationPropertyBindings, bindingPath) => {
const rawBindingTarget = rawNavigationPropertyBindings[bindingPath];
lazy(navigationPropertyBindings, bindingName, () => {
let resolvedBindingTarget;
if (rawBindingTarget._type === 'Singleton') {
resolvedBindingTarget = converter.getConvertedSingleton(rawBindingTarget.fullyQualifiedName);
} else {
resolvedBindingTarget = converter.getConvertedEntitySet(rawBindingTarget.fullyQualifiedName);
}
if (!resolvedBindingTarget) {
converter.logError(
`${rawElement._type} '${rawElement.fullyQualifiedName}': Failed to resolve NavigationPropertyBinding ${bindingName}`
);
resolvedBindingTarget = {} as any;
}
return resolvedBindingTarget;
});
lazy(
navigationPropertyBindings,
bindingPath,
() =>
// the NavigationPropertyBinding will lead to either an EntitySet or a Singleton, it cannot be undefined
(converter.getConvertedEntitySet(rawBindingTarget) ??
converter.getConvertedSingleton(rawBindingTarget))!
);
return navigationPropertyBindings;

@@ -1229,6 +1222,6 @@ }, {} as EntitySet['navigationPropertyBinding'] | Singleton['navigationPropertyBinding']);

function convertSingleton(converter: Converter, rawSingleton: RawSingleton): Singleton {
const convertedSingleton = rawSingleton as Singleton;
const convertedSingleton = rawSingleton as unknown as Singleton;
lazy(convertedSingleton, 'entityType', resolveEntityType(converter, rawSingleton.entityTypeName));
lazy(convertedSingleton, 'annotations', resolveAnnotations(converter, rawSingleton as Singleton));
lazy(convertedSingleton, 'annotations', resolveAnnotations(converter, convertedSingleton));

@@ -1239,7 +1232,3 @@ const _rawNavigationPropertyBindings = rawSingleton.navigationPropertyBinding;

'navigationPropertyBinding',
resolveNavigationPropertyBindings(
converter,
_rawNavigationPropertyBindings as Singleton['navigationPropertyBinding'],
rawSingleton
)
resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings)
);

@@ -1258,6 +1247,6 @@

function convertEntitySet(converter: Converter, rawEntitySet: RawEntitySet): EntitySet {
const convertedEntitySet = rawEntitySet as EntitySet;
const convertedEntitySet = rawEntitySet as unknown as EntitySet;
lazy(convertedEntitySet, 'entityType', resolveEntityType(converter, rawEntitySet.entityTypeName));
lazy(convertedEntitySet, 'annotations', resolveAnnotations(converter, rawEntitySet as EntitySet));
lazy(convertedEntitySet, 'annotations', resolveAnnotations(converter, convertedEntitySet));

@@ -1268,7 +1257,3 @@ const _rawNavigationPropertyBindings = rawEntitySet.navigationPropertyBinding;

'navigationPropertyBinding',
resolveNavigationPropertyBindings(
converter,
_rawNavigationPropertyBindings as EntitySet['navigationPropertyBinding'],
rawEntitySet
)
resolveNavigationPropertyBindings(converter, _rawNavigationPropertyBindings)
);

@@ -1399,4 +1384,17 @@

lazy(convertedActionImport, 'action', () => converter.getConvertedAction(rawActionImport.actionName));
lazy(convertedActionImport, 'action', () => {
const rawActions = converter.rawSchema.actions.filter(
(rawAction) => !rawAction.isBound && rawAction.fullyQualifiedName.startsWith(rawActionImport.actionName)
);
// this always resolves to a unique unbound action, but resolution of unbound functions can be ambiguous:
// unbound function FQNs have overloads depending on all of their parameters
if (rawActions.length > 1) {
converter.logError(`Ambiguous reference in action import: ${rawActionImport.fullyQualifiedName}`);
}
// return the first matching action or function
return converter.getConvertedAction(rawActions[0].fullyQualifiedName)!;
});
return convertedActionImport;

@@ -1426,24 +1424,35 @@ }

lazy(convertedAction, 'annotations', () => {
const action = substringBeforeFirst(rawAction.fullyQualifiedName, '(');
/*
Annotation resolution rule for actions:
// if the action is unbound (e.g. "myAction"), the annotation target is "myAction()"
const annotationTargetFQN = rawAction.isBound
? rawAction.fullyQualifiedName
: `${rawAction.fullyQualifiedName}()`;
(1) annotation target: the specific unbound or bound overload, e.g.
- for actions: "x.y.z.unboundAction()" / "x.y.z.boundAction(x.y.z.Entity)"
- for functions: "x.y.z.unboundFunction(Edm.String)" / "x.y.z.unboundFunction(x.y.z.Entity,Edm.String)"
(2) annotation target: unspecified overload, e.g.
- for actions: "x.y.z.unboundAction" / "x.y.z.boundAction"
- for functions: "x.y.z.unboundFunction" / "x.y.z.unboundFunction"
const rawAnnotations = converter.getAnnotations(annotationTargetFQN);
const baseAnnotations = converter.getAnnotations(action);
When resolving (1) takes precedence over (2). That is, annotations on the specific overload overwrite
annotations on the unspecific overload, on term/qualifier level.
*/
for (const baseAnnotation of baseAnnotations) {
const unspecificOverloadTarget = substringBeforeFirst(rawAction.fullyQualifiedName, '(');
const specificOverloadTarget = rawAction.fullyQualifiedName;
const effectiveAnnotations = converter.getAnnotations(specificOverloadTarget);
const unspecificAnnotations = converter.getAnnotations(unspecificOverloadTarget);
for (const unspecificAnnotation of unspecificAnnotations) {
if (
!rawAnnotations.some(
!effectiveAnnotations.some(
(annotation) =>
annotation.term === baseAnnotation.term && annotation.qualifier === baseAnnotation.qualifier
annotation.term === unspecificAnnotation.term &&
annotation.qualifier === unspecificAnnotation.qualifier
)
) {
rawAnnotations.push(baseAnnotation);
effectiveAnnotations.push(unspecificAnnotation);
}
}
return createAnnotationsObject(converter, rawAction, rawAnnotations);
return createAnnotationsObject(converter, rawAction, effectiveAnnotations);
});

@@ -1476,4 +1485,27 @@

lazy(convertedActionParameter, 'annotations', resolveAnnotations(converter, rawActionParameter));
lazy(convertedActionParameter, 'annotations', () => {
// annotations on action parameters are resolved following the rules for actions
const unspecificOverloadTarget =
rawActionParameter.fullyQualifiedName.substring(0, rawActionParameter.fullyQualifiedName.indexOf('(')) +
rawActionParameter.fullyQualifiedName.substring(rawActionParameter.fullyQualifiedName.indexOf(')') + 1);
const specificOverloadTarget = rawActionParameter.fullyQualifiedName;
const effectiveAnnotations = converter.getAnnotations(specificOverloadTarget);
const unspecificAnnotations = converter.getAnnotations(unspecificOverloadTarget);
for (const unspecificAnnotation of unspecificAnnotations) {
if (
!effectiveAnnotations.some(
(annotation) =>
annotation.term === unspecificAnnotation.term &&
annotation.qualifier === unspecificAnnotation.qualifier
)
) {
effectiveAnnotations.push(unspecificAnnotation);
}
}
return createAnnotationsObject(converter, rawActionParameter, effectiveAnnotations);
});
return convertedActionParameter;

@@ -1480,0 +1512,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc