Skip to content

Commit

Permalink
fix(databases): Improve documentation for adapters and allow dynamic …
Browse files Browse the repository at this point in the history
…Knex adapter options (#3019)
  • Loading branch information
daffl authored Jan 28, 2023
1 parent f1c7a76 commit 66c4b5e
Show file tree
Hide file tree
Showing 14 changed files with 614 additions and 763 deletions.
16 changes: 8 additions & 8 deletions docs/api/databases/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ Feathers database adapters are modules that provide [services](../services.md) t

<BlockQuote>

[Services](../services.md) allow to implement access to _any_ database or API. The database adapters listed here are just convenience wrappers with a common API. See the community adapters section for support for other datastores.
[Services](../services.md) allow to implement access to _any_ database or API. The database adapters listed here are just convenience wrappers with a common API. See the community adapters section for support for other datastores.

</BlockQuote>

## Core Adapters

The following data storage adapters are maintained alongside Feathers core.
The following data storage adapters are available in Feathers core

| Core Package | Supported Data Stores |
|---|---|
| [memory](./memory) | Memory |
| [mongodb](./mongodb) | MongoDB |
| [knex](./knex) | MySQL<br/> MariaDB <br/> PostgreSQL<br/> CockroachDB<br/> SQLite<br/> Amazon Redshift<br/> OracleDB<br/> MSSQL | [feathers-knex](https://github.com/feathersjs-ecosystem/feathers-knex) |
| Core Package | Supported Data Stores |
| -------------------- | -------------------------------------------------------------------------------------------------------------- |
| [Memory](./memory) | Memory |
| [MongoDB](./mongodb) | MongoDB |
| [SQL (Knex)](./knex) | MySQL<br/> MariaDB <br/> PostgreSQL<br/> CockroachDB<br/> SQLite<br/> Amazon Redshift<br/> OracleDB<br/> MSSQL |

## Community Adapters

You can find full-featured support for many more community-contributed adapters in [Awesome FeathersJS](https://github.com/feathersjs/awesome-feathersjs#database).
There are also many community maintained adapters for other databases and ORMs which can be found on the [Ecosystem page](/ecosystem/?cat=Database&sort=lastPublish).
129 changes: 38 additions & 91 deletions docs/api/databases/common.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,21 @@ app.use('/messages', new NameService())
app.use('/messages', new NameService({ id, events, paginate }))
```

### `service([options])`

The `service` function returns a new service instance initialized with the given options. Internally just calls `new NameService(options)` from above.

```ts
import { service } from 'feathers-<name>'

app.use('/messages', service())
app.use('/messages', service({ id, events, paginate }))
```

### Options

The following options are available for all database adapters:

- `id` (_optional_) - The name of the id field property (usually set by default to `id` or `_id`).
- `paginate` (_optional_) - A [pagination object](#pagination) containing a `default` and `max` page size
- `multi` (_optional_, default: `false`) - Allow `create` with arrays and `patch` and `remove` with id `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`)

The following legacy options are still available but should be avoided:

- `events` (_optional_, **deprecated**) - A list of [custom service events](../events.md#custom-events) sent by this service. Use the `events` option when [registering the service with app.use](../application.md#usepath-service--options) instead.
- `operators` (_optional_, **deprecated**) - A list of additional non-standard query parameters to allow (e.g `[ '$regex' ]`). Not necessary when using a [query schema validator](../schema/validators.md#validatequery)
- `filters` (_optional_, **deprecated**) - A list of top level `$` query parameters to allow (e.g. `[ '$populate' ]`). Not necessary when using a [query schema validator](../schema/validators.md#validatequery)
- `operators` (_optional_, **deprecated**) - A list of additional non-standard query parameters to allow (e.g `[ '$regex' ]`). Not necessary when using a [query schema](../schema/validators.md#validatequery)
- `filters` (_optional_, **deprecated**) - A list of top level `$` query parameters to allow (e.g. `[ '$populate' ]`). Not necessary when using a [query schema](../schema/validators.md#validatequery)

For database specific options see the adapter documentation.

## Pagination

Expand Down Expand Up @@ -102,75 +95,53 @@ Disabling or changing the default pagination is not available in the client. Onl

</BlockQuote>

## Extending Adapters

There are two ways to extend existing database adapters. Either by extending the base class or by adding functionality through hooks.

### Classes

All modules also export an [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes) as `Service` that can be directly extended like this:

```js
'use strict'

const { Service } = require('feathers-<database>')
## params.adapter

class MyService extends Service {
create(data, params) {
data.created_at = new Date()
Setting the `adapter` in the [service method `params`](../services.md#params) allows do dynamically modify the database adapter options based on the request. This e.g. allows to temporarily allow multiple entry creation/changes or the pagination settings.

return super.create(data, params)
```ts
const messages = [
{
text: 'message 1'
},
{
text: 'message 2'
}
]

update(id, data, params) {
data.updated_at = new Date()

return super.update(id, data, params)
// Enable multiple entry insertion for this request
app.service('messages').create(messages, {
adapter: {
multi: true
}
}

app.use(
'/todos',
new MyService({
paginate: {
default: 2,
max: 4
}
})
)
})
```

### Hooks
<BlockQuote type="tip">

Another option is weaving in functionality through [hooks](../hooks.md). For example, `createdAt` and `updatedAt` timestamps could be added like this:
If the adapter has a `Model` option, `params.adapter.Model` can be used to point to different databases based on the request to e.g. allow multi-tenant systems. This is usually done by setting `context.params.adapter` in a [hook](../hooks.md).

```js
const feathers = require('@feathersjs/feathers')
</BlockQuote>

// Import the database adapter of choice
const service = require('feathers-<adapter>')
## params.paginate

const app = feathers().use(
'/todos',
service({
paginate: {
default: 2,
max: 4
}
})
)

app.service('todos').hooks({
before: {
create: [(context) => (context.data.createdAt = new Date())],
Setting `paginate` in the [service method `params`](../services.md#params) allows to change or disable the default pagination for a single request:

update: [(context) => (context.data.updatedAt = new Date())]
}
```ts
// Get all messages as an array
const allMessages = await app.service('messages').find({
paginate: false
})

app.listen(3030)
```

## Extending Adapters

There are two ways to extend existing database adapters. Either by extending the base class or by adding functionality through hooks.

### Classes

All modules also export an [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes) as `<Name>Service` that can be directly extended. See the [Service CLI guide](../../guides/cli/service.class.md) on how to override existing and implement new methods.

## Service methods

This section describes specifics on how the [service methods](../services.md) are implemented for all adapters.
Expand All @@ -194,30 +165,6 @@ These methods are only available internally on the server, not on the client sid

</BlockQuote>

### adapter.Model

If the ORM or database supports models, the model instance or reference to the collection belonging to this adapter can be found in `adapter.Model`. This allows to easily make custom queries using that model, e.g. in a hook:

```js
// Make a MongoDB aggregation (`messages` is using `feathers-mongodb`)
app.service('messages').hooks({
before: {
async find(context) {
const results = await service.Model.aggregate([
{ $match: { item_id: id } },
{
$group: { _id: null, total_quantity: { $sum: '$quantity' } }
}
]).toArray()

// Do something with results

return context
}
}
})
```

### adapter.find(params)

`adapter.find(params) -> Promise` returns a list of all records matching the query in `params.query` using the [common querying mechanism](./querying.md). Will either return an array with the results or a page object if [pagination is enabled](#pagination).
Expand Down
Loading

0 comments on commit 66c4b5e

Please # to comment.