Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .reuse/dep5
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: cds-adapter-graphql
Upstream-Name: graphql
Upstream-Contact: The cap team <cap@sap.com>
Source: https://github.com/cap-js/cds-adapter-graphql
Source: https://github.com/cap-js/graphql
Disclaimer: The code in this project may include calls to APIs ("API Calls") of
SAP or third-party products or services developed outside of this project
("External Products").
Expand All @@ -25,6 +25,6 @@ Disclaimer: The code in this project may include calls to APIs ("API Calls") of
parties the right to use of access any SAP External Product, through API Calls.

Files: *
Copyright: 2022 SAP SE or an SAP affiliate company and cds-adapter-graphql contributors
Copyright: 2022 SAP SE or an SAP affiliate company and cap-js/graphql contributors
License: Apache-2.0

14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Version 0.6.1 - 2023-07-05

### Changed

- Improved query logging:
+ Don't log queries that are `undefined`
+ Log `operationName`
+ Log `variables` when not in production
+ Sanitize arguments and their values in queries when in production

### Fixed

- Changed GraphiQL Explorer Plugin CDN URL due to upstream renaming

## Version 0.6.0 - 2023-06-23

### Added
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![REUSE status](https://api.reuse.software/badge/github.com/cap-js/cds-adapter-graphql)](https://api.reuse.software/info/github.com/cap-js/cds-adapter-graphql)
[![REUSE status](https://api.reuse.software/badge/github.com/cap-js/graphql)](https://api.reuse.software/info/github.com/cap-js/graphql)

# CDS protocol adapter for GraphQL

Expand Down Expand Up @@ -32,12 +32,12 @@ _**WARNING:** This package is in an early general availability state. This means

## Support, Feedback, Contributing

This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/cap-js/cds-adapter-graphql/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md).
This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/cap-js/graphql/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md).

## Code of Conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](CODE_OF_CONDUCT.md) at all times.

## Licensing

Copyright 2022 SAP SE or an SAP affiliate company and cds-adapter-graphql contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/cap-js/cds-adapter-graphql).
Copyright 2022 SAP SE or an SAP affiliate company and cap-js/graphql contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/cap-js/graphql).
2 changes: 1 addition & 1 deletion app/graphiql.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<script crossorigin src="https://unpkg.com/graphiql/graphiql.min.js"></script>
<script crossorigin src="https://unpkg.com/@graphiql/plugin-explorer/dist/graphiql-plugin-explorer.umd.js"></script>
<script crossorigin src="https://unpkg.com/@graphiql/plugin-explorer/dist/index.umd.js"></script>

<script>
const fetcher = GraphiQL.createFetcher({ url: '' })
Expand Down
8 changes: 6 additions & 2 deletions app/graphiql.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
const path = require('path')
const express = require('express')
const router = express.Router()

module.exports = (req, res, next) => {
router.get('/', (req, res, next) => {
if (req.query.query) {
// Forward GET requests with query URL parameter to GraphQL server
next()
} else {
res.sendFile(path.join(__dirname, 'graphiql.html'))
}
}
})

module.exports = router
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const DEBUG = cds.debug('adapters')
const GraphQLAdapter = require('./lib/GraphQLAdapter')

let services
const _collectServicesAndMountAdapter = (srv, options) => {
const collectServicesAndMountAdapter = (srv, options) => {
if (!services) {
services = {}
cds.on('served', () => {
Expand All @@ -15,4 +15,4 @@ const _collectServicesAndMountAdapter = (srv, options) => {
services[srv.name] = srv
}

module.exports = _collectServicesAndMountAdapter
module.exports = collectServicesAndMountAdapter
15 changes: 6 additions & 9 deletions lib/GraphQLAdapter.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
const cds = require('@sap/cds')
const LOG = cds.log('graphql')
const express = require('express')
const { createHandler } = require('graphql-http/lib/use/express')
const { generateSchema4 } = require('./schema')
const queryLogger = require('./logger')
const graphiql = require('../app/graphiql')
const { decodeURIComponent } = cds.utils
const { createHandler } = require('graphql-http/lib/use/express')

function GraphQLAdapter(options) {
const router = express.Router()
Expand All @@ -15,13 +13,12 @@ function GraphQLAdapter(options) {

router
.use(express.json()) //> required by logger below
.use((req, _, next) => {
LOG.info(req.method, req.body?.query || decodeURIComponent(req.query.query))
next()
})
.use(queryLogger)

if (options.graphiql) router.use(graphiql)

if (options.graphiql) router.get('/', graphiql)
router.use((req, res) => createHandler({ schema, context: { req, res }, ...options })(req, res))

return router
}

Expand Down
47 changes: 47 additions & 0 deletions lib/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const cds = require('@sap/cds')
const { decodeURIComponent } = cds.utils
const LOG = cds.log('graphql')
const util = require('util')

const IS_PRODUCTION = process.env.NODE_ENV === 'production'

const queryLogger = (req, _, next) => {
let query = req.body?.query || (req.query.query && decodeURIComponent(req.query.query))
// Only log requests that contain a query
if (!query) {
next()
return
}
query = query.trim()

const operationName = req.body?.operationName || req.query?.operationName

let variables = req.body?.variables || req.query?.variables
if (typeof variables === 'string') {
try {
// variables is a JSON string if taken from req.query.variables
variables = JSON.parse(variables)
} catch (e) {
// Ignore parsing errors, handled by GraphQL server
}
}
if (IS_PRODUCTION && variables) variables = '***'

// Only add properties to object that aren't undefined
const queryInfo = Object.fromEntries(Object.entries({ operationName, variables }).filter(([, v]) => v))
// Only format queryInfo if it contains properties
const formattedQueryInfo =
Object.keys(queryInfo).length > 0 ? util.formatWithOptions({ colors: false, depth: null }, queryInfo) : undefined

// If query is multiline string, add newline padding to front
let formattedQuery = query.includes('\n') ? `\n${query}` : query
// Sanitize all values between parentheses
if (IS_PRODUCTION) formattedQuery = formattedQuery.replace(/\([\s\S]*?\)/g, '( *** )')

// Don't log undefined values
LOG.info(...[req.method, formattedQueryInfo, formattedQuery].filter(e => e))

next()
}

module.exports = queryLogger
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cap-js/graphql",
"version": "0.6.0",
"version": "0.6.1",
"description": "CDS protocol adapter for GraphQL",
"keywords": [
"CAP",
Expand Down
15 changes: 15 additions & 0 deletions test/resources/bookshop-graphql/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"cds": {
"requires": {
"db": {
"kind": "sqlite",
"credentials": {
"database": ":memory:"
}
},
"auth": {
"kind": "mocked"
}
}
}
}
Loading