Skip to content

Commit

Permalink
Merge pull request #3 from alexanderkasten/feature/add_credentials
Browse files Browse the repository at this point in the history
Refactor SSEManager to support passing EventSourceInit options to get…
  • Loading branch information
alexanderkasten authored Dec 28, 2024
2 parents 4d39c80 + 8abde59 commit 53a0b84
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 25 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Create a new file `app/api/sse/route.ts` with the following content:

```typescript
import { createSSEHandler } from 'use-next-sse';

export const dynamic = 'force-dynamic';
export const GET = createSSEHandler(async (send, close) => {
let count = 0;
Expand Down
7 changes: 6 additions & 1 deletion __tests__/use-sse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ describe('useSSE', () => {

test('initializes EventSource with the provided URL', () => {
renderHook(() => useSSE({ url: 'https://example.com/sse' }));
expect(EventSource).toHaveBeenCalledWith('https://example.com/sse');
expect(EventSource).toHaveBeenCalledWith('https://example.com/sse', { withCredentials: false });
});

test('initializes EventSource with the provided URL and credentials', () => {
renderHook(() => useSSE({ url: 'https://example.com/sse', withCredentials: true }));
expect(EventSource).toHaveBeenCalledWith('https://example.com/sse', { withCredentials: true });
});

test('listens for specific event when eventName is provided', () => {
Expand Down
1 change: 0 additions & 1 deletion example/src/app/components/EvenOdd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useSSE } from 'use-next-sse';
import { useState } from 'react';

export default function SSEExample() {

const { data: allData, error: allError } = useSSE({ url: '/api/even-odd' });
const { data: evenData, error: evenError } = useSSE({ url: '/api/even-odd', eventName: 'even' });
const { data: oddData, error: oddError } = useSSE({ url: '/api/even-odd', eventName: 'odd' });
Expand Down
22 changes: 4 additions & 18 deletions example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
Expand All @@ -23,20 +19,10 @@
}
],
"paths": {
"@/*": [
"./src/*"
]
"@/*": ["./src/*"]
},
"forceConsistentCasingInFileNames": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"next.config.js"
],
"exclude": [
"node_modules"
]
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.js"],
"exclude": ["node_modules"]
}
4 changes: 2 additions & 2 deletions src/client/sse-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ class SSEManager {
private connections: Map<string, { source: EventSource; refCount: number; listeners: Map<string, Set<Listener>> }> =
new Map();

getConnection(url: string): EventSource {
getConnection(url: string, init?: EventSourceInit): EventSource {
let connection = this.connections.get(url);
if (!connection) {
const source = new EventSource(url);
const source = new EventSource(url, init);
connection = { source, refCount: 0, listeners: new Map() };
this.connections.set(url, connection);
}
Expand Down
15 changes: 12 additions & 3 deletions src/client/use-sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export type SSEOptions = {
* const { data, error, lastEventId, close } = useSSE({ url: 'https://example.com/sse', eventName: 'test', reconnect: true });
*/
reconnect?: boolean | { interval?: number; maxAttempts?: number };
/**
* Whether to include credentials in the request. Default `false`.
*/
withCredentials?: boolean;
};

interface SSEResult<T> {
Expand Down Expand Up @@ -83,6 +87,7 @@ interface SSEResult<T> {
* @param {boolean | { interval?: number, maxAttempts?: number }} [options.reconnect] - Whether to automatically reconnect if the connection is lost. If an object, the interval and maxAttempts can be specified. Default `false`.
* @param {number} [options.reconnect.interval] - The interval in milliseconds to wait before reconnecting. Default `1000`ms.
* @param {number} [options.reconnect.maxAttempts] - The maximum number of reconnection attempts. Default `5`.
* @param {boolean} [options.withCredentials=false] - Whether to include credentials in the request. Default `false`.
* @returns {SSEResult<T>} The result of the SSE connection, including data, error, last event ID, and a close function. {@link SSEResult}
*
* @example
Expand All @@ -94,7 +99,12 @@ interface SSEResult<T> {
* }
* }, [data]);
*/
export function useSSE<T = any>({ url, eventName = 'message', reconnect = false }: SSEOptions): SSEResult<T> {
export function useSSE<T = any>({
url,
eventName = 'message',
reconnect = false,
withCredentials = false,
}: SSEOptions): SSEResult<T> {
const [data, setData] = useState<T | null>(null);
const [error, setError] = useState<Error | null>(null);
const [lastEventId, setLastEventId] = useState<string | null>(null);
Expand All @@ -114,8 +124,7 @@ export function useSSE<T = any>({ url, eventName = 'message', reconnect = false
useEffect(() => {
const connect = () => {
setConnectionState('connecting');
const source = sseManager.getConnection(url);

const source = sseManager.getConnection(url, { withCredentials });
const handleOpen = () => {
setConnectionState('open');
reconnectAttempts.current = 0;
Expand Down

0 comments on commit 53a0b84

Please sign in to comment.