Socket
Socket
Sign inDemoInstall

api-elements

Package Overview
Dependencies
Maintainers
3
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

api-elements - npm Package Compare versions

Comparing version 0.3.1 to 0.3.2

lib/utils.js

10

CHANGELOG.md
# API Elements (JavaScript) CHANGELOG
## 0.3.2 (2020-09-23)
### Bug Fixes
- Inherit fixed attribute in `valueOf`
### Enhancements
- Dereference elements in valueOf
## 0.3.1 (2020-09-07)

@@ -4,0 +14,0 @@

289

lib/define-value-of.js

@@ -1,134 +0,47 @@

/* eslint-disable no-bitwise, no-underscore-dangle */
/* eslint-disable no-underscore-dangle */
const R = require('ramda');
const {
Element,
ArrayElement,
ObjectElement,
StringElement,
BooleanElement,
NumberElement,
NullElement,
} = require('minim');
const {
isFixed,
isFixedType,
isRequired,
isNullable,
isOptional,
isPrimitive,
isEnum,
isArray,
isObject,
getDefault,
getFirstSample,
isNonEmptyArray,
isEmptyArray,
isRef,
isObjectWithUndefinedValues,
trivialValue,
getStructureMembers,
} = require('./utils');
const EnumElement = require('./elements/Enum');
const setFlag = (mask, options) => (options | mask);
const clearFlag = (mask, options) => (options & ~mask);
const isFlag = (mask, options) => (options & mask) !== 0;
const FIXED_FLAG = 1 << 0;
const NULLABLE_FLAG = 1 << 1;
const FIXED_TYPE_FLAG = 1 << 2;
function findDefault(e) {
if (undefined !== e._attributes) {
const result = e.attributes.get('default');
if (undefined !== result) {
return result;
}
}
return null;
}
function hasTypeAttribute(e, attribute) {
if (undefined !== e._attributes) {
const typeAttributes = e.attributes.get('typeAttributes');
if (typeAttributes) {
return typeAttributes.includes(attribute);
}
}
return false;
}
const hasFixedTypeAttribute = e => hasTypeAttribute(e, 'fixed');
const hasFixedTypeTypeAttribute = e => hasTypeAttribute(e, 'fixedType');
const hasNullableTypeAttribute = e => hasTypeAttribute(e, 'nullable');
const hasOptionalTypeAttribute = e => hasTypeAttribute(e, 'optional');
function updateTypeAttributes(e, options) {
let result = options;
if (hasFixedTypeAttribute(e)) {
result = setFlag(FIXED_FLAG, result);
}
if (hasFixedTypeTypeAttribute(e)) {
result = setFlag(FIXED_TYPE_FLAG, result);
}
if (hasNullableTypeAttribute(e)) {
result = setFlag(NULLABLE_FLAG, result);
}
return result;
}
function inheritFlags(options) {
return clearFlag(clearFlag(FIXED_TYPE_FLAG | NULLABLE_FLAG, options));
}
function findFirstSample(e) {
if (undefined !== e._attributes) {
const samples = e.attributes.get('samples');
if (samples instanceof ArrayElement) {
if (undefined !== samples.content && samples.content.length > 0) {
return samples.content[0];
}
}
}
return null;
}
const isPrimitive = e => (e instanceof StringElement) || (e instanceof NumberElement) || (e instanceof BooleanElement);
const isEnumElement = e => e instanceof EnumElement;
const isArrayElement = e => e instanceof ArrayElement;
const isObjectElement = e => e instanceof ObjectElement;
const hasSample = e => findFirstSample(e) !== null;
const hasDefault = e => findDefault(e) !== null;
const hasContent = e => e.content !== undefined;
const hasValue = R.anyPass([hasContent, hasSample, hasDefault]);
const hasNoValue = R.complement(hasValue);
const isNoValuePrimitive = R.both(isPrimitive, hasNoValue);
const isNonEmptyArrayElement = e => isArrayElement(e) && e.content && !e.isEmpty;
const isEmptyArray = e => isArrayElement(e) && e.content.every(isNoValuePrimitive);
const isObjectWithUndefinedValues = e => isObjectElement(e)
&& e.content.every(prop => prop.value === undefined || prop.value.content === undefined);
function trivialValue(e) {
if (e instanceof BooleanElement) {
return new BooleanElement(false);
}
if (e instanceof NumberElement) {
return new NumberElement(0);
}
if (e instanceof StringElement) {
return new StringElement('');
}
if (e instanceof NullElement) {
return new NullElement();
}
return undefined;
}
function mapValue(e, options, f, elements) {
/**
* Map the element values
* @param {element} e - element
* @param {boolean} inheritFixed - inherited fixed attribute
* @param {function} f - map function
* @param {object=} elements - object map of elements to look for inherited types
* @return {any}
*/
function mapValue(e, f, inheritFixed, elements) {
if (e === undefined) {
return e;
return undefined;
}
const opts = updateTypeAttributes(e, options);
const isElementFixed = inheritFixed || isFixed(e);
if (e.content && !isEmptyArray(e) && !isObjectWithUndefinedValues(e)) {
const result = f(e, opts, elements, 'content');
if (e.content && !isEmptyArray(e, elements) && !isObjectWithUndefinedValues(e, elements)) {
const result = f(e, isElementFixed, elements, 'content');
if (undefined !== result) {
if (result !== undefined) {
return result;

@@ -138,6 +51,6 @@ }

const sample = findFirstSample(e);
const sample = getFirstSample(e);
if (sample) {
const result = f(sample, opts, elements, 'sample');
if (undefined !== result) {
const result = f(sample, isElementFixed, elements, 'sample');
if (result !== undefined) {
return result;

@@ -147,6 +60,6 @@ }

const dflt = findDefault(e);
const dflt = getDefault(e);
if (dflt) {
const result = f(dflt, opts, elements, 'default');
if (undefined !== result) {
const result = f(dflt, isElementFixed, elements, 'default');
if (result !== undefined) {
return result;

@@ -156,7 +69,7 @@ }

// reconsider content for array element (prefer sample/default first)
if (isNonEmptyArrayElement(e)) {
const result = f(e, opts, elements, 'content');
// reconsider content for array and object element (prefer sample/default first)
if (isNonEmptyArray(e, elements) && isObject(e, elements)) {
const result = f(e, isElementFixed, elements, 'content');
if (undefined !== result) {
if (result !== undefined) {
return result;

@@ -166,5 +79,5 @@ }

if (isFlag(NULLABLE_FLAG, opts)) {
const result = f(new NullElement(), opts, elements, 'nullable');
if (undefined !== result) {
if (isNullable(e)) {
const result = f(new NullElement(), isElementFixed, elements, 'nullable');
if (result !== undefined) {
return result;

@@ -175,3 +88,3 @@ }

if (elements) {
if (e.element === 'ref') {
if (isRef(e)) {
const result = elements[e.content];

@@ -181,20 +94,21 @@ const inheritedElements = R.filter(el => !el.id.equals(e.content), elements);

if (e.path && e.path.toValue() === 'content') {
return mapValue(result.content, opts, f, inheritedElements);
return mapValue(result.content, f, isElementFixed, inheritedElements);
}
return mapValue(result, opts, f, inheritedElements);
return mapValue(result, f, isElementFixed, inheritedElements);
}
const result = elements[e.element];
if (result) {
if (result !== undefined) {
const inheritedElements = R.filter(el => !el.id.equals(e.element), elements);
return mapValue(result, opts, f, inheritedElements);
return mapValue(result, f, isElementFixed, inheritedElements);
}
}
if (isEnumElement(e)) {
const enums = e.enumerations;
if (enums && enums.content && enums.content[0]) {
const result = f(enums.content[0], opts, elements, 'generated');
if (undefined !== result) {
if (isEnum(e, elements)) {
const content = getStructureMembers(e, elements);
if (content && content[0]) {
const result = f(content[0], isElementFixed, elements, 'generated');
if (result !== undefined) {
return result;

@@ -207,4 +121,4 @@ }

if (trivial) {
const result = f(trivial, opts, elements, 'generated');
if (undefined !== result) {
const result = f(trivial, isElementFixed, elements, 'generated');
if (result !== undefined) {
return result;

@@ -214,4 +128,4 @@ }

if (isArrayElement(e) && e.isEmpty) {
return f(e, opts, elements, 'generated');
if ((isArray(e, elements) && e.isEmpty) || isObject(e, elements)) {
return f(e, isElementFixed, elements, 'generated');
}

@@ -222,10 +136,15 @@

function reduceValue(e, options, elements) {
const opts = updateTypeAttributes(e, options);
/**
* Reduce the element value
* @param {element} e - element
* @param {boolean} inheritFixed - inherited fixed attribute
* @param {object=} elements - object map of elements to look for inherited types
* @return {any}
*/
function reduceValue(e, inheritFixed, elements) {
if (e.content === undefined) {
return mapValue(e, opts, e => e.content, elements);
return mapValue(e, e => e.content, inheritFixed, elements);
}
if (isPrimitive(e)) {
if (isPrimitive(e, elements)) {
return e.content;

@@ -238,18 +157,18 @@ }

if (isEnumElement(e)) {
return mapValue(e.content, inheritFlags(opts), reduceValue, elements);
if (isEnum(e, elements)) {
return mapValue(e.content, reduceValue, inheritFixed, elements);
}
if (isObjectElement(e)) {
if (isObject(e, elements)) {
let result = {};
const isFixed = isFlag(FIXED_FLAG, opts);
const isFixedType = isFlag(FIXED_TYPE_FLAG, opts);
const content = getStructureMembers(e, elements);
const isElementFixedType = isFixedType(e);
e.content.some((item) => {
const skippable = hasOptionalTypeAttribute(item) || (!isFixed && !isFixedType && !hasTypeAttribute(item, 'required'));
content.some((item) => {
const isSkippable = isOptional(item) || (!inheritFixed && !isElementFixedType && !isRequired(item));
const key = mapValue(item.key, inheritFlags(opts), reduceValue, elements);
const key = mapValue(item.key, reduceValue, inheritFixed, elements);
if (key === undefined) {
if (skippable) {
if (isSkippable) {
return false;

@@ -262,5 +181,5 @@ }

const value = mapValue(item.value, inheritFlags(opts), reduceValue, elements);
const value = mapValue(item.value, reduceValue, inheritFixed, elements);
if (value === undefined) {
if (skippable) {
if (isSkippable) {
return false;

@@ -280,6 +199,7 @@ }

if (e instanceof ArrayElement) {
const result = e.map(item => mapValue(item, inheritFlags(opts), reduceValue, elements));
if (isArray(e, elements)) {
const content = getStructureMembers(e, elements);
const result = content.map(item => mapValue(item, reduceValue, inheritFixed, elements));
if (!isFlag(FIXED_FLAG, opts) && !isFlag(FIXED_TYPE_FLAG, opts)) {
if (!inheritFixed && !isFixedType(e)) {
return result.filter(item => item !== undefined);

@@ -299,18 +219,23 @@ }

module.exports = () => {
if (!Object.getOwnPropertyNames(Element.prototype).includes('valueOf')) {
Object.defineProperty(Element.prototype, 'valueOf', {
value(flags, elements) {
if (flags !== undefined && flags.source) {
return mapValue(this, 0, (value, opts, elements, source) => {
const result = reduceValue(value, opts, elements);
if (undefined === result) {
return undefined;
}
return [reduceValue(value, opts, elements), source];
}, elements);
}
return mapValue(this, 0, (value, opts) => reduceValue(value, opts, elements), elements);
},
});
if (Object.getOwnPropertyNames(Element.prototype).includes('valueOf')) {
return;
}
Object.defineProperty(Element.prototype, 'valueOf', {
value(flags, elements) {
if (flags && flags.source) {
return mapValue(this, (value, attrs, elements, source) => {
const result = reduceValue(value, attrs, elements);
if (result === undefined) {
return undefined;
}
return [result, source];
}, false, elements);
}
return mapValue(this, reduceValue, false, elements);
},
});
};
{
"name": "api-elements",
"version": "0.3.1",
"version": "0.3.2",
"description": "API Elements JavaScript",

@@ -35,3 +35,3 @@ "author": "Apiary.io <support@apiary.io>",

},
"gitHead": "d226305421ff42dfa30041568eb639a0755aa16b"
"gitHead": "fdb70bfffae4ddfffbc4348f7e22a8de979cadc2"
}
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