Repository navigation
refactor!: next major version (6.x) #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
0babb8f
refactor: move WebSocket and SSE support to plugins, update error han…
dragon-fish a0f172e
refactor: update plugin installation methods to use 'fx' instead of '…
dragon-fish 40bf53d
chore: add CHANGELOG.md
dragon-fish e38e844
docs: update CHANGELOG and README, add plugin docs
dragon-fish b1f4280
chore: housekeeping
dragon-fish e0926d8
fix: ensure ctx.rawResponse remains unread and matches ctx.response.r…
dragon-fish cd1b9d0
chore: bump version to 5.3.1
dragon-fish eeae00a
Merge branch 'master' into dragon-fish/major-6
dragon-fish 3adea76
fix: enhance cookie-jar uninstall process
dragon-fish f7279a6
fix: improve SSE connection handling with enhanced error and close ev…
dragon-fish 092402e
docs: update CHANGELOG with plugin lifecycle changes and context enha…
dragon-fish f1eb093
fix: update FexiosInterceptor to use FexiosHookHandler for improved t…
dragon-fish eb47340
fix: improve SSE connection error handling and timeout management
dragon-fish d8bbb0a
refactor!: restructure FexiosContext for improved lifecycle managemen…
dragon-fish a269b81
fix: ensure proper handling of afterRawResponse event in Fexios lifec…
dragon-fish File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # Changelog | ||
|
|
||
| ## 6.0.0 | ||
|
|
||
| ### Breaking Changes | ||
|
|
||
| - **WebSocket (WS) and Server-Sent Events (SSE) moved out of core** | ||
|
|
||
| - Core no longer supports WS/SSE detection/handling. | ||
| - The following legacy behaviors are removed and will now throw a dedicated error: | ||
| - `responseType: 'ws'` or `responseType: 'stream'` | ||
| - Request URLs starting with `ws://` or `wss://` | ||
|
dragon-fish marked this conversation as resolved.
Resolved
|
||
| - Responses with `upgrade: websocket` or `content-type: text/event-stream` | ||
| - When triggered, core throws `FexiosError` with `code: 'FEATURE_MOVED_TO_PLUGIN'` and a message guiding users to install plugins. | ||
|
|
||
| - **`responseType` no longer includes WS/SSE values** | ||
|
|
||
| - `FexiosConfigs['responseType']` now only supports: | ||
| - `'json' | 'text' | 'form' | 'blob' | 'arrayBuffer'` | ||
|
|
||
| - `FexiosPlugin` now should be an object, with a required `name` and `install(fx)` function. | ||
|
|
||
| - `name`: a string that uniquely identifies the plugin. | ||
| - `install(fx)`: a function that installs the plugin. | ||
| - `uninstall(fx)` (optional): a function that will be called when the plugin is uninstalled. You can clean up side effects here. | ||
|
|
||
| - **`FexiosContext` is restructured into `ctx.request`, `ctx.runtime`, and `ctx.response`** | ||
| - Lifecycle hook context is now a structured object: | ||
| - `ctx.request`: request configs and mutable request state (url/query/headers/body/...) | ||
| - `ctx.runtime`: runtime-only state (abortController/onProgress/customEnv/...) | ||
| - `ctx.response`: parsed `FexiosResponse` (available in `afterResponse` and final context) | ||
| - For normal user experience, final context still keeps shortcut getters: | ||
| - `ctx.data`, `ctx.headers`, `ctx.url`, `ctx.responseType`, `ctx.rawResponse`, `ctx.rawRequest` | ||
|
|
||
| ### Migration | ||
|
|
||
| - **Use plugins instead of core WS/SSE** | ||
|
|
||
| - Install plugins from `fexios/plugins`: | ||
| - `pluginWebSocket` for WebSocket | ||
| - `pluginSSE` for Server-Sent Events | ||
| - New APIs: | ||
| - `fx.ws(url, options?) -> Promise<WebSocket>` | ||
| - `fx.sse(url, options?) -> Promise<EventSource>` | ||
|
|
||
| - **New hook namespaces for real-time features** | ||
|
|
||
| - WebSocket hooks: | ||
| - `websocket:beforeConnect`, `websocket:open`, `websocket:message`, `websocket:error`, `websocket:close` | ||
| - SSE hooks: | ||
| - `sse:beforeConnect`, `sse:open`, `sse:message`, `sse:error`, `sse:close` | ||
|
|
||
| - **Migrate lifecycle hooks to new context structure** | ||
| - Replace request mutations: | ||
| - `ctx.url` -> `ctx.request.url` | ||
| - `ctx.query` -> `ctx.request.query` | ||
| - `ctx.headers` -> `ctx.request.headers` | ||
| - Replace runtime env: | ||
| - `ctx.customEnv` -> `ctx.runtime.customEnv` | ||
| - Parsed response wrapper remains `ctx.response` (type: `FexiosResponse`) | ||
|
|
||
| ### Added | ||
|
|
||
| - **Plugin lifecycle support** | ||
|
|
||
| - `FexiosPlugin` now supports optional `uninstall(fx)` for cleanup. | ||
| - `fx.plugin(plugin)` now returns an uninstall function (see breaking change above). | ||
| - `fx.uninstall(pluginOrName)` is available to remove a plugin at runtime. | ||
|
|
||
| - **`ctx.app` in lifecycle hooks** | ||
| - Core injects `ctx.app` (current `Fexios` instance) before any lifecycle hooks run, so plugins/users can access app-level info from the context. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| # Plugins | ||
|
|
||
| This directory contains documentation for **official Fexios plugins**. | ||
|
|
||
| ## Import path | ||
|
|
||
| All official plugins are exported from: | ||
|
|
||
| ```ts | ||
| import { pluginXXX } from 'fexios/plugins' | ||
| // ↑↑↑↑↑↑↑↑↑ Replace with the real plugin you want to use | ||
| ``` | ||
|
|
||
| ## Official plugins | ||
|
|
||
| - **Cookie Jar**: [`docs/plugins/cookie-jar.md`](cookie-jar.md) | ||
| - **SSE (EventSource)**: [`docs/plugins/sse.md`](sse.md) | ||
| - **WebSocket**: [`docs/plugins/websocket.md`](websocket.md) | ||
|
|
||
| ## Creating a plugin (tutorial) | ||
|
|
||
| Fexios plugins are **objects** with a required `name` and `install(fx)` function. | ||
|
|
||
| ### 1) Minimal plugin template | ||
|
|
||
| ```ts | ||
| import { Fexios, type FexiosPlugin } from 'fexios' | ||
|
|
||
| export const authPlugin: FexiosPlugin = { | ||
| name: 'auth-plugin', | ||
| install(fx) { | ||
| fx.on('beforeRequest', (ctx) => { | ||
| ctx.headers = { ...ctx.headers, Authorization: 'Bearer token' } | ||
| return ctx | ||
| }) | ||
| }, | ||
| } | ||
|
|
||
| const fx = new Fexios() | ||
| await fx.plugin(authPlugin) | ||
| ``` | ||
|
|
||
| ### 2) Uninstalling a plugin | ||
|
|
||
| If your plugin defines `uninstall(fx)`, Fexios will call it when you uninstall: | ||
|
|
||
| ```ts | ||
| export const demoPlugin: FexiosPlugin = { | ||
| name: 'demo-plugin', | ||
| install() { | ||
| // setup... | ||
| }, | ||
| uninstall() { | ||
| // cleanup... | ||
| }, | ||
| } | ||
|
|
||
| const fx = new Fexios() | ||
| await fx.plugin(demoPlugin) | ||
|
|
||
| // uninstall by name or by reference | ||
| fx.uninstall('demo-plugin') | ||
| // fx.uninstall(demoPlugin) | ||
| ``` | ||
|
|
||
| ### 3) Adding instance methods (TypeScript module augmentation) | ||
|
|
||
| Plugins can attach new methods/fields onto the `Fexios` instance. To make it type-safe, | ||
| add module augmentation in your plugin module: | ||
|
|
||
| ```ts | ||
| import type { FexiosPlugin } from 'fexios' | ||
|
|
||
| declare module 'fexios' { | ||
| interface Fexios { | ||
| hello: (name: string) => string | ||
| } | ||
| } | ||
|
|
||
| export const helloPlugin: FexiosPlugin = { | ||
| name: 'hello-plugin', | ||
| install(fx) { | ||
| fx.hello = (name) => `Hello, ${name}` | ||
| }, | ||
| uninstall(fx) { | ||
| fx.hello = undefined as any | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| ### 4) Hooks & lifecycle events | ||
|
|
||
| Inside `install(fx)`, you can use: | ||
|
|
||
| - `fx.on('<lifecycleEvent>', handler)` to intercept request/response lifecycle. | ||
| - `fx.interceptors.request.use(...)` / `fx.interceptors.response.use(...)` as axios-like sugar. | ||
|
|
||
| Official plugins (SSE/WebSocket) also emit custom lifecycle events such as | ||
| `sse:beforeConnect` / `websocket:beforeConnect`. | ||
|
|
||
| ## Runtime notes (browser vs Node.js) | ||
|
|
||
| - In browsers, `EventSource` and `WebSocket` are usually available globally. | ||
| - In Node.js, you may need to provide polyfills (set them on `globalThis`) before using `pluginSSE` / `pluginWebSocket`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Cookie Jar Plugin | ||
|
|
||
| > [!IMPORTANT] | ||
| > | ||
| > This plugin is only available in **Node.js** environment. | ||
|
|
||
| The Cookie Jar plugin adds **automatic cookie persistence** for Fexios requests: | ||
|
|
||
| - It appends a `Cookie` header for outgoing requests (based on request URL). | ||
| - It parses `Set-Cookie` from responses and stores cookies in-memory. | ||
| - It exposes an instance at `fx.cookieJar` for manual access. | ||
|
|
||
| ## Import | ||
|
|
||
| ```ts | ||
| import { Fexios } from 'fexios' | ||
| import { pluginCookieJar } from 'fexios/plugins' | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```ts | ||
| const fx = new Fexios({ baseURL: 'https://example.com' }).plugin( | ||
| pluginCookieJar | ||
| ) | ||
|
|
||
| // The plugin exposes the jar: | ||
| fx.cookieJar?.setCookie({ | ||
| name: 'foo', | ||
| value: 'bar', | ||
| domain: 'example.com', | ||
| path: '/', | ||
| }) | ||
|
|
||
| // Requests will automatically include matching cookies | ||
| await fx.get('/profile') | ||
| ``` | ||
|
|
||
| ## API | ||
|
|
||
| The plugin exposes a `CookieJar` instance at `fx.cookieJar`. | ||
|
|
||
| Common methods: | ||
|
|
||
| - `cookieJar.setCookie(cookie, domain?, path?)` | ||
| - `cookieJar.getCookie(name, domain?, path?)` | ||
| - `cookieJar.getCookies(domain?, path?)` | ||
| - `cookieJar.getCookieHeader(domain?, path?)` | ||
| - `cookieJar.clear()` | ||
| - `cookieJar.cleanExpiredCookies()` | ||
|
|
||
| ## Notes | ||
|
|
||
| - **In-memory only**: cookies are stored in memory; persistence is up to your app. | ||
| - **Multiple Set-Cookie headers**: | ||
| - If the runtime supports `headers.getSetCookie()` (e.g. undici), the plugin will read all values. | ||
| - Otherwise it falls back to `headers.get('set-cookie')`, which may not preserve multiple cookies in some environments. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # SSE (EventSource) Plugin | ||
|
|
||
| This plugin adds `fx.sse(...)` to create an **SSE (Server-Sent Events)** connection using `EventSource`. | ||
|
|
||
| ## Import | ||
|
|
||
| ```ts | ||
| import { Fexios } from 'fexios' | ||
| import { pluginSSE } from 'fexios/plugins' | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```ts | ||
| const fx = new Fexios({ baseURL: 'https://example.com' }).plugin(pluginSSE) | ||
|
|
||
| const es = await fx.sse('/events', { | ||
| query: { room: 'lobby' }, | ||
| timeout: 30_000, | ||
| }) | ||
|
|
||
| es.addEventListener('message', (event) => { | ||
| console.log('message:', event.data) | ||
| }) | ||
| ``` | ||
|
|
||
| ## API | ||
|
|
||
| ### `fx.sse(url, options?)` | ||
|
|
||
| - **Returns**: `Promise<EventSource>` (resolves after the connection is opened) | ||
| - **options.query**: query params to merge into the URL | ||
| - **options.timeout**: connect timeout in ms (default: `fx.baseConfigs.timeout ?? 60000`) | ||
|
|
||
| ## Lifecycle events | ||
|
|
||
| The plugin emits the following Fexios lifecycle events: | ||
|
|
||
| - `sse:beforeConnect` — allow you to modify `{ url, timeout }` before connecting | ||
| - `sse:open` | ||
| - `sse:message` | ||
| - `sse:error` | ||
|
|
||
| ## Runtime notes (Node.js) | ||
|
|
||
| In Node.js, `EventSource` is not always available globally. You can provide a polyfill: | ||
|
|
||
| ```ts | ||
| import EventSource from 'eventsource' | ||
| ;(globalThis as any).EventSource = EventSource | ||
| ``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.