Skip to content

Commit 0ada369

Browse files
schwmahm23johannes-vogel
authored
feat: support for @sap/cds^7 middlewares/protocols (#86)
* Rename protocols `path` config to `endpoint` * Collect services and init adapter on served * Extract service collection from `CDSGraphQLAdapter` * Undo indentation * Mount adapter at configured `endpoint` * Remove newline * Move services into options argument * Bump required `@sap/cds` version to 7 * Allow newer major versions for `@sap/cds` devDependency * Add changelog entries * Add step to README about annotating services * Add `@graphql` annotation to services used by `cds.test` * Add tests for prorocol annotations and endpoint config * Fix typos * Add note about required protocol annotations to changelog entry * Fix function name * Fix path to `gql` tag util * Fix path to annotations `cds.test` project * Add missing `@graphql` annotation to test service * Revert "Rename protocols `path` config to `endpoint`" This reverts commit eca7148. * Use `path` instead of `endpoint` as router path * Extract `GraphQLAdapter` function as module * Log serving protocol and path equivalent to cds 6 * Bump `cds` version in `devDependencies` to `>=7` * Make `GraphQLAdapter` accessible via root `index.js` * Import cds in CRUD resolvers * Don't overwrite other configured protocols in annotations test project * Adjust test project `server.js` files to not overwrite configured protocols * Fix configured graphql path in tests * Remove `GraphQLAdapter` exposed at root * Adjust logging of mount path to match other protocols * Improve function name * Fix and improve changelog entries * Improve function name --------- Co-authored-by: Heiko Witteborg <[email protected]> Co-authored-by: Johannes Vogel <[email protected]>
1 parent da008d5 commit 0ada369

File tree

25 files changed

+214
-45
lines changed

25 files changed

+214
-45
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## Version 0.6.0 - tbd
8+
## Version 0.6.0 - 2023-06-23
99

1010
### Added
1111

12+
- Support for `@sap/cds^7` middlewares and protocols. Note: services now need to be annotated with protocol annotations such as `@graphql` or `@protocol: 'graphql'`.
13+
1214
### Changed
1315

16+
- Bump required `@sap/cds` version to `>=7`
17+
- `@cap-js/graphql/index.js` now collects individual services and mounts the adapter as a protocol middleware on the `cds.on('served', ...)` event
18+
- Moved the `GraphQLAdapter` module to `lib/GraphQLAdapter.js` and merged it with `CDSGraphQLAdapter` previously found in `index.js` in the root directory
1419
- Don't generate fields that represent compositions of aspects within mutation types that represent services
15-
- Moved the `GraphQLAdapter` module to the root directory (`index.js`), simplifying the import process and reducing the required typing.
1620
- Disabled conjunction on the same field for the following operators:
1721
+ `eq` (Equal)
1822
+ `gt` (Greater Than)

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ _**WARNING:** This package is in an early general availability state. This means
1919
> This will automatically plugin to `@sap/cds` runtime, enabling the new [middlewares architecture](https://cap.cloud.sap/docs/node.js/middlewares) in Node.js, and register a GraphQL endpoint at `/graphql` serving all CRUD requests for the application services found in your model.
2020
2121
2. Run your server as usual, e.g. using `cds watch`.
22-
> The runtime will automatically serve all services via GraphQL at the default configured endpoint.
22+
23+
3. Annotate the services you want to serve, e.g. using `@graphql` or `@protocol: 'graphql'`.
24+
> The runtime will serve all annotated services via GraphQL at the default configured endpoint.
2325
2426
## Limitations
2527

index.js

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
const cds = require('@sap/cds')
2-
const LOG = cds.log('graphql')
3-
const express = require('express')
4-
const { createHandler } = require('graphql-http/lib/use/express')
5-
const { generateSchema4 } = require('./lib/schema')
6-
const graphiql = require('./app/graphiql')
7-
const { decodeURIComponent } = cds.utils
2+
const DEBUG = cds.debug('adapters')
3+
const GraphQLAdapter = require('./lib/GraphQLAdapter')
84

9-
function GraphQLAdapter(options) {
10-
const router = express.Router()
11-
const { services } = options
12-
const defaults = { graphiql: true }
13-
const schema = generateSchema4(services)
14-
options = { ...defaults, ...options }
15-
16-
router
17-
.use(express.json()) //> required by logger below
18-
.use((req, _, next) => {
19-
LOG.info(req.method, req.body?.query || decodeURIComponent(req.query.query))
20-
next()
5+
let services
6+
const _collectServicesAndMountAdapter = (srv, options) => {
7+
if (!services) {
8+
services = {}
9+
cds.on('served', () => {
10+
options.services = services
11+
cds.app.use (options.path, cds.middlewares.before, GraphQLAdapter(options), cds.middlewares.after)
12+
DEBUG?.('app.use(', options.path, ', ... )')
2113
})
22-
23-
if (options.graphiql) router.get('/', graphiql)
24-
router.use((req, res) => createHandler({ schema, context: { req, res }, ...options })(req, res))
25-
return router
14+
}
15+
services[srv.name] = srv
2616
}
2717

28-
module.exports = GraphQLAdapter
18+
module.exports = _collectServicesAndMountAdapter

lib/GraphQLAdapter.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const cds = require('@sap/cds')
2+
const LOG = cds.log('graphql')
3+
const express = require('express')
4+
const { createHandler } = require('graphql-http/lib/use/express')
5+
const { generateSchema4 } = require('./schema')
6+
const graphiql = require('../app/graphiql')
7+
const { decodeURIComponent } = cds.utils
8+
9+
function GraphQLAdapter(options) {
10+
const router = express.Router()
11+
const { services } = options
12+
const defaults = { graphiql: true }
13+
const schema = generateSchema4(services)
14+
options = { ...defaults, ...options }
15+
16+
router
17+
.use(express.json()) //> required by logger below
18+
.use((req, _, next) => {
19+
LOG.info(req.method, req.body?.query || decodeURIComponent(req.query.query))
20+
next()
21+
})
22+
23+
if (options.graphiql) router.get('/', graphiql)
24+
router.use((req, res) => createHandler({ schema, context: { req, res }, ...options })(req, res))
25+
return router
26+
}
27+
28+
module.exports = GraphQLAdapter

lib/resolvers/crud/create.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const cds = require('@sap/cds/lib')
12
const { INSERT } = cds.ql
23
const { ARGS } = require('../../constants')
34
const { getArgumentByName, astToEntries } = require('../parse/ast2cqn')

lib/resolvers/crud/delete.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const cds = require('@sap/cds/lib')
12
const { DELETE } = cds.ql
23
const { ARGS } = require('../../constants')
34
const { getArgumentByName, astToWhere } = require('../parse/ast2cqn')

lib/resolvers/crud/read.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const cds = require('@sap/cds/lib')
12
const { SELECT } = cds.ql
23
const { ARGS, CONNECTION_FIELDS } = require('../../constants')
34
const { getArgumentByName, astToColumns, astToWhere, astToOrderBy, astToLimit } = require('../parse/ast2cqn')

lib/resolvers/crud/update.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const cds = require('@sap/cds/lib')
12
const { SELECT, UPDATE } = cds.ql
23
const { ARGS } = require('../../constants')
34
const { getArgumentByName, astToColumns, astToWhere, astToEntries } = require('../parse/ast2cqn')

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"graphql-http": "^1.16.0"
3737
},
3838
"peerDependencies": {
39-
"@sap/cds": ">=6.3"
39+
"@sap/cds": ">=7"
4040
},
4141
"devDependencies": {
4242
"axios": ">=0.24",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const cds = require('@sap/cds')
2+
const path = require('path')
3+
const protocols = cds.env.protocols ??= {}
4+
if (!protocols.graphql) protocols.graphql = {
5+
path: '/custom-graphql-path', impl: path.join(__dirname, '../../../index.js')
6+
}

0 commit comments

Comments
 (0)