Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 6 additions & 19 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,19 @@ jobs:

strategy:
matrix:
node-version: [18.x, 20.x]

services:
postgres:
image: postgres:latest
env:
POSTGRES_DB: feathers
POSTGRES_PASSWORD: postgres
POSTGRES_PORT: 5432
POSTGRES_USER: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
node-version: [20.x, 24.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm i -g npm
# Removing node_modules and package-lock.json is a workaround for some Rollup on Linux bug
- run: |
rm -rf node_modules package-lock.json
npm install
- run: npm test
env:
CI: true
TEST_DB: postgres
7 changes: 0 additions & 7 deletions .mocharc.json

This file was deleted.

1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
47 changes: 0 additions & 47 deletions .nycrc

This file was deleted.

45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,51 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [6.0.0-pre.5](https://github.com/feathersjs/feathers/compare/v6.0.0-pre.4...v6.0.0-pre.5) (2025-12-20)

**Note:** Version bump only for package feathers

# [6.0.0-pre.4](https://github.com/feathersjs/feathers/compare/v6.0.0-pre.3...v6.0.0-pre.4) (2025-12-20)

### Bug Fixes

- Do not allow id or undefined in fetch client .get ([#3632](https://github.com/feathersjs/feathers/issues/3632)) ([4faeeec](https://github.com/feathersjs/feathers/commit/4faeeecf0911dcf1cd121446c9ac22c7b0aa0c9d))

### Features

- **http:** Add multipart/form-data support for file uploads ([#3634](https://github.com/feathersjs/feathers/issues/3634)) ([8476bf2](https://github.com/feathersjs/feathers/commit/8476bf23b10218e531f2ad93f3c5934e1582da7b))
- **http:** Add streaming request body support ([#3635](https://github.com/feathersjs/feathers/issues/3635)) ([4c2aa85](https://github.com/feathersjs/feathers/commit/4c2aa859465da46334b9b5d2209766a17d71a8b7))

# [6.0.0-pre.3](https://github.com/feathersjs/feathers/compare/v6.0.0-pre.2...v6.0.0-pre.3) (2025-10-10)

### Bug Fixes

- Fix redirect URI encoding ([#3621](https://github.com/feathersjs/feathers/issues/3621)) ([4dbcce5](https://github.com/feathersjs/feathers/commit/4dbcce598d894846899417cd51820a70b00f22e0))

# [6.0.0-pre.2](https://github.com/feathersjs/feathers/compare/v6.0.0-pre.1...v6.0.0-pre.2) (2025-09-04)

### Bug Fixes

- Add typesVersions for TypeScript compatibility ([87c181c](https://github.com/feathersjs/feathers/commit/87c181cf8d3bcd4f86d0caad41de83d220077ad8))

# [6.0.0-pre.1](https://github.com/feathersjs/feathers/compare/v6.0.0-pre.0...v6.0.0-pre.1) (2025-09-03)

### Bug Fixes

- Add compatibility exports ([#3605](https://github.com/feathersjs/feathers/issues/3605)) ([3aed869](https://github.com/feathersjs/feathers/commit/3aed8696ca95fe4a4351c2d7e7f274ab66b50c09))
- Add registerPublisher method to protected method list ([2c0664a](https://github.com/feathersjs/feathers/commit/2c0664acf97dca3bf7a2efaf3564f04c3de5842e))

# [6.0.0-pre.0](https://github.com/feathersjs/feathers/compare/v5.0.34...v6.0.0-pre.0) (2025-08-30)

### Bug Fixes

- Make handling of async iterables consistent ([#3602](https://github.com/feathersjs/feathers/issues/3602)) ([a29ea3c](https://github.com/feathersjs/feathers/commit/a29ea3c89bf0fe07f0aec823ef3f3e33941f1aa3))

### Features

- SSE real-time events ([#3601](https://github.com/feathersjs/feathers/issues/3601)) ([fbfb75c](https://github.com/feathersjs/feathers/commit/fbfb75c5a2fde7ff785a71e787e746952b7a47b3))
- V6 packages refactor ([#3596](https://github.com/feathersjs/feathers/issues/3596)) ([364aab5](https://github.com/feathersjs/feathers/commit/364aab563542fc9d6dd96c1f5f48b146727d7d1e))

## [5.0.34](https://github.com/feathersjs/feathers/compare/v5.0.33...v5.0.34) (2025-05-03)

### Bug Fixes
Expand Down
3 changes: 1 addition & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2024 Feathers Contributors
Copyright (c) 2025 Feathers Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<a href="https://feathersjs.com" title="FeathersJS">
<img src="https://feathersjs.com/og.png" alt="Feathers - The API and real-time application framework">
<img src="https://feathersjs.com/og.svg" alt="Feathers - The API and real-time application framework">
</a>

---
Expand All @@ -10,7 +10,7 @@

Feathers is a full-stack framework for creating web APIs and real-time applications with TypeScript or JavaScript.

Feathers can interact with any backend technology, supports many databases out of the box and works with any frontend like React, VueJS, Angular, React Native, Android or iOS.
Feathers works with Node.js, Deno, Bun, Cloudflare Workers and standalone in the browser and can interact with any backend technology, supports many databases out of the box and works with any frontend like React, VueJS, Angular, React Native, Android or iOS.

# Getting started

Expand Down Expand Up @@ -48,6 +48,6 @@ npm test

# License

Copyright (c) 2024 [Feathers contributors](https://github.com/feathersjs/feathers/graphs/contributors)
Copyright (c) 2025 [Feathers contributors](https://github.com/feathersjs/feathers/graphs/contributors)

Licensed under the [MIT license](LICENSE).
138 changes: 137 additions & 1 deletion docs/api/client/rest.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The following chapter describes the use of
npm install @feathersjs/rest-client --save
```

`@feathersjs/rest-client` allows to connect to a service exposed through a REST HTTP transport (e.g. with [Koa](../koa.md#rest) or [Express](../express.md#rest)) using [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), [Superagent](https://github.com/ladjs/superagent) or [Axios](https://github.com/mzabriskie/axios).
`@feathersjs/rest-client` allows to connect to a service exposed through a REST HTTP transport (e.g. with [Koa](../koa.md#rest) or [Express](../express.md#rest)) using [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), [Superagent](https://github.com/ladjs/superagent) or [Axios](https://github.com/mzabriskie/axios).

<BlockQuote type="info">

Expand Down Expand Up @@ -175,6 +175,142 @@ app.configure(
)
```

### FormData and File Uploads

The REST client automatically detects when you pass a `FormData` object and handles it appropriately - skipping JSON serialization and letting the browser set the correct `Content-Type` header with the multipart boundary.

```ts
// Create a FormData object
const formData = new FormData()
formData.append('file', fileInput.files[0])
formData.append('description', 'My uploaded file')

// Upload using the service - FormData is auto-detected
const result = await app.service('uploads').create(formData)
```

On the server, the data is parsed and converted to a plain object:

```ts
// Server receives:
{
file: File,
description: 'My uploaded file'
}
```

Multiple values for the same field name become an array:

```ts
// Client
const formData = new FormData()
formData.append('files', file1)
formData.append('files', file2)
formData.append('files', file3)

// Server receives:
{
files: [File, File, File] // All files in one array
}
```

<BlockQuote type="warning" label="REST only">

FormData and file uploads are only supported with the REST/HTTP transport. Socket.io does not support FormData - attempting to send FormData over websockets will result in an error.

</BlockQuote>

<BlockQuote type="info" label="note">

File uploads use the native `Request.formData()` API which buffers the entire request into memory. For large file uploads (videos, large datasets), consider using presigned URLs to upload directly to cloud storage (S3, R2, etc.).

</BlockQuote>

### Streaming Uploads

The REST client supports streaming data to services using `ReadableStream`. This is useful for large file uploads, real-time data ingestion, or piping data directly to storage without buffering.

```ts
// Stream a file to a service
const file = fileInput.files[0]
const stream = file.stream()

const result = await app.service('uploads').create(stream, {
headers: {
'Content-Type': file.type,
'X-Filename': file.name
}
})
```

On the server, the service receives the `ReadableStream` directly:

```ts
class UploadService {
async create(stream: ReadableStream, params: Params) {
const filename = params.headers['x-filename']
const contentType = params.headers['content-type']

// Pipe directly to storage - no buffering
await storage.upload(filename, stream, { contentType })

return { filename, uploaded: true }
}
}
```

The stream can be piped directly to cloud storage (S3, R2, etc.) without loading the entire file into memory:

```ts
async create(stream: ReadableStream, params: Params) {
// Stream directly to R2/S3
await env.MY_BUCKET.put(params.headers['x-filename'], stream)
return { success: true }
}
```

For more complex metadata, you can stringify an object into a header:

```ts
// Client
const file = fileInput.files[0]

await app.service('csv-import').create(file.stream(), {
headers: {
'Content-Type': 'text/csv',
'X-Import-Options': JSON.stringify({
filename: file.name,
tableName: 'products',
skipHeader: true
})
}
})

// Server
async create(stream: ReadableStream, params: Params) {
const options = JSON.parse(params.headers['x-import-options'])
// options.filename, options.tableName, options.skipHeader
}
```

<BlockQuote type="warning" label="Header size limits">

HTTP headers are typically limited to 8KB total. Keep metadata small - use headers for filenames, options, and IDs, not large data payloads.

</BlockQuote>

<BlockQuote type="info" label="Content-Type">

If no `Content-Type` header is specified, streaming requests default to `application/octet-stream`. Any content type not recognized as JSON, form-urlencoded, or multipart will be streamed through to the service.

</BlockQuote>

<BlockQuote type="warning" label="REST only">

Streaming uploads are only supported with the REST/HTTP transport. Socket.io does not support streaming request bodies.

</BlockQuote>

### Custom Methods

On the client, [custom service methods](../services.md#custom-methods) registered using the `methods` option when registering the service via `restClient.service()`:
Expand Down
Loading