Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32,485 changes: 25,266 additions & 7,219 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"node": ">= 22"
},
"workspaces": [
"packages/*"
"packages/*",
"website"
],
"scripts": {
"publish": "lerna publish --force-publish && git commit -am \"chore: Update changelog\" && git push origin",
Expand Down
6 changes: 3 additions & 3 deletions website/app/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
@plugin "@tailwindcss/typography";
@plugin "daisyui";

@source "../../../node_modules/daisy-ui-kit/app/components/*.{vue,js}";
@source "../../../node_modules/@feathersdev/websites/app/components/**/*.{vue,js}";
@source "../../../node_modules/@feathersdev/websites/app/layouts/*.{vue,js}";
@source "../../../../node_modules/daisy-ui-kit/app/components/*.{vue,js}";
@source "../../../../node_modules/@feathersdev/websites/app/components/**/*.{vue,js}";
@source "../../../../node_modules/@feathersdev/websites/app/layouts/*.{vue,js}";
@source "../../components/**/*.{vue,js,jsx,mjs,ts,tsx}";
@source "../../layouts/**/*.{vue,js,jsx,mjs,ts,tsx}";
@source "../../pages/**/*.{vue,js,jsx,mjs,ts,tsx}";
Expand Down
1 change: 0 additions & 1 deletion website/app/components/TopNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const { openSearch } = useGlobalSearch()
<Flex row items-center class="gap-6 rounded-box bg-base-100/10 p-3 sm:px-12">
<NuxtLink to="/guides">Guides</NuxtLink>
<NuxtLink to="/api">API</NuxtLink>
<NuxtLink to="/cookbook">Cookbook</NuxtLink>
<NuxtLink to="/help">Help</NuxtLink>
</Flex>
</NavbarCenter>
Expand Down
1 change: 0 additions & 1 deletion website/app/layouts/page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<div class="relative pt-0">
<NuxtPage />
</div>
<MoonSurface />
<FooterMain />
</main>
</template>
39 changes: 10 additions & 29 deletions website/content/api/application.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
# Application

::badges{npm="@feathersjs/feathers" changelog="https://github.com/feathersjs/feathers/blob/dove/packages/feathers/CHANGELOG.md"}
::

```
npm install @feathersjs/feathers --save
npm install feathers@pre --save
```

The core `@feathersjs/feathers` module provides the ability to initialize a new Feathers application instance. It works in Node, React Native and the browser (see the [client](./client) chapter for more information). Each instance allows for registration and retrieval of [services](./services), [hooks](./hooks), plugin configuration, and getting and setting configuration options. An initialized Feathers application is referred to as the **app object**.
`import { feathers } from 'feathers` provides the ability to initialize a new Feathers application instance. It works on all runtimes, React Native and the browser (see the [client](./client) chapter for more information). Each instance allows for registration and retrieval of [services](./services), [hooks](./hooks), plugin configuration, and getting and setting configuration options. An initialized Feathers application is referred to as the **app object**.

```ts
import { feathers } from '@feathersjs/feathers'
import { feathers } from 'feathers'

type ServiceTypes = {
// Add registered services here
Expand All @@ -29,7 +26,7 @@ const app = feathers<ServiceTypes, Configuration>()
`app.use(path, service [, options]) -> app` allows registering a [service object](./services) on a given `path`.

```ts
import { feathers, type Id } from '@feathersjs/feathers'
import { feathers, type Id } from 'feathers'

class MessageService {
async get(id: Id) {
Expand Down Expand Up @@ -171,7 +168,7 @@ app.configure(setupService)
## .setup([server])

`app.setup([server]) -> Promise<app>` is used to initialize all services by calling each [services .setup(app, path)](services#setupapp-path) method (if available).
It will also use the `server` instance passed (e.g. through `http.createServer`) to set up SocketIO (if enabled) and any other provider that might require the server instance. You can register [application setup hooks](./hooks#setup-and-teardown) to e.g. set up database connections and other things required to be initialized on startup in a certain order.
It will also use the `server` instance passed (e.g. through `http.createServer`). You can register [application setup hooks](./hooks#setup-and-teardown) to e.g. set up database connections and other things required to be initialized on startup in a certain order.

Normally `app.setup` will be called automatically when starting the application via [app.listen([port])](#listen-port) but there are cases (like in tests) when it can be called explicitly.

Expand All @@ -194,7 +191,7 @@ Normally `app.setup` will be called automatically when starting the application
::

```ts
import { feathers } from '@feathersjs/feathers'
import { feathers } from 'feathers'

type ServiceTypes = {
// Add services path to type mapping here
Expand Down Expand Up @@ -222,15 +219,15 @@ On the server, settings are usually initialized using [Feathers configuration](c

## .on(eventname, listener)

Provided by the core [NodeJS EventEmitter .on](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener). Registers a `listener` method (`function(data) {}`) for the given `eventname`.
Provided by the [EventEmitter .on](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener). Registers a `listener` method (`function(data) {}`) for the given `eventname`.

```js
app.on('login', (user) => console.log('Logged in', user))
```

## .emit(eventname, data)

Provided by the core [NodeJS EventEmitter .emit](https://nodejs.org/api/events.html#events_emitter_emit_eventname_args).
Provided by the [EventEmitter .emit](https://nodejs.org/api/events.html#events_emitter_emit_eventname_args).

```ts
type MyEventData = { message: string }
Expand All @@ -248,14 +245,14 @@ app.on('myevent', (data: MyEventData) => console.log('myevent happened', data))

## .removeListener(eventname)

Provided by the core [NodeJS EventEmitter .removeListener](https://nodejs.org/api/events.html#events_emitter_removelistener_eventname_listener). Removes all or the given listener for `eventname`.
Provided by the [EventEmitter .removeListener](https://nodejs.org/api/events.html#events_emitter_removelistener_eventname_listener). Removes all or the given listener for `eventname`.

## .mixins

`app.mixins` contains a list of service mixins. A mixin is a callback (`(service, path, options) => {}`) that gets run for every service that is being registered. Adding your own mixins allows to add functionality to every registered service.

```ts
import type { Id } from '@feathersjs/feathers'
import type { Id } from 'feathers'

// Mixins have to be added before registering any services
app.mixins.push((service: any, path: string) => {
Expand Down Expand Up @@ -290,22 +287,6 @@ servicePaths.forEach((path) => {
To retrieve services use [app.service(path)](#service-path), not `app.services[path]` directly.
::

A Feathers [client](client) does not know anything about the server it is connected to. This means that `app.services` will _not_ automatically contain all services available on the server. Instead, the server has to provide the list of its services, e.g. through a [custom service](./services):

```ts
class InfoService {
constructor(public app: Application) {}

async find() {
return {
service: Object.keys(this.app.services)
}
}
}

app.use('info', new InfoService(app))
```

## .defaultService

`app.defaultService` can be a function that returns an instance of a new standard service for `app.service(path)` if there isn't one registered yet. By default it throws a `NotFound` error when you are trying to access a service that doesn't exist.
Expand Down
21 changes: 8 additions & 13 deletions website/content/api/errors.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
# Errors

::badges{npm="@feathersjs/errors" changelog="https://github.com/feathersjs/feathers/blob/dove/packages/errors/CHANGELOG.md"}
::

```
npm install @feathersjs/errors --save
```

The `@feathersjs/errors` module contains a set of standard error classes used by all other Feathers modules.
`feathersjs/errors` contains a set of standard error classes used by all other Feathers modules.

## Examples

Here are a few ways that you can use them:

```ts
import { NotFound, GeneralError, BadRequest } from '@feathersjs/errors'
import { NotFound, GeneralError, BadRequest } from 'feathers/errors'

// If you were to create an error yourself.
const notFound = new NotFound('User does not exist')
Expand Down Expand Up @@ -67,7 +60,7 @@ The following error types, all of which are instances of `FeathersError`, are av
- 503: `Unavailable`

::tip
All of the Feathers core modules and most plugins and database adapters automatically emit the appropriate Feathers errors for you. For example, most of the database adapters will already send `Conflict` or `Unprocessable` errors on validation errors.
All of the Feathers core modules and most plugins automatically emit the appropriate Feathers errors for you.
::

Feathers errors contain the following fields:
Expand Down Expand Up @@ -109,13 +102,15 @@ console.log(error.toJSON())

## Error Handling

It is important to make sure that errors get cleaned up before they go back to the client. [Express error handling middleware](https://docs.feathersjs.com/api/express.html#expresserrorhandler) works only for REST calls. If you want to make sure that ws errors are handled as well, you need to use [application error hooks](hooks#application-hooks) which are called on any service call error.
It is important to make sure that errors get cleaned up before they go back to the client. If you want to make sure that ws errors are handled as well, you need to use [application error hooks](hooks#application-hooks) which are called on any service call error.

Here is an example error handler you can add to app.hooks errors.

```js
const errors = require('@feathersjs/errors')
const errorHandler = (ctx) => {
import type { NextFunction, HookContext } from 'feathers'
import { GeneralError } from 'feathers/errors'

export const errorHandler = (ctx: HookContext) => {
if (ctx.error) {
const error = ctx.error
if (!error.code) {
Expand Down
14 changes: 4 additions & 10 deletions website/content/api/hooks.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@


# Hooks

Hooks are pluggable middleware functions that can be registered **around**, **before**, **after** or on **error**(s) of a [service method](./services). Multiple hook functions can be chained to create complex work-flows. A hook is **transport independent**, which means it does not matter if it has been called internally on the server, through HTTP(S) (REST), websockets or any other transport Feathers supports. They are also service agnostic, meaning they can be used with ​**any**​ service regardless of whether they use a database or not.
Hooks are pluggable middleware functions that can be registered **around**, **before**, **after** or on **error**(s) of a [service method](./services). Multiple hook functions can be chained to create complex work-flows. A hook is **transport independent**, which means it does not matter if it has been called internally on the server, through HTTP(S) or any other transport Feathers supports. They are also service agnostic, meaning they can be used with ​**any**​ service regardless of whether they use a database or not.

Hooks are commonly used to handle things like permissions, validation, logging, [authentication](./authentication/hook), [data schemas and resolvers](./schema/index), sending notifications and more. This pattern keeps your application logic flexible, composable, and easier to trace through and debug. For more information about the design patterns behind hooks see [this blog post](https://blog.feathersjs.com/api-service-composition-with-hooks-47af13aa6c01).
Hooks are commonly used to handle things like permissions, validation, logging, authentication, sending notifications and more. This pattern keeps your application logic flexible, composable, and easier to trace through and debug.

## Quick Example

The following example logs the runtime of any service method on the `messages` service and adds `createdAt` property before saving the data to the database:

```ts
import { feathers, type HookContext, type NextFunction } from '@feathersjs/feathers'
import { feathers, type HookContext, type NextFunction } from 'feathers'

const app = feathers()

Expand Down Expand Up @@ -42,10 +40,6 @@ app.service('messages').hooks({
})
```

::note
While it is always possible to add properties like `createdAt` in the above example via hooks, the preferred way to make data modifications like this in Feathers 5 is via [schemas and resolvers](./schema/index).
::

## Hook functions

### before, after and error
Expand Down Expand Up @@ -125,7 +119,7 @@ app.service('messages').hooks({

### Setting `context.result`

When `context.result` is set in an `around` hook before calling `await next()` or in a `before` hook, the original [service method](./services) call will be skipped. All other hooks will still execute in their normal order. The following example always returns the currently [authenticated user](./authentication/service) instead of the actual user for all `get` method calls:
When `context.result` is set in an `around` hook before calling `await next()` or in a `before` hook, the original [service method](./services) call will be skipped. All other hooks will still execute in their normal order. The following example always returns the current user instead of the actual user for all `get` method calls:

```js
app.service('users').hooks({
Expand Down
Loading