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

@cap-js/graphql

Package Overview
Dependencies
Maintainers
2
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cap-js/graphql - npm Package Compare versions

Comparing version 0.9.0 to 0.10.0

lib/resolvers/parse/ast/literal.js

18

CHANGELOG.md

@@ -8,2 +8,20 @@ # Changelog

## Version 0.10.0 - 2023-01-30
### Added
- Support for generating GraphQL descriptions from CDS doc comments of services, entities, and elements
- Support for operator `in` for filtering on lists of values
### Changed
- Bump `@graphiql/plugin-explorer` version to `^1`
- Ignore fields that represent foreign keys in GraphQL schema generation
- When compiling to GraphQL using the CDS API or CLI, only generate GraphQL schemas for services that are annotated with GraphQL protocol annotations
### Fixed
- Name clashes when CDS elements are named `nodes` or `totalCount`
- Parsing of `null` values in lists
## Version 0.9.0 - 2023-11-16

@@ -10,0 +28,0 @@

23

lib/compile.js

@@ -5,5 +5,26 @@ const cds = require('@sap/cds')

const _isServiceAnnotatedWithGraphQL = service => {
const { definition } = service
if (definition['@graphql']) return true
const protocol = definition['@protocol']
if (protocol) {
// @protocol: 'graphql' or @protocol: ['graphql', 'odata']
const protocols = Array.isArray(protocol) ? protocol : [protocol]
// Normalize objects such as { kind: 'graphql' } to strings
return protocols.map(p => (typeof p === 'object' ? p.kind : p)).some(p => p.match(/graphql/i))
}
return false
}
function cds_compile_to_gql(csn, options = {}) {
const m = cds.linked(csn)
const services = Object.fromEntries(m.services.map(s => [s.name, new cds.ApplicationService(s.name, m)]))
const services = Object.fromEntries(
m.services
.map(s => [s.name, new cds.ApplicationService(s.name, m)])
// Only compile services with GraphQL endpoints
.filter(([_, service]) => _isServiceAnnotatedWithGraphQL(service))
)

@@ -10,0 +31,0 @@ let schema = generateSchema4(services)

10

lib/constants.js

@@ -23,2 +23,6 @@ const CONNECTION_FIELDS = {

const LOGICAL_OPERATORS = {
in: 'in'
}
const STRING_OPERATIONS = {

@@ -30,3 +34,3 @@ startswith: 'startswith',

const OPERATOR_CONJUNCTION_SUPPORT = {
const OPERATOR_LIST_SUPPORT = {
[RELATIONAL_OPERATORS.eq]: false,

@@ -38,2 +42,3 @@ [RELATIONAL_OPERATORS.ne]: true,

[RELATIONAL_OPERATORS.lt]: false,
[LOGICAL_OPERATORS.in]: true,
[STRING_OPERATIONS.startswith]: false,

@@ -48,4 +53,5 @@ [STRING_OPERATIONS.endswith]: false,

RELATIONAL_OPERATORS,
LOGICAL_OPERATORS,
STRING_OPERATIONS,
OPERATOR_CONJUNCTION_SUPPORT
OPERATOR_LIST_SUPPORT
}

@@ -7,3 +7,2 @@ const cds = require('@sap/cds/lib')

const GraphQLRequest = require('../GraphQLRequest')
const { isPlainObject } = require('../utils')
const formatResult = require('../parse/ast/result')

@@ -19,5 +18,4 @@

const result = await service.dispatch(new GraphQLRequest({ req, res, query }))
const resultInArray = isPlainObject(result) ? [result] : result
return formatResult(selection, resultInArray, true)
return formatResult(entity, selection, result, false)
}

@@ -6,3 +6,2 @@ const cds = require('@sap/cds/lib')

const GraphQLRequest = require('../GraphQLRequest')
const { isPlainObject } = require('../utils')
const formatResult = require('../parse/ast/result')

@@ -15,3 +14,3 @@

let query = SELECT.from(entity)
query.columns(astToColumns(selection.selectionSet.selections))
query.columns(astToColumns(entity, selection.selectionSet.selections, true))

@@ -35,5 +34,3 @@ const filter = getArgumentByName(args, ARGS.filter)

const resultInArray = isPlainObject(result) ? [result] : result
return formatResult(selection, resultInArray)
return formatResult(entity, selection, result, true)
}

@@ -7,3 +7,2 @@ const cds = require('@sap/cds/lib')

const GraphQLRequest = require('../GraphQLRequest')
const { isPlainObject } = require('../utils')
const formatResult = require('../parse/ast/result')

@@ -17,3 +16,3 @@

const queryBeforeUpdate = SELECT.from(entity)
queryBeforeUpdate.columns(astToColumns(selection.selectionSet.selections))
queryBeforeUpdate.columns(astToColumns(entity, selection.selectionSet.selections, false))

@@ -45,5 +44,3 @@ if (filter) queryBeforeUpdate.where(astToWhere(filter))

const resultInArray = isPlainObject(mergedResults) ? [mergedResults] : mergedResults
return formatResult(selection, resultInArray, true)
return formatResult(entity, selection, mergedResults, false)
}

@@ -1,91 +0,41 @@

const { Kind } = require('graphql')
const { visit, Kind } = require('graphql')
const fragmentSpreadSelections = require('./fragment')
const substituteVariable = require('./variable')
const removeMetaFieldsFromSelections = require('./meta')
const parseLiteral = require('./literal')
const _traverseObjectValue = (info, objectValue, _fields) =>
objectValue.fields.forEach(field => {
const _field = _fields[field.name.value]
_traverseArgumentOrObjectField(info, field, _field)
})
module.exports = info => {
const rootTypeName = info.parentType.name
const rootType = info.schema.getType(rootTypeName)
const rootFields = rootType.getFields()
const _traverseListValue = (info, listValue, _fields) => {
for (let i = 0; i < listValue.values.length; i++) {
const value = listValue.values[i]
switch (value.kind) {
case Kind.VARIABLE:
listValue.values[i] = substituteVariable(info, value)
break
case Kind.OBJECT:
_traverseObjectValue(info, value, _fields)
break
const enrichedAST = visit(info.fieldNodes, {
[Kind.SELECTION_SET](node) {
// Substitute fragment spreads with fragment definitions into the AST as if they were inline fields
// Prevents the necessity for special handling of fragments in AST to CQN
// Note: FragmentSpread visitor function cannot be used to replace fragment spreads with fragment definitions
// that contain multiple top level selections, since those must be placed directly into the selection set
node.selections = fragmentSpreadSelections(info, node.selections)
},
[Kind.FIELD](node) {
// Remove __typename from selections to prevent field from being interpreted as DB column
// Instead let graphql framework determine the type
if (node.name?.value === '__typename') return null
},
// Literals within the AST have not yet been parsed
[Kind.ARGUMENT]: parseLiteral(rootFields),
// Literals within the AST have not yet been parsed
[Kind.OBJECT_FIELD]: parseLiteral(rootFields),
[Kind.VARIABLE](node) {
// Substitute variable values into the AST as if they were literal values
// Prevents the necessity for special handling of variables in AST to CQN
return substituteVariable(info, node)
},
[Kind.NULL](node) {
// Convenience value for handling of null values in AST to CQN
node.value = null
}
}
}
const _isScalarKind = kind => kind === Kind.INT || kind === Kind.FLOAT || kind === Kind.STRING || kind === Kind.BOOLEAN
const _traverseArgumentOrObjectField = (info, argumentOrObjectField, _fieldOr_arg) => {
const value = argumentOrObjectField.value
const type = _getTypeFrom_fieldOr_arg(_fieldOr_arg)
if (_isScalarKind(value.kind)) value.value = type.parseLiteral(value)
switch (value.kind) {
case Kind.VARIABLE:
argumentOrObjectField.value = substituteVariable(info, value)
break
case Kind.LIST:
_traverseListValue(info, value, type.getFields?.())
break
case Kind.OBJECT:
_traverseObjectValue(info, value, type.getFields())
break
}
// Convenience value for both literal and variable values
if (argumentOrObjectField.value?.kind === Kind.NULL) argumentOrObjectField.value.value = null
}
const _traverseSelectionSet = (info, selectionSet, _fields) => {
selectionSet.selections = fragmentSpreadSelections(info, selectionSet.selections)
selectionSet.selections = removeMetaFieldsFromSelections(selectionSet.selections)
selectionSet.selections.forEach(field => {
const _field = _fields[field.name.value]
_traverseField(info, field, _field)
})
}
const _getTypeFrom_fieldOr_arg = _field => {
let type = _field.type
while (type.ofType) type = type.ofType
return type
return enrichedAST
}
const _traverseField = (info, field, _field) => {
if (field.selectionSet) {
const type = _getTypeFrom_fieldOr_arg(_field)
_traverseSelectionSet(info, field.selectionSet, type.getFields())
}
field.arguments.forEach(arg => {
const _arg = _field.args.find(a => a.name === arg.name.value)
_traverseArgumentOrObjectField(info, arg, _arg)
})
}
const _traverseFieldNodes = (info, fieldNodes, _fields) =>
fieldNodes.forEach(fieldNode => {
const _field = _fields[fieldNode.name.value]
_traverseField(info, fieldNode, _field)
})
module.exports = info => {
const deepClonedFieldNodes = JSON.parse(JSON.stringify(info.fieldNodes))
const rootTypeName = info.parentType.name
const rootType = info.schema.getType(rootTypeName)
_traverseFieldNodes(info, deepClonedFieldNodes, rootType.getFields())
return deepClonedFieldNodes
}

@@ -10,5 +10,5 @@ const { Kind } = require('graphql')

selections.flatMap(selection =>
selection.kind === Kind.FRAGMENT_SPREAD ? _substituteFragment(info, selection) : [selection]
selection.kind === Kind.FRAGMENT_SPREAD ? _substituteFragment(info, selection) : selection
)
module.exports = fragmentSpreadSelections

@@ -6,5 +6,21 @@ const { Kind } = require('graphql')

const _valueToGenericScalarValue = value => ({
kind: 'GenericScalarValue',
value
const _valueToGraphQLType = value => {
if (typeof value === 'boolean') return Kind.BOOLEAN
if (typeof value === 'number') {
if (Number.isInteger(value)) return Kind.INT
return Kind.FLOAT
}
// Return below means: (typeof value === 'string' || Buffer.isBuffer(value))
return Kind.STRING
}
const _valueToScalarValue = value => ({
kind: _valueToGraphQLType(value),
value,
// Variable values have already been parsed
// -> skip parsing in Argument and ObjectField visitor functions
skipParsing: true
})

@@ -34,21 +50,13 @@

const _variableToValue = variable => {
if (Array.isArray(variable)) {
return _arrayToListValue(variable)
}
if (Array.isArray(variable)) return _arrayToListValue(variable)
if (isPlainObject(variable)) {
return _objectToObjectValue(variable)
}
if (isPlainObject(variable)) return _objectToObjectValue(variable)
if (variable === null) {
return _nullValue
}
if (variable === null) return _nullValue
if (variable === undefined) {
return undefined
}
if (variable === undefined) return undefined
return _valueToGenericScalarValue(variable)
return _valueToScalarValue(variable)
}
module.exports = variableValue => _variableToValue(variableValue)

@@ -5,4 +5,4 @@ const { CONNECTION_FIELDS } = require('../../../constants')

const formatResult = (field, result, skipTopLevelConnection) => {
const _formatObject = (selections, object) => {
const formatResult = (entity, field, result, isConnection) => {
const _formatObject = (type, selections, object) => {
const result = {}

@@ -16,4 +16,6 @@

for (const field of fields) {
const element = type.elements[field.name.value]
const elementType = element._target || element
const responseKey = field.alias?.value || field.name.value
result[responseKey] = _formatByType(field, value)
result[responseKey] = _formatByType(elementType, field, value, element.is2many)
}

@@ -34,9 +36,9 @@ }

const _formatArray = (field, array, skipTopLevelConnection) => {
const _formatArray = (type, field, array, isConnection) => {
const selections = field.selectionSet.selections
const potentiallyNestedSelections = getPotentiallyNestedNodesSelections(selections)
const result = array.map(e => _formatObject(potentiallyNestedSelections, e))
const potentiallyNestedSelections = getPotentiallyNestedNodesSelections(selections, isConnection)
const result = array.map(e => _formatObject(type, potentiallyNestedSelections, e))
// REVISIT: requires differentiation for support of configurable schema flavors
if (skipTopLevelConnection) return result
if (!isConnection) return result

@@ -49,6 +51,6 @@ return {

const _formatByType = (field, value, skipTopLevelConnection) => {
if (Array.isArray(value)) return _formatArray(field, value, skipTopLevelConnection)
const _formatByType = (type, field, value, isConnection) => {
if (Array.isArray(value)) return _formatArray(type, field, value, isConnection)
if (isPlainObject(value)) return _formatObject(field.selectionSet.selections, value)
if (isPlainObject(value)) return _formatObject(type, field.selectionSet.selections, value)

@@ -58,5 +60,7 @@ return value

return _formatByType(field, result, skipTopLevelConnection)
// TODO: if singleton, don't wrap in array
const resultInArray = isPlainObject(result) ? [result] : result
return _formatByType(entity, field, resultInArray, isConnection)
}
module.exports = formatResult

@@ -8,9 +8,10 @@ const { getPotentiallyNestedNodesSelections } = require('../util')

const astToColumns = selections => {
const astToColumns = (entity, selections, isConnection) => {
let columns = []
for (const selection of getPotentiallyNestedNodesSelections(selections)) {
for (const selection of getPotentiallyNestedNodesSelections(selections, isConnection)) {
const args = selection.arguments
const fieldName = selection.name.value
const element = entity.elements[fieldName]
const column = { ref: [fieldName] }

@@ -20,3 +21,3 @@ if (selection.alias) column.as = selection.alias.value

if (selection.selectionSet?.selections) {
const columns = astToColumns(selection.selectionSet.selections)
const columns = astToColumns(element._target, selection.selectionSet.selections, element.is2many)
// columns is empty if only __typename was selected (which was filtered out in the enriched AST)

@@ -23,0 +24,0 @@ column.expand = columns.length > 0 ? columns : ['*']

@@ -1,2 +0,2 @@

const { RELATIONAL_OPERATORS, STRING_OPERATIONS } = require('../../../constants')
const { RELATIONAL_OPERATORS, LOGICAL_OPERATORS, STRING_OPERATIONS } = require('../../../constants')
const { Kind } = require('graphql')

@@ -16,3 +16,4 @@

[RELATIONAL_OPERATORS.le]: '<=',
[RELATIONAL_OPERATORS.lt]: '<'
[RELATIONAL_OPERATORS.lt]: '<',
[LOGICAL_OPERATORS.in]: 'in'
}

@@ -34,9 +35,15 @@

const gqlOperator = objectField.name.value
const operand = objectField.value
if (objectField.value.kind === Kind.LIST) {
const _xprs = objectField.value.values.map(value => _to_xpr(ref, gqlOperator, value.value))
if (gqlOperator === LOGICAL_OPERATORS.in) {
const list = operand.kind === Kind.LIST ? operand.values.map(value => ({ val: value.value })) : [{ val: operand.value }]
return [ref, _gqlOperatorToCdsOperator(gqlOperator), { list }]
}
if (operand.kind === Kind.LIST) {
const _xprs = operand.values.map(value => _to_xpr(ref, gqlOperator, value.value))
return _joinedXprFrom_xprs(_xprs, 'and')
}
return _to_xpr(ref, gqlOperator, objectField.value.value)
return _to_xpr(ref, gqlOperator, operand.value)
}

@@ -43,0 +50,0 @@

@@ -1,3 +0,1 @@

const { CONNECTION_FIELDS } = require('../../../constants')
const _filterOutDuplicateColumnsSelections = selections => {

@@ -18,7 +16,5 @@ const mergedSelectionsMap = new Map()

const getPotentiallyNestedNodesSelections = selections => {
const isConnection = selections.some(selection => Object.values(CONNECTION_FIELDS).includes(selection.name.value))
return isConnection ? _filterOutDuplicateColumnsSelections(selections) : selections
}
const getPotentiallyNestedNodesSelections = (selections, isConnection) =>
isConnection ? _filterOutDuplicateColumnsSelections(selections) : selections
module.exports = { getPotentiallyNestedNodesSelections }

@@ -13,3 +13,3 @@ const {

const { cdsToGraphQLScalarType } = require('../types/scalar')
const { RELATIONAL_OPERATORS, STRING_OPERATIONS, OPERATOR_CONJUNCTION_SUPPORT } = require('../../constants')
const { RELATIONAL_OPERATORS, LOGICAL_OPERATORS, STRING_OPERATIONS, OPERATOR_LIST_SUPPORT } = require('../../constants')
const {

@@ -60,2 +60,3 @@ GraphQLBinary,

const _generateScalarFilter = gqlType => {
const numericOperators = Object.values({ ...RELATIONAL_OPERATORS, ...LOGICAL_OPERATORS })
const filterType = {

@@ -65,18 +66,18 @@ // REVISIT: which filters for binary

[GraphQLBoolean.name]: _generateFilterType(GraphQLBoolean, [RELATIONAL_OPERATORS.eq, RELATIONAL_OPERATORS.ne]),
[GraphQLDate.name]: _generateFilterType(GraphQLDate, Object.values(RELATIONAL_OPERATORS)),
[GraphQLDateTime.name]: _generateFilterType(GraphQLDateTime, Object.values(RELATIONAL_OPERATORS)),
[GraphQLDecimal.name]: _generateFilterType(GraphQLDecimal, Object.values(RELATIONAL_OPERATORS)),
// REVISIT: should 'eq'/'ne' be generated since exact comparisons could be difficult due to floating point errors?
[GraphQLFloat.name]: _generateFilterType(GraphQLFloat, Object.values(RELATIONAL_OPERATORS)),
[GraphQLID.name]: _generateFilterType(GraphQLID, Object.values(RELATIONAL_OPERATORS)),
[GraphQLInt.name]: _generateFilterType(GraphQLInt, Object.values(RELATIONAL_OPERATORS)),
[GraphQLInt16.name]: _generateFilterType(GraphQLInt16, Object.values(RELATIONAL_OPERATORS)),
[GraphQLInt64.name]: _generateFilterType(GraphQLInt64, Object.values(RELATIONAL_OPERATORS)),
[GraphQLDate.name]: _generateFilterType(GraphQLDate, numericOperators),
[GraphQLDateTime.name]: _generateFilterType(GraphQLDateTime, numericOperators),
[GraphQLDecimal.name]: _generateFilterType(GraphQLDecimal, numericOperators),
// REVISIT: should 'eq'/'ne'/'in' be generated since exact comparisons could be difficult due to floating point errors?
[GraphQLFloat.name]: _generateFilterType(GraphQLFloat, numericOperators),
[GraphQLID.name]: _generateFilterType(GraphQLID, numericOperators),
[GraphQLInt.name]: _generateFilterType(GraphQLInt, numericOperators),
[GraphQLInt16.name]: _generateFilterType(GraphQLInt16, numericOperators),
[GraphQLInt64.name]: _generateFilterType(GraphQLInt64, numericOperators),
[GraphQLString.name]: _generateFilterType(
GraphQLString,
Object.values({ ...RELATIONAL_OPERATORS, ...STRING_OPERATIONS })
Object.values({ ...RELATIONAL_OPERATORS, ...LOGICAL_OPERATORS, ...STRING_OPERATIONS })
),
[GraphQLTime.name]: _generateFilterType(GraphQLTime, Object.values(RELATIONAL_OPERATORS)),
[GraphQLTimestamp.name]: _generateFilterType(GraphQLTimestamp, Object.values(RELATIONAL_OPERATORS)),
[GraphQLUInt8.name]: _generateFilterType(GraphQLUInt8, Object.values(RELATIONAL_OPERATORS))
[GraphQLTime.name]: _generateFilterType(GraphQLTime, numericOperators),
[GraphQLTimestamp.name]: _generateFilterType(GraphQLTimestamp, numericOperators),
[GraphQLUInt8.name]: _generateFilterType(GraphQLUInt8, numericOperators)
}[gqlType.name]

@@ -92,6 +93,3 @@ return new GraphQLList(filterType)

const ops = operations.map(op => [
[op],
{ type: OPERATOR_CONJUNCTION_SUPPORT[op] ? new GraphQLList(gqlType) : gqlType }
])
const ops = operations.map(op => [[op], { type: OPERATOR_LIST_SUPPORT[op] ? new GraphQLList(gqlType) : gqlType }])
const fields = Object.fromEntries(ops)

@@ -98,0 +96,0 @@ const newFilterType = new GraphQLInputObjectType({ name: filterName, fields })

@@ -14,4 +14,6 @@ const { GraphQLObjectType } = require('graphql')

const serviceName = gqlName(service.name)
const resolve = resolvers[serviceName]
fields[serviceName] = { type: _serviceToObjectType(service), resolve }
fields[serviceName] = {
type: _serviceToObjectType(service),
resolve: resolvers[serviceName]
}
}

@@ -37,3 +39,8 @@

return new GraphQLObjectType({ name: gqlName(service.name), fields })
return new GraphQLObjectType({
name: gqlName(service.name),
// REVISIT: Passed services currently don't directly contain doc property
description: service.model.definitions[service.name].doc,
fields
})
}

@@ -40,0 +47,0 @@

@@ -32,7 +32,12 @@ const { GraphQLScalarType, Kind, GraphQLError } = require('graphql')

const parseLiteral = valueNode => {
if (valueNode.kind !== Kind.STRING) throw getGraphQLValueError(ERROR_NON_STRING_VALUE, valueNode)
const { kind, value } = valueNode
const buffer = Buffer.from(valueNode.value, 'base64')
_validateBase64String(valueNode.value, buffer, valueNode)
if (kind !== Kind.STRING) throw getGraphQLValueError(ERROR_NON_STRING_VALUE, valueNode)
// WORKAROUND: value could have already been parsed to a Buffer, necessary because of manual parsing in enrich AST
if (Buffer.isBuffer(value)) return value
const buffer = Buffer.from(value, 'base64')
_validateBase64String(value, buffer, valueNode)
return buffer

@@ -39,0 +44,0 @@ }

@@ -10,3 +10,3 @@ const { GraphQLScalarType, Kind } = require('graphql')

// Cut off milliseconds
return date.replace(/\.\d\d\dZ$/, 'Z')
return date.slice(0, 19) + 'Z'
}

@@ -13,0 +13,0 @@

@@ -26,3 +26,5 @@ const { GraphQLScalarType, Kind } = require('graphql')

const parseLiteral = valueNode => {
if (valueNode.kind !== Kind.FLOAT && valueNode.kind !== Kind.INT && valueNode.kind !== Kind.STRING)
const { kind, value } = valueNode
if (kind !== Kind.FLOAT && kind !== Kind.INT && kind !== Kind.STRING)
throw getGraphQLValueError(ERROR_NON_NUMERIC_VALUE, valueNode)

@@ -32,3 +34,3 @@

return valueNode.value
return value
}

@@ -35,0 +37,0 @@

@@ -31,5 +31,6 @@ const { GraphQLScalarType, Kind } = require('graphql')

const parseLiteral = valueNode => {
if (valueNode.kind !== Kind.INT && valueNode.kind !== Kind.STRING)
throw getGraphQLValueError(ERROR_NON_INTEGER_VALUE, valueNode)
const { kind } = valueNode
if (kind !== Kind.INT && kind !== Kind.STRING) throw getGraphQLValueError(ERROR_NON_INTEGER_VALUE, valueNode)
const num = _toBigInt(valueNode)

@@ -36,0 +37,0 @@ validateRange(num, MIN_INT64, MAX_INT64, ERROR_NON_64_BIT_INTEGER_VALUE, valueNode)

@@ -32,3 +32,7 @@ const { GraphQLObjectType, GraphQLList, GraphQLInt } = require('graphql')

const fields = {}
const newEntityObjectType = new GraphQLObjectType({ name: entityName, fields: () => fields })
const newEntityObjectType = new GraphQLObjectType({
name: entityName,
description: entity.doc,
fields: () => fields
})
cache.set(entityName, newEntityObjectType)

@@ -42,3 +46,3 @@

if (type) {
const field = { type }
const field = { type, description: element.doc }
if (element.is2many) field.args = argsGenerator(cache).generateArgumentsForType(element)

@@ -45,0 +49,0 @@ fields[gqlName(name)] = field

@@ -6,5 +6,9 @@ const hasScalarFields = entity =>

const _isFlatForeignKey = element => Boolean(element['@odata.foreignKey4'] || element._foreignKey4)
const _isLocalized = element => element.name === 'localized' && element.target?.endsWith('.texts')
const shouldElementBeIgnored = element => element.name.startsWith('up_') || _isLocalized(element)
// TODO: add check for @cds.api.ignore
const shouldElementBeIgnored = element =>
element.name.startsWith('up_') || _isLocalized(element) || _isFlatForeignKey(element)

@@ -11,0 +15,0 @@ const isCompositionOfAspect = entity =>

{
"name": "@cap-js/graphql",
"version": "0.9.0",
"version": "0.10.0",
"description": "CDS protocol adapter for GraphQL",

@@ -47,3 +47,3 @@ "keywords": [

"jest": "^29.3.1",
"prettier": "^3",
"prettier": "3.2.4",
"semver": "^7.4.0",

@@ -50,0 +50,0 @@ "sqlite3": "^5.0.2"

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