Skip to content

Commit 97c12ae

Browse files
committed
Restructured content in cds.connect docs
1 parent 876a531 commit 97c12ae

1 file changed

Lines changed: 129 additions & 185 deletions

File tree

node.js/cds-connect.md

Lines changed: 129 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,99 @@ The latter include **database** services. In all cases use `cds.connect` to conn
1313
[[toc]]
1414

1515

16+
## Connecting to Required Services { #cds-connect-to }
17+
18+
19+
20+
### cds. connect.to () {.method}
21+
22+
Use `cds.connect.to()` to connect to services configured in a project's `cds.requires` configuration.
23+
24+
```js
25+
const ReviewsService = await cds.connect.to('ReviewsService')
26+
```
27+
28+
The method returns a _Promise_ resolving to a _[Service](../cds/cdl#services)_ instance which acts as a client proxy to the service's API, allowing you to call its methods and access its data using common [`cds.Service`](core-services#consuming-services) methods, e.g.:
29+
30+
```js
31+
let reviews = await ReviewsService.read ('Reviews')
32+
```
33+
34+
35+
**Arguments** are as follows:
36+
37+
```ts:no-line-numbers
38+
async function cds.connect.to (
39+
name? : string, // reference to an entry in `cds.requires` config
40+
options? : {
41+
kind : string // reference to a preset in `cds.requires.kinds` config
42+
impl : string // module name of the implementation
43+
}
44+
) : Promise<Service>
45+
```
46+
47+
Argument `name` is used to look up connect options from [configured services](#cds-env-requires), which are defined in the `cds.requires` section of your _package.json_ or _.cdsrc.json_ or _.yaml_ files.
48+
49+
Argument `options` also allows to pass additional options such as `credentials` programmatically, and thus create services without configurations and [service bindings](#service-bindings), for example, you could connect to a local SQLite database in your tests like this:
50+
51+
```js
52+
const db2 = await cds.connect.to ({
53+
kind: 'sqlite', credentials: { url: 'db2.sqlite' }
54+
})
55+
```
56+
57+
58+
### cds. services {#cds-connect-caching .property}
59+
60+
When connecting to a service using `cds.connect.to()`, the service instance is cached in [`cds.services`](cds-facade#cds-services) under the service name. This means that subsequent calls to `cds.connect.to()` with the same service name will all return the same instance. As services constructed by [`cds.serve`](cds-serve#cds-serve) are registered with [`cds.services`](cds-facade#cds-services) as well, a connect finds and returns them as local service connections.
61+
62+
You can also access cached service instance like this:
63+
64+
```js
65+
const { ReviewsService } = cds.services
66+
```
67+
68+
> Note: If _ad-hoc_ options are provided, the instance is not cached.
69+
1670

1771

1872
## Configuring Required Services {#cds-env-requires }
1973

20-
To configure required remote services in Node.js, simply add respective entries to the `cds.requires` sections in your _package.json_ or in _.cdsrc.json_ (omitting the `cds.` prefix). These configurations are constructed as follows:
74+
To configure required remote services in Node.js, simply add respective entries to the `cds.requires` sections in your _package.json_ or in _.cdsrc.json_ or _.yaml_. These configurations are constructed as follows:
2175

22-
```json
23-
"cds": {
76+
::: code-group
77+
78+
```json [package.json]
79+
{"cds":{
2480
"requires": {
81+
"db": { "kind": "sqlite", "credentials": { "url":"db.sqlite" }},
2582
"ReviewsService": {
2683
"kind": "odata", "model": "@capire/reviews"
2784
},
2885
"OrdersService": {
2986
"kind": "odata", "model": "@capire/orders"
3087
},
3188
}
32-
}
89+
}}
90+
```
91+
92+
```yaml [.cdsrc.yaml]
93+
cds:
94+
requires:
95+
db:
96+
kind: sqlite
97+
credentials:
98+
url: db.sqlite
99+
ReviewsService:
100+
kind: odata,
101+
model: @capire/reviews
102+
OrdersService:
103+
kind: odata,
104+
model: @capire/orders
33105
```
34106
107+
:::
108+
35109
Entries in this section tell the service loader to not serve that service as part of your application, but expects a service binding at runtime in order to connect to the external service provider. The options are as follows:
36110
37111
@@ -104,147 +178,83 @@ If you specify a model, then a service definition for your required service must
104178
The example specifies `service: 'BusinessPartnerService'`, which results in a check for a service called `BusinessPartnerService` instead of `remote-service` in the model loaded from `some/imported/model`.
105179

106180

107-
### cds.requires.<i>\<srv\></i>`.credentials`
108-
109-
Specify the credentials to connect to the service. Credentials need to be kept secure and should not be part of a configuration file.
110-
111-
112-
113-
114-
115-
## Connecting to Required Services { #cds-connect-to }
116181

117182

183+
## Service Bindings {#service-bindings}
118184

119-
### cds. connect.to () {.method}
120-
121-
Declaration:
122-
123-
```ts:no-line-numbers
124-
async function cds.connect.to (
125-
name : string, // reference to an entry in `cds.requires` config
126-
options : {
127-
kind : string // reference to a preset in `cds.requires.kinds` config
128-
impl : string // module name of the implementation
129-
}
130-
)
131-
```
132-
133-
Use `cds.connect.to()` to connect to services configured in a project's `cds.requires` configuration. Usually such services are remote services, which in turn can be mocked locally. Here's an example:
134-
135-
::: code-group
185+
A service binding connects an application with a cloud service. For that, the cloud service's credentials need to be injected in the CDS configuration:
136186

137-
```json [package.json]
138-
{"cds":{
139-
"requires":{
140-
"db": { "kind": "sqlite", "credentials": { "url":"db.sqlite" }},
141-
"ReviewsService": { "kind": "odata-v4" }
187+
```jsonc
188+
{
189+
"requires": {
190+
"db": {
191+
"kind": "hana",
192+
"credentials": { /* from service binding */ }
193+
}
142194
}
143-
}}
144-
```
145-
146-
:::
147-
148-
```js
149-
const ReviewsService = cds.connect.to('ReviewsService')
150-
const db = cds.connect.to('db')
151-
```
152-
153-
Argument `options` allows to pass options programmatically, and thus create services without configurations, for example:
154-
155-
```js
156-
const db2 = cds.connect.to ({
157-
kind: 'sqlite', credentials: { url: 'db2.sqlite' }
158-
})
195+
}
159196
```
160197

161-
In essence, `cds.connect.to()` works like that:
162198

163-
```js
164-
let o = { ...cds.requires[name], ...options }
165-
let csn = o.model ? await cds.load(o.model) : cds.model
166-
let Service = require (o.impl) //> a subclass of cds.Service
167-
let srv = new Service (name, csn, o)
168-
return srv.init() ?? srv
169-
```
199+
### cds.requires.<i>\<srv\></i>.credentials
170200

201+
All service binding information goes into this property. It's filled from the process environment when starting server processes, managed by deployment environments. Service bindings provide the details about how to reach a required service at runtime, that is, providing requisite credentials, most prominently the target service's `url`.
171202

172203

204+
You specify the credentials to be used for a service by using one of the following:
173205

174-
### cds.connect.to <i> (name, options?) &#8594; service </i>
206+
- Process environment variables
207+
- Command line options
208+
- File system
209+
- Auto binding
175210

176-
Connects to a required service and returns a _Promise_ resolving to a corresponding _[Service](../cds/cdl#services)_ instance.
177-
Subsequent invocations with the same service name all return the same instance.
211+
For example, in development, you can add them to a _.env_ file as follows:
178212

179-
```js
180-
const srv = await cds.connect.to ('some-service')
181-
const { Books } = srv.entities
182-
await srv.run (SELECT.from(Books))
213+
```properties
214+
# .env file
215+
cds.requires.remote-service.credentials = { "url":"http://...", ... }
183216
```
184217

218+
::: warning ❗ Never add secrets or passwords to _package.json_ or _.cdsrc.json_!
219+
General rule of thumb: `.credentials` are always filled (and overridden) from process environment on process start.
220+
:::
185221

186-
_**Arguments:**_
187-
188-
* `name` is used to look up connect options from [configured services](#cds-env-requires).
189-
* `options` allows to provide _ad-hoc_ options, overriding [configured ones](#cds-env-requires).
190-
191-
192-
_**Caching:**_
193-
194-
Service instances are cached in [`cds.services`](cds-facade#cds-services), thus subsequent connects with the same service name return the initially connected one. As services constructed by [`cds.serve`](cds-serve#cds-serve) are registered with [`cds.services`](cds-facade#cds-services) as well, a connect finds and returns them as local service connections.
195-
196-
If _ad-hoc_ options are provided, the instance is not cached.
197-
198-
199-
200-
### cds.connect.to <i> (options) &#8594; service </i>
201-
202-
Ad-hoc connection (&rarr; only for tests):
203-
204-
```js
205-
cds.connect.to ({ kind:'sqlite', credentials:{database:'my.db'} })
206-
```
207222

208223

224+
### Basic Mechanism {#bindings-via-cds-env}
209225

210-
### cds.connect.to <i> ('\<kind\>:\<url\>') &#8594; service </i>
211226

212-
This is a shortcut for ad-hoc connections.
227+
The CAP Node.js runtime expects to find the service bindings in `cds.env.requires`.
213228

214-
For example:
215-
```js
216-
cds.connect.to ('sqlite:my.db')
217-
```
229+
1. Configured required services constitute endpoints for service bindings.
218230

219-
is equivalent to:
231+
```json
232+
"cds": {
233+
"requires": {
234+
"ReviewsService": {...},
235+
}
236+
}
237+
```
220238

221-
```js
222-
cds.connect.to ({kind: 'sqlite', credentials:{database:'my.db'}})
223-
```
239+
2. These are made available to the runtime via `cds.env.requires`.
224240

241+
```js
242+
const { ReviewsService } = cds.env.requires
243+
```
225244

245+
3. Service Bindings essentially fill in `credentials` to these entries.
226246

227-
## Service Bindings {#service-bindings}
247+
```js
248+
const { ReviewsService } = cds.env.requires
249+
ReviewsService.credentials = {
250+
url: "http://localhost:4005/reviews"
251+
}
252+
```
228253

229-
A service binding connects an application with a cloud service. For that, the cloud service's credentials need to be injected in the CDS configuration:
254+
The latter is appropriate in test suites. In productive code, you never provide credentials in a hard-coded way. Instead, use one of the options presented in the following sections.
230255

231-
```jsonc
232-
{
233-
"requires": {
234-
"db": {
235-
"kind": "hana",
236-
"credentials": { /* from service binding */ }
237-
}
238-
}
239-
}
240-
```
241256

242-
You specify the credentials to be used for a service by using one of the following:
243-
- Environment variables
244-
- File system
245-
- Auto binding
246257

247-
What to use depends on your environment.
248258

249259
### In Cloud Foundry {#bindings-in-cloud-platforms}
250260

@@ -258,6 +268,8 @@ Cloud Foundry uses auto configuration of service credentials through the `VCAP_S
258268

259269
[Learn more about environment variables on Cloud Foundry and `cf env`.](https://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html){.learn-more}
260270

271+
272+
261273
#### Through `VCAP_SERVICES` env var {#vcap_services}
262274

263275
When deploying to Cloud Foundry, service bindings are provided in `VCAP_SERVICES` process environment variables, which is JSON-stringified array containing credentials for multiple services. The entries are matched to the entries in `cds.requires` as follows, in order of precedence:
@@ -373,6 +385,8 @@ Here are a few examples:
373385
</table>
374386

375387

388+
389+
376390
### In Kubernetes / Kyma { #in-kubernetes-kyma}
377391

378392
CAP supports [servicebinding.io](https://servicebinding.io/) service bindings and SAP BTP service bindings created by the [SAP BTP Service Operator](https://github.com/SAP/sap-btp-service-operator).
@@ -608,79 +622,9 @@ The resulting `VCAP_SERVICES` env variable looks like this:
608622
```
609623

610624

611-
## Hybrid Testing
612-
613-
614-
In addition to the [static configuration of required services](#service-bindings), additional information, such as urls, secrets, or passwords are required to actually send requests to remote endpoints. These are dynamically filled into property `credentials` from process environments, as explained in the following.
615-
616-
617-
### cds.requires.<i>\<srv\></i>.credentials
618-
619-
All service binding information goes into this property. It's filled from the process environment when starting server processes, managed by deployment environments. Service bindings provide the details about how to reach a required service at runtime, that is, providing requisite credentials, most prominently the target service's `url`.
620-
621-
For development purposes, you can pass them on the command line or add them to a _.env_ or _default-env.json_ file as follows:
622-
623-
```properties
624-
# .env file
625-
cds.requires.remote-service.credentials = { "url":"http://...", ... }
626-
```
627-
::: warning
628-
❗ Never add secrets or passwords to _package.json_ or _.cdsrc.json_!
629-
General rule of thumb: `.credentials` are always filled (and overridden) from process environment on process start.
630-
:::
631-
632-
One prominent exception of that, which you would frequently add to your _package.json_ is the definition of a database file for persistent sqlite database during development:
633-
```json
634-
"cds": { "requires": {
635-
"db": {
636-
"kind": "sql",
637-
"[development]": {
638-
"kind": "sqlite",
639-
"credentials": {
640-
"url": "db/bookshop.sqlite"
641-
}
642-
}
643-
}
644-
}}
645-
```
646-
647-
648-
649-
650-
### Basic Mechanism {#bindings-via-cds-env}
651-
652-
653-
The CAP Node.js runtime expects to find the service bindings in `cds.env.requires`.
654-
655-
1. Configured required services constitute endpoints for service bindings.
656-
657-
```json
658-
"cds": {
659-
"requires": {
660-
"ReviewsService": {...},
661-
}
662-
}
663-
```
664-
665-
2. These are made available to the runtime via `cds.env.requires`.
666-
667-
```js
668-
const { ReviewsService } = cds.env.requires
669-
```
670-
671-
3. Service Bindings essentially fill in `credentials` to these entries.
672-
673-
```js
674-
const { ReviewsService } = cds.env.requires
675-
ReviewsService.credentials = {
676-
url: "http://localhost:4005/reviews"
677-
}
678-
```
679-
680-
The latter is appropriate in test suites. In productive code, you never provide credentials in a hard-coded way. Instead, use one of the options presented in the following sections.
681625

682626

683-
### Through _.cdsrc-private.json_ File for Local Testing
627+
### Through _.cdsrc-private.json_ File for Hybrid Testing
684628

685629
[Learn more about hybrid testing using _.cdsrc-private.json_.](../advanced/hybrid-testing#bind-to-cloud-services)
686630

0 commit comments

Comments
 (0)