Skip to content

Commit

Permalink
feat: move datasource config from JSON to TS files
Browse files Browse the repository at this point in the history
Rework the template for new datasources to store the datasource
configuration inside the TypeScript source code file
(e.g. `src/datasources/db.datasource.ts`) and stop emitting JSON files.

Update affected CLI commands like `lb4 repository` to support both
styles:
- legacy JSON-based configuration
- modern TS-based configuration

Update existing examples to use the new style.

Update relevant places in our documentation to use the new style too.

Signed-off-by: Miroslav Bajtoš <[email protected]>
  • Loading branch information
bajtos committed Apr 24, 2020
1 parent f19f2e4 commit 6105456
Show file tree
Hide file tree
Showing 60 changed files with 954 additions and 614 deletions.
1 change: 0 additions & 1 deletion docs/site/Appsody-LoopBack.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ Model Todo was created in src/models/
? Select the connector for db: In-memory db (supported by StrongLoop)
? window.localStorage key to use for persistence (browser only):
? Full path to file for persistence (server only): ./data/db.json
create src/datasources/db.datasource.config.json
create src/datasources/db.datasource.ts
update src/datasources/index.ts

Expand Down
88 changes: 43 additions & 45 deletions docs/site/Calling-other-APIs-and-Web-Services.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,31 @@ servicMethodName: {
```

If you have more than one operations to map, it might be easier to edit the
DataSource JSON after it's been created. See below for the example of the
mapping of the WSDL binding operations and Node.js methods.
DataSource configuration after it's been created. See below for the example of
the mapping of the WSDL binding operations and Node.js methods.

```json
{
"name": "ds",
"connector": "soap",
"url": "http://calculator-webservice.mybluemix.net/calculator",
"wsdl": "http://calculator-webservice.mybluemix.net/calculator?wsdl",
"remotingEnabled": true,
```ts
const config = {
name: 'ds',
connector: 'soap',
url: 'http://calculator-webservice.mybluemix.net/calculator',
wsdl: 'http://calculator-webservice.mybluemix.net/calculator?wsdl',
remotingEnabled: true,
// ADD THIS SNIPPET
"operations": {
"add": {
"service": "CalculatorService", //WSDL service name
"port": "CalculatorPort", //WSDL port name
"operation": "add" //WSDL operation name
operations: {
add: {
service: 'CalculatorService', //WSDL service name
port: 'CalculatorPort', //WSDL port name
operation: 'add', //WSDL operation name
},
"subtract": {
"service": "CalculatorService",
"port": "CalculatorPort",
"operation": "subtract"
}
}
subtract: {
service: 'CalculatorService',
port: 'CalculatorPort',
operation: 'subtract',
},
},
// END OF THE SNIPPET
}
};
```

For details, you can refer to the SOAP connector's operations property:
Expand All @@ -98,7 +98,6 @@ petstore.json
? Validate spec against Swagger spec 2.0?: No
? Security config for making authenticated requests to API:
? Use positional parameters instead of named parameters?: No
create src/datasources/ds.datasource.config.json
create src/datasources/ds.datasource.ts
```

Expand Down Expand Up @@ -127,8 +126,7 @@ $ lb4 datasource
? Use default CRUD mapping: No
```

The next step is to edit the DataSource JSON file for `options` and
`operations`.
The next step is to edit the DataSource file for `options` and `operations`.

The REST connector uses the
[request module](https://www.npmjs.com/package/request) as the HTTP client. You
Expand All @@ -139,30 +137,30 @@ The `template` object specifies the REST API invocation as a JSON template. You
can find more details in the
[Defining a custom method using a template page](https://loopback.io/doc/en/lb4/REST-connector.html#defining-a-custom-method-using-a-template).

```json
{
"name": "restds",
"connector": "rest",
"baseURL": "https://swapi.co/api/",
"crud": false,
"options": {
"headers": {
"accept": "application/json",
"content-type": "application/json"
}
```ts
const config = {
name: 'restds',
connector: 'rest',
baseURL: 'https://swapi.co/api/',
crud: false,
options: {
headers: {
accept: 'application/json',
'content-type': 'application/json',
},
},
"operations": [
operations: [
{
"template": {
"method": "GET",
"url": "https://swapi.co/api/people/{personId}"
template: {
method: 'GET',
url: 'https://swapi.co/api/people/{personId}',
},
"functions": {
"getCharacter": ["personId"]
}
}
]
}
functions: {
getCharacter: ['personId'],
},
},
],
};
```

## Add a service
Expand Down
95 changes: 91 additions & 4 deletions docs/site/DataSource-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,97 @@ Once all the prompts have been answered, the CLI will do the following:

- Install `@loopback/repository` and the connector package (if it's not a custom
connector).
- Create a file with the connector configuration as follows:
`/src/datasources/${dataSource.dataSourceName}.datasource.config.json`
- Create a DataSource class which recieves the connector config using
- Create a DataSource class which receives the connector config using
[Dependency Injection](Dependency-injection.md) as follows:
`/src/datasources/${dataSource.dataSourceName}.datasource.ts`
`/src/datasources/${dataSourceName}.datasource.ts`. The connector
configuration provided via CLI is available via static property
`defaultConfig`.
- Update `/src/datasources/index.ts` to export the newly created DataSource
class.

### Legacy JSON-based configuration

Datasources created by a CLI version from before April 2020 are using JSON-based
file convention for defining datasources:

- `/src/datasources/${dataSourceName}.datasource.config.json` contains
datasource configuration in JSON format, e.g. the connector name, target host
& port, credentials, and so on.
- `/src/datasources/${dataSourceName}.datasource.ts` defines a datasource class,
the default configuration is loaded from the JSON file.

CLI commands like `lb4 repository` and `lb4 service` support both the old
(JSON-based) and the current (pure TypeScript) styles, there are no changes
immediately needed to make your existing project work with the recent CLI
versions.

However, we recommend to eventually migrate existing datasource files to the new
style.

#### Migration guide

1. Open `{dataSourceName}.datasource.ts` file and replace import of `config`
from the JSON file with the actual content of the JSON file.

For example:

```diff
-import config from './db.datasource.config.json';
+
+const config = {
+ "name": "db",
+ "connector": "memory",
+ "localStorage": "",
+ "file": "./data/db.json",
+};
```

2. Save the file, run Prettier to fix the coding style (change double-quotes `"`
to single-quotes `'`, remove quotes from property names like `connector` and
`file`).

Example output using LoopBack's coding style:

```ts
const config = {
name: 'db',
connector: 'memory',
localStorage: '',
file: './data/db.json',
};
```

3. Add a static `defaultConfig` property to your datasource class.

For example:

```diff
export class DbDataSource extends juggler.DataSource {
static dataSourceName = 'db';
+ static readonly defaultConfig = config;

constructor(
```

4. Modify the tests importing the default datasource configuration from the JSON
file, get the default configuration via the new static property instead.

This is typically needed by tests for service proxies, which are are working
with a datasource connected to a web service. Datasources connected to a
database usually don't need different configuration for tests.

For example:

```diff
-import GEO_CODER_CONFIG from '../datasources/geocoder.datasource.config.json';
+import {GeocoderDataSource} from '../datasources/geocoder.datasource';

//...

export function getProxiedGeoCoderConfig(proxy: HttpCachingProxy) {
- return merge({}, GEO_CODER_CONFIG, {
+ return merge({}, GeocoderDataSource.defaultConfig, {
options: {
```

5. Delete the datasource JSON file, it's no longer needed.
20 changes: 11 additions & 9 deletions docs/site/DataSources.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,29 @@ It is recommended to use the [`lb4 datasource` command](DataSource-generator.md)
provided by the CLI to generate a DataSource. The CLI will prompt for all
necessary connector information and create the following files:

- `${dataSource.dataSourceName}.datasource.config.json` containing the connector
configuration
- `${dataSource.dataSourceName}.datasource.ts` containing a class extending
`juggler.DataSource`. This class can be used to override the default
DataSource behaviour programaticaly. Note: The connector configuration stored
in the `.json` file is injected into this class using
[Dependency Injection](Dependency-injection.md).
DataSource behavior programmatically. Note: The connector configuration is
available in a static property `defaultConfig` and can be injected into the
class constructor using [Dependency Injection](Dependency-injection.md).

Both the above files are generated in `src/datasources/` directory by the CLI.
It will also update `src/datasources/index.ts` to export the new DataSource
class.
The above file is generated in `src/datasources/` directory by the CLI. CLI will
also update `src/datasources/index.ts` to export the new DataSource class.

Example DataSource Class:

```ts
import {inject} from '@loopback/core';
import {juggler} from '@loopback/repository';
import config from './db.datasource.config.json';

const config = {
name: 'db',
connector: 'memory',
};

export class DbDataSource extends juggler.DataSource {
static dataSourceName = 'db';
static readonly defaultConfig = config;

constructor(
@inject('datasources.config.db', {optional: true})
Expand Down
23 changes: 9 additions & 14 deletions docs/site/OpenAPI-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,6 @@ export class AccountController {
If `--client` is specified, a datasource is generated to configure the
connection to the endpoint that exposes an OpenAPI spec.

{% include code-caption.html content="src/datasources/test2.datasource.config.json"
%}

```json
{
"name": "test2",
"connector": "openapi",
"spec": "customer.yaml",
"validate": false,
"positional": true
}
```

{% include code-caption.html content="src/datasources/test2.datasource.ts"
%}

Expand All @@ -421,12 +408,20 @@ import {
ValueOrPromise,
} from '@loopback/core';
import {juggler} from '@loopback/repository';
import config from './test2.datasource.config.json';
const config = {
name: 'test2',
connector: 'openapi',
spec: 'customer.yaml',
validate: false,
positional: true,
};
@lifeCycleObserver('datasource')
export class Test2DataSource extends juggler.DataSource
implements LifeCycleObserver {
static dataSourceName = 'test2';
static readonly defaultConfig = config;
constructor(
@inject('datasources.config.test2', {optional: true})
Expand Down
Loading

0 comments on commit 6105456

Please sign in to comment.