Skip to content

Commit

Permalink
fix(docs): refactor docs to create artifacts at runtime
Browse files Browse the repository at this point in the history
Signed-off-by: Diana Lau <[email protected]>
  • Loading branch information
dhmlau committed Nov 9, 2020
1 parent a034984 commit 510ba91
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 151 deletions.
15 changes: 15 additions & 0 deletions docs/site/Creating-artifacts-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
lang: en
title: 'Creating Artifacts at Runtime'
keywords: LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Creating-artifacts-runtime.html
summary: Create LoopBack artifacts at runtime
---

Besides using the [command-line interface](Command-line-interface.md) to
generate LoopBack artifacts, you can also create the artifacts below at runtime:

- [Model](Creating-model-runtime.md)
- [DataSource](Creating-datasource-runtime.md)
- [Repository](Creating-repository-runtime.md)
35 changes: 35 additions & 0 deletions docs/site/Creating-datasource-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
lang: en
title: 'Creating DataSources at Runtime'
keywords: LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI, DataSource
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Creating-datasource-runtime.html
summary: Create LoopBack DataSources at runtime
---

A datasource can be created at runtime by creating an instance of
`juggler.DataSource`. It requires a name for the datasource, the connector, and
the connection details.

```ts
import {juggler} from '@loopback/repository';
const dsName = 'bookstore-ds';
const bookDs = new juggler.DataSource({
name: dsName,
connector: require('loopback-connector-mongodb'),
url: 'mongodb://sysop:moon@localhost',
});
await bookDs.connect();
app.dataSource(bookDs, dsName);
```

For details about datasource options, refer to the [DataSource
documentation])(https://apidocs.strongloop.com/loopback-datasource-juggler/#datasource)
.

Attach the newly created datasource to the app by calling `app.dataSource()`.

{% include note.html content="
The `app.datasource()` method is available only on application classes
with `RepositoryMixin` applied.
" %}
52 changes: 52 additions & 0 deletions docs/site/Creating-model-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
lang: en
title: 'Creating Models at Runtime'
keywords: LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI, Model
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Creating-model-runtime.html
summary: Create LoopBack Models at runtime
---

Models can also be created at runtime using the `defineModelClass()` helper
function from the `@loopback/repository` class. It expects a base model to
extend (typically `Model` or `Entity`), followed by a `ModelDefinition` object
as shown in the example below.

```ts
const bookDef = new ModelDefinition('Book')
.addProperty('id', {type: 'number', id: true})
.addProperty('title', {type: 'string'});
const BookModel = defineModelClass<typeof Entity, {id: number; title?: string}>(
Entity, // Base model
bookDef, // ModelDefinition
);
```

You will notice that we are specifying generic parameters for the
`defineModelClass()` function. The first parameter is the base model, the second
one is an interface providing the TypeScript description for the properties of
the model we are defining. If the interface is not specified, the generated
class will have only members inherited from the base model class, which
typically means no properties.

In case you need to use an existing Model as the base class, specify the Model
as the base class instead of `Entity`.

```ts
// Assuming User is a pre-existing Model class in the app
import {User} from './user.model';
import DynamicModelCtor from '@loopback/repository';
const StudentModel = defineModelClass<
typeof User,
// id being provided by the base class User
{university?: string}
>(User, studentDef);
```

If you want make this new Model available from other parts of the app, you can
call `app.model(StudentModel)` to create a binding for it.

{% include note.html content="
The `app.model()` method is available only on application classes with
`RepositoryMixin` applied.
" %}
79 changes: 79 additions & 0 deletions docs/site/Creating-repository-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
lang: en
title: 'Creating Repositories at Runtime'
keywords: LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI, Repository
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Creating-repository-runtime.html
summary: Create LoopBack Repositories at runtime
---

Repositories can be created at runtime using the `defineCrudRepositoryClass`
helper function from the `@loopback/rest-crud` package. It creates
`DefaultCrudRepository`-based repository classes by default.

```ts
const BookRepository = defineCrudRepositoryClass<
Book,
typeof Book.prototype.id,
BookRelations
>(BookModel);
```

In case you want to use a non-`DefaultCrudRepository` repository class or you
want to create a custom repository, use the `defineRepositoryClass()` helper
function instead. Pass a second parameter to this function as the base class for
the new repository.

There are two options for doing this:

## 1. Using a base repository class

Create a base repository with your custom implementation, and then specify this
repository as the base class.

```ts
class MyRepoBase<
E extends Entity,
IdType,
Relations extends object
> extends DefaultCrudRepository<E, IdType, Relations> {
// Custom implementation
}

const BookRepositoryClass = defineRepositoryClass<
typeof BookModel,
MyRepoBase<BookModel, typeof BookModel.prototype.id, BookRelations>
>(BookModel, MyRepoBase);
```

## 2. Using a Repository mixin

Create a repository mixin with your customization as shown in the
[Defining A Repository Mixin Class Factory Function](https://loopback.io/doc/en/lb4/migration-models-mixins.html#defining-a-repository-mixin-class-factory-function)
example, apply the mixin on the base repository class (e.g.
`DefaultCrudRepository`) then specify this combined repository as the base class
to be used.

```ts
const BookRepositoryClass = defineRepositoryClass<
typeof BookModel,
DefaultCrudRepository<
BookModel,
typeof BookModel.prototype.id,
BookRelations
> &
FindByTitle<BookModel>
>(BookModel, FindByTitleRepositoryMixin(DefaultCrudRepository));
```

Dependency injection has to be configured for the datasource as shown below.

```ts
inject(`datasources.${dsName.name}`)(BookRepository, undefined, 0);
const repoBinding = app.repository(BookRepository);
```

{% include note.html content="
The `app.repository()` method is available only on application classes
with `RepositoryMixin` applied.
" %}
29 changes: 2 additions & 27 deletions docs/site/DataSource.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,34 +54,9 @@ export class DbDataSource extends juggler.DataSource {
}
```

### Creating a DataSource at Runtime
### Common Tasks

A datasource can be created at runtime by creating an instance of
`juggler.DataSource`. It requires a name for the datasource, the connector, and
the connection details.

```ts
import {juggler} from '@loopback/repository';
const dsName = 'bookstore-ds';
const bookDs = new juggler.DataSource({
name: dsName,
connector: require('loopback-connector-mongodb'),
url: 'mongodb://sysop:moon@localhost',
});
await bookDs.connect();
app.dataSource(bookDs, dsName);
```

For details about datasource options, refer to the [DataSource
documentation])(https://apidocs.strongloop.com/loopback-datasource-juggler/#datasource)
.

Attach the newly created datasource to the app by calling `app.dataSource()`.

{% include note.html content="
The `app.datasource()` method is available only on application classes
with `RepositoryMixin` applied.
" %}
- [Create DataSource at runtime](Creating-datasource-runtime.md)

### Connector

Expand Down
54 changes: 3 additions & 51 deletions docs/site/Model.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,58 +143,10 @@ export class Customer {
}
```
### Defining a Model at Runtime
## Common Tasks
Models can also be created at runtime using the `defineModelClass()` helper
function from the `@loopback/repository` class. It expects a base model to
extend (typically `Model` or `Entity`), followed by a `ModelDefinition` object
as shown in the example below.

```ts
const bookDef = new ModelDefinition('Book')
.addProperty('id', {type: 'number', id: true})
.addProperty('title', {type: 'string'});
const BookModel = defineModelClass<typeof Entity, {id: number; title?: string}>(
Entity, // Base model
bookDef, // ModelDefinition
);
```
You will notice that we are specifying generic parameters for the
`defineModelClass()` function. The first parameter is the base model, the second
one is an interface providing the TypeScript description for the properties of
the model we are defining. If the interface is not specified, the generated
class will have only members inherited from the base model class, which
typically means no properties.

In case you need to use an existing Model as the base class, specify the Model
as the base class instead of `Entity`.

```ts
// Assuming User is a pre-existing Model class in the app
import {User} from './user.model';
import DynamicModelCtor from '@loopback/repository';
const StudentModel = defineModelClass<
typeof User,
// id being provided by the base class User
{university?: string}
>(User, studentDef);
```
If you want make this new Model available from other parts of the app, you can
call `app.model(StudentModel)` to create a binding for it.
{% include note.html content="
The `app.model()` method is available only on application classes with
`RepositoryMixin` applied.
" %}
### Model Discovery
Instead of creating models from scratch, LoopBack can automatically generate
model definitions by discovering the schema of your database. See
[Discovering models](Discovering-models.md) for more details and a list of
connectors supporting model discovery.
- [Define models at runtime](Creating-model-runtime.md)
- [Discover models from databases](DIscovering-models.md)
## Model Metadata
Expand Down
77 changes: 4 additions & 73 deletions docs/site/Repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ as a dependency in your application.
You can then install your favorite connector by saving it as part of your
application dependencies.

## Common Tasks

- [Creating Repository at runtime](Creating-repository-runtime.md)

## Repository Mixin

`@loopback/repository` provides a mixin for your Application that enables
Expand Down Expand Up @@ -301,79 +305,6 @@ Please See [Testing Your Application](Testing-your-application.md) section in
order to set up and write unit, acceptance, and integration tests for your
application.

## Creating Repositories at Runtime

Repositories can be created at runtime using the `defineCrudRepositoryClass`
helper function from the `@loopback/rest-crud` package. It creates
`DefaultCrudRepository`-based repository classes by default.

```ts
const BookRepository = defineCrudRepositoryClass<
Book,
typeof Book.prototype.id,
BookRelations
>(BookModel);
```

In case you want to use a non-`DefaultCrudRepository` repository class or you
want to create a custom repository, use the `defineRepositoryClass()` helper
function instead. Pass a second parameter to this function as the base class for
the new repository.

There are two options for doing this:

#### 1. Using a base repository class

Create a base repository with your custom implementation, and then specify this
repository as the base class.

```ts
class MyRepoBase<
E extends Entity,
IdType,
Relations extends object
> extends DefaultCrudRepository<E, IdType, Relations> {
// Custom implementation
}

const BookRepositoryClass = defineRepositoryClass<
typeof BookModel,
MyRepoBase<BookModel, typeof BookModel.prototype.id, BookRelations>
>(BookModel, MyRepoBase);
```

#### 2. Using a Repository mixin

Create a repository mixin with your customization as shown in the
[Defining A Repository Mixin Class Factory Function](https://loopback.io/doc/en/lb4/migration-models-mixins.html#defining-a-repository-mixin-class-factory-function)
example, apply the mixin on the base repository class (e.g.
`DefaultCrudRepository`) then specify this combined repository as the base class
to be used.

```ts
const BookRepositoryClass = defineRepositoryClass<
typeof BookModel,
DefaultCrudRepository<
BookModel,
typeof BookModel.prototype.id,
BookRelations
> &
FindByTitle<BookModel>
>(BookModel, FindByTitleRepositoryMixin(DefaultCrudRepository));
```

Dependency injection has to be configured for the datasource as shown below.

```ts
inject(`datasources.${dsName.name}`)(BookRepository, undefined, 0);
const repoBinding = app.repository(BookRepository);
```

{% include note.html content="
The `app.repository()` method is available only on application classes
with `RepositoryMixin` applied.
" %}

## Access KeyValue Stores

We can now access key-value stores such as [Redis](https://redis.io/) using the
Expand Down
14 changes: 14 additions & 0 deletions docs/site/sidebars/lb4_sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ children:
url: Using-openapi-to-graphql.html
output: 'web, pdf'

- title: 'Creating Artifacts at Runtime'
url: Creating-artifacts-runtime.html
output: 'web, pdf'
children:
- title: 'Creating Model at Runtime'
url: Creating-model-runtime.html
output: 'web, pdf'
- title: 'Creating DataSource at Runtime'
url: Creating-datasource-runtime.html
output: 'web, pdf'
- title: 'Creating Repositories at Runtime'
url: Creating-repository-runtime.html
output: 'web, pdf'

- title: 'Building frontend applications'
output: 'web, pdf'
children:
Expand Down

0 comments on commit 510ba91

Please sign in to comment.