use-sse-vue 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.cjs +89 -0
- package/dist/index.umd.cjs.map +1 -0
- package/dist/useSse.d.ts +51 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Roman3205 <https://github.com/roman3205>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# use-sse-vue
|
|
2
|
+
|
|
3
|
+
A lightweight, robust Vue and Nuxt composable for managing Server-Sent Events (SSE) connections with auto-reconnect, JSON parsing, and SSR safety. Compatible with both Vue 2 and Vue 3.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install use-sse-vue
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
_Note: Ensure `vue` is installed in your project._
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```vue
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import { useSse } from 'use-sse-vue'
|
|
18
|
+
|
|
19
|
+
const { data, status, error, connect, disconnect } = useSse('http://localhost:3000/events', {
|
|
20
|
+
autoConnect: true,
|
|
21
|
+
reconnectDelay: 2000,
|
|
22
|
+
maxReconnectAttempts: 5
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<div>
|
|
28
|
+
<p>Status: {{ status }}</p>
|
|
29
|
+
<div v-if="data">Received: {{ data }}</div>
|
|
30
|
+
<button @click="connect" :disabled="status !== 'closed'">Connect</button>
|
|
31
|
+
<button @click="disconnect" :disabled="status === 'closed'">Disconnect</button>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Reference
|
|
37
|
+
|
|
38
|
+
### `useSse(url, options)`
|
|
39
|
+
|
|
40
|
+
#### Parameters
|
|
41
|
+
|
|
42
|
+
- **`url`**: `string | (() => string) | Ref<string>` - The SSE endpoint URL. Can be a static string, a getter function, or a Vue Ref.
|
|
43
|
+
- **`options`**: `UseSseOptions` (optional)
|
|
44
|
+
- `autoConnect` (`boolean`, default: `true`): Automatically initiate connection on component mount.
|
|
45
|
+
- `reconnectDelay` (`number`, default: `3000`): Time to wait (in ms) before attempting a reconnect.
|
|
46
|
+
- `maxReconnectAttempts` (`number`, default: `5`): Maximum consecutive reconnect attempts.
|
|
47
|
+
- `onMessage` (`(data: any, event: MessageEvent) => void`): Callback when a message is received.
|
|
48
|
+
- `onOpen` (`(event: Event) => void`): Callback when connection opens.
|
|
49
|
+
- `onError` (`(event: Event) => void`): Callback when connection errors occur.
|
|
50
|
+
|
|
51
|
+
#### Return Value
|
|
52
|
+
|
|
53
|
+
Returns an object containing:
|
|
54
|
+
|
|
55
|
+
- **`data`**: `Ref<any | null>` - The parsed event data.
|
|
56
|
+
- **`status`**: `Ref<'connecting' | 'open' | 'closed'>` - Reactive connection state.
|
|
57
|
+
- **`error`**: `Ref<Event | null>` - The latest error event.
|
|
58
|
+
- **`connect`**: `() => void` - Connect manually.
|
|
59
|
+
- **`disconnect`**: `() => void` - Disconnect manually.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSse, type UseSseOptions } from './useSse';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { onUnmounted, ref, watch } from "vue-demi";
|
|
2
|
+
//#region src/useSse.ts
|
|
3
|
+
function useSse(url, options = {}) {
|
|
4
|
+
const { autoConnect = true, reconnectDelay = 3e3, maxReconnectAttempts = 5, onMessage, onError, onOpen } = options;
|
|
5
|
+
const data = ref(null);
|
|
6
|
+
const status = ref("closed");
|
|
7
|
+
const error = ref(null);
|
|
8
|
+
let eventSource = null;
|
|
9
|
+
let reconnectCount = 0;
|
|
10
|
+
let reconnectTimer = null;
|
|
11
|
+
const isSSR = typeof window === "undefined";
|
|
12
|
+
const connect = () => {
|
|
13
|
+
if (isSSR || eventSource) return;
|
|
14
|
+
const targetUrl = typeof url === "function" ? url() : typeof url === "object" && "value" in url ? url.value : url;
|
|
15
|
+
status.value = "connecting";
|
|
16
|
+
error.value = null;
|
|
17
|
+
try {
|
|
18
|
+
eventSource = new EventSource(targetUrl);
|
|
19
|
+
eventSource.onopen = (event) => {
|
|
20
|
+
status.value = "open";
|
|
21
|
+
reconnectCount = 0;
|
|
22
|
+
onOpen?.(event);
|
|
23
|
+
};
|
|
24
|
+
eventSource.onmessage = (event) => {
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(event.data);
|
|
27
|
+
data.value = parsed;
|
|
28
|
+
onMessage?.(parsed, event);
|
|
29
|
+
} catch {
|
|
30
|
+
data.value = event.data;
|
|
31
|
+
onMessage?.(event.data, event);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
eventSource.onerror = (event) => {
|
|
35
|
+
error.value = event;
|
|
36
|
+
onError?.(event);
|
|
37
|
+
tryReconnect();
|
|
38
|
+
};
|
|
39
|
+
} catch (err) {
|
|
40
|
+
status.value = "closed";
|
|
41
|
+
error.value = err;
|
|
42
|
+
tryReconnect();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const disconnect = () => {
|
|
46
|
+
if (reconnectTimer) {
|
|
47
|
+
clearTimeout(reconnectTimer);
|
|
48
|
+
reconnectTimer = null;
|
|
49
|
+
}
|
|
50
|
+
if (eventSource) {
|
|
51
|
+
eventSource.close();
|
|
52
|
+
eventSource = null;
|
|
53
|
+
}
|
|
54
|
+
status.value = "closed";
|
|
55
|
+
};
|
|
56
|
+
const tryReconnect = () => {
|
|
57
|
+
disconnect();
|
|
58
|
+
if (reconnectCount < maxReconnectAttempts) {
|
|
59
|
+
status.value = "connecting";
|
|
60
|
+
reconnectCount++;
|
|
61
|
+
reconnectTimer = setTimeout(connect, reconnectDelay);
|
|
62
|
+
} else status.value = "closed";
|
|
63
|
+
};
|
|
64
|
+
if (typeof url === "function" || typeof url === "object" && "value" in url) watch(url, () => {
|
|
65
|
+
if (status.value !== "closed") {
|
|
66
|
+
disconnect();
|
|
67
|
+
connect();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (autoConnect) connect();
|
|
71
|
+
onUnmounted(() => {
|
|
72
|
+
disconnect();
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
data,
|
|
76
|
+
status,
|
|
77
|
+
error,
|
|
78
|
+
connect,
|
|
79
|
+
disconnect
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { useSse };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/useSse.ts"],"sourcesContent":["import { ref, onUnmounted, watch, type Ref } from 'vue-demi'\n\nexport interface UseSseOptions<T = any> {\n autoConnect?: boolean\n reconnectDelay?: number\n maxReconnectAttempts?: number\n onMessage?: (data: T, event: MessageEvent) => void\n onError?: (event: Event) => void\n onOpen?: (event: Event) => void\n}\n\nexport function useSse<T = any>(\n url: string | (() => string) | Ref<string>,\n options: UseSseOptions<T> = {}\n) {\n const {\n autoConnect = true,\n reconnectDelay = 3000,\n maxReconnectAttempts = 5,\n onMessage,\n onError,\n onOpen\n } = options\n\n const data = ref<T | null>(null) as Ref<T | null>\n const status = ref<'connecting' | 'open' | 'closed'>('closed')\n const error = ref<Event | null>(null)\n\n let eventSource: EventSource | null = null\n let reconnectCount = 0\n let reconnectTimer: any = null\n\n // Environment check\n const isSSR = typeof window === 'undefined'\n\n const connect = () => {\n if (isSSR || eventSource) return\n\n // Extract target URL from string, ref, or getter function\n const targetUrl =\n typeof url === 'function'\n ? url()\n : typeof url === 'object' && 'value' in url\n ? url.value\n : url\n\n status.value = 'connecting'\n error.value = null\n\n try {\n eventSource = new EventSource(targetUrl)\n\n eventSource.onopen = (event) => {\n status.value = 'open'\n reconnectCount = 0\n onOpen?.(event)\n }\n\n eventSource.onmessage = (event: MessageEvent) => {\n // Attempt to parse JSON, fallback to raw string if it fails\n try {\n const parsed = JSON.parse(event.data)\n data.value = parsed\n onMessage?.(parsed, event)\n } catch {\n data.value = event.data as any\n onMessage?.(event.data, event)\n }\n }\n\n eventSource.onerror = (event) => {\n error.value = event\n onError?.(event)\n\n // Trigger reconnection\n tryReconnect()\n }\n } catch (err) {\n status.value = 'closed'\n error.value = err as any\n tryReconnect()\n }\n }\n\n const disconnect = () => {\n if (reconnectTimer) {\n clearTimeout(reconnectTimer)\n reconnectTimer = null\n }\n if (eventSource) {\n eventSource.close()\n eventSource = null\n }\n status.value = 'closed'\n }\n\n const tryReconnect = () => {\n disconnect()\n\n if (reconnectCount < maxReconnectAttempts) {\n status.value = 'connecting'\n reconnectCount++\n reconnectTimer = setTimeout(connect, reconnectDelay)\n } else {\n status.value = 'closed'\n }\n }\n\n // Monitor URL change if it is reactive\n if (typeof url === 'function' || (typeof url === 'object' && 'value' in url)) {\n watch(url, () => {\n if (status.value !== 'closed') {\n disconnect()\n connect()\n }\n })\n }\n\n if (autoConnect) {\n connect()\n }\n\n onUnmounted(() => {\n disconnect()\n })\n\n return {\n data,\n status,\n error,\n connect,\n disconnect\n }\n}\n"],"mappings":";;AAWA,SAAgB,OACd,KACA,UAA4B,CAAC,GAC7B;CACA,MAAM,EACJ,cAAc,MACd,iBAAiB,KACjB,uBAAuB,GACvB,WACA,SACA,WACE;CAEJ,MAAM,OAAO,IAAc,IAAI;CAC/B,MAAM,SAAS,IAAsC,QAAQ;CAC7D,MAAM,QAAQ,IAAkB,IAAI;CAEpC,IAAI,cAAkC;CACtC,IAAI,iBAAiB;CACrB,IAAI,iBAAsB;CAG1B,MAAM,QAAQ,OAAO,WAAW;CAEhC,MAAM,gBAAgB;EACpB,IAAI,SAAS,aAAa;EAG1B,MAAM,YACJ,OAAO,QAAQ,aACX,IAAI,IACJ,OAAO,QAAQ,YAAY,WAAW,MACpC,IAAI,QACJ;EAER,OAAO,QAAQ;EACf,MAAM,QAAQ;EAEd,IAAI;GACF,cAAc,IAAI,YAAY,SAAS;GAEvC,YAAY,UAAU,UAAU;IAC9B,OAAO,QAAQ;IACf,iBAAiB;IACjB,SAAS,KAAK;GAChB;GAEA,YAAY,aAAa,UAAwB;IAE/C,IAAI;KACF,MAAM,SAAS,KAAK,MAAM,MAAM,IAAI;KACpC,KAAK,QAAQ;KACb,YAAY,QAAQ,KAAK;IAC3B,QAAQ;KACN,KAAK,QAAQ,MAAM;KACnB,YAAY,MAAM,MAAM,KAAK;IAC/B;GACF;GAEA,YAAY,WAAW,UAAU;IAC/B,MAAM,QAAQ;IACd,UAAU,KAAK;IAGf,aAAa;GACf;EACF,SAAS,KAAK;GACZ,OAAO,QAAQ;GACf,MAAM,QAAQ;GACd,aAAa;EACf;CACF;CAEA,MAAM,mBAAmB;EACvB,IAAI,gBAAgB;GAClB,aAAa,cAAc;GAC3B,iBAAiB;EACnB;EACA,IAAI,aAAa;GACf,YAAY,MAAM;GAClB,cAAc;EAChB;EACA,OAAO,QAAQ;CACjB;CAEA,MAAM,qBAAqB;EACzB,WAAW;EAEX,IAAI,iBAAiB,sBAAsB;GACzC,OAAO,QAAQ;GACf;GACA,iBAAiB,WAAW,SAAS,cAAc;EACrD,OACE,OAAO,QAAQ;CAEnB;CAGA,IAAI,OAAO,QAAQ,cAAe,OAAO,QAAQ,YAAY,WAAW,KACtE,MAAM,WAAW;EACf,IAAI,OAAO,UAAU,UAAU;GAC7B,WAAW;GACX,QAAQ;EACV;CACF,CAAC;CAGH,IAAI,aACF,QAAQ;CAGV,kBAAkB;EAChB,WAAW;CACb,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vue-demi")) : typeof define === "function" && define.amd ? define(["exports", "vue-demi"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["use-sse-vue"] = {}, global.VueDemi));
|
|
3
|
+
})(this, function(exports, vue_demi) {
|
|
4
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
5
|
+
//#region src/useSse.ts
|
|
6
|
+
function useSse(url, options = {}) {
|
|
7
|
+
const { autoConnect = true, reconnectDelay = 3e3, maxReconnectAttempts = 5, onMessage, onError, onOpen } = options;
|
|
8
|
+
const data = (0, vue_demi.ref)(null);
|
|
9
|
+
const status = (0, vue_demi.ref)("closed");
|
|
10
|
+
const error = (0, vue_demi.ref)(null);
|
|
11
|
+
let eventSource = null;
|
|
12
|
+
let reconnectCount = 0;
|
|
13
|
+
let reconnectTimer = null;
|
|
14
|
+
const isSSR = typeof window === "undefined";
|
|
15
|
+
const connect = () => {
|
|
16
|
+
if (isSSR || eventSource) return;
|
|
17
|
+
const targetUrl = typeof url === "function" ? url() : typeof url === "object" && "value" in url ? url.value : url;
|
|
18
|
+
status.value = "connecting";
|
|
19
|
+
error.value = null;
|
|
20
|
+
try {
|
|
21
|
+
eventSource = new EventSource(targetUrl);
|
|
22
|
+
eventSource.onopen = (event) => {
|
|
23
|
+
status.value = "open";
|
|
24
|
+
reconnectCount = 0;
|
|
25
|
+
onOpen?.(event);
|
|
26
|
+
};
|
|
27
|
+
eventSource.onmessage = (event) => {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(event.data);
|
|
30
|
+
data.value = parsed;
|
|
31
|
+
onMessage?.(parsed, event);
|
|
32
|
+
} catch {
|
|
33
|
+
data.value = event.data;
|
|
34
|
+
onMessage?.(event.data, event);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
eventSource.onerror = (event) => {
|
|
38
|
+
error.value = event;
|
|
39
|
+
onError?.(event);
|
|
40
|
+
tryReconnect();
|
|
41
|
+
};
|
|
42
|
+
} catch (err) {
|
|
43
|
+
status.value = "closed";
|
|
44
|
+
error.value = err;
|
|
45
|
+
tryReconnect();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const disconnect = () => {
|
|
49
|
+
if (reconnectTimer) {
|
|
50
|
+
clearTimeout(reconnectTimer);
|
|
51
|
+
reconnectTimer = null;
|
|
52
|
+
}
|
|
53
|
+
if (eventSource) {
|
|
54
|
+
eventSource.close();
|
|
55
|
+
eventSource = null;
|
|
56
|
+
}
|
|
57
|
+
status.value = "closed";
|
|
58
|
+
};
|
|
59
|
+
const tryReconnect = () => {
|
|
60
|
+
disconnect();
|
|
61
|
+
if (reconnectCount < maxReconnectAttempts) {
|
|
62
|
+
status.value = "connecting";
|
|
63
|
+
reconnectCount++;
|
|
64
|
+
reconnectTimer = setTimeout(connect, reconnectDelay);
|
|
65
|
+
} else status.value = "closed";
|
|
66
|
+
};
|
|
67
|
+
if (typeof url === "function" || typeof url === "object" && "value" in url) (0, vue_demi.watch)(url, () => {
|
|
68
|
+
if (status.value !== "closed") {
|
|
69
|
+
disconnect();
|
|
70
|
+
connect();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
if (autoConnect) connect();
|
|
74
|
+
(0, vue_demi.onUnmounted)(() => {
|
|
75
|
+
disconnect();
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
data,
|
|
79
|
+
status,
|
|
80
|
+
error,
|
|
81
|
+
connect,
|
|
82
|
+
disconnect
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
exports.useSse = useSse;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=index.umd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.cjs","names":[],"sources":["../src/useSse.ts"],"sourcesContent":["import { ref, onUnmounted, watch, type Ref } from 'vue-demi'\n\nexport interface UseSseOptions<T = any> {\n autoConnect?: boolean\n reconnectDelay?: number\n maxReconnectAttempts?: number\n onMessage?: (data: T, event: MessageEvent) => void\n onError?: (event: Event) => void\n onOpen?: (event: Event) => void\n}\n\nexport function useSse<T = any>(\n url: string | (() => string) | Ref<string>,\n options: UseSseOptions<T> = {}\n) {\n const {\n autoConnect = true,\n reconnectDelay = 3000,\n maxReconnectAttempts = 5,\n onMessage,\n onError,\n onOpen\n } = options\n\n const data = ref<T | null>(null) as Ref<T | null>\n const status = ref<'connecting' | 'open' | 'closed'>('closed')\n const error = ref<Event | null>(null)\n\n let eventSource: EventSource | null = null\n let reconnectCount = 0\n let reconnectTimer: any = null\n\n // Environment check\n const isSSR = typeof window === 'undefined'\n\n const connect = () => {\n if (isSSR || eventSource) return\n\n // Extract target URL from string, ref, or getter function\n const targetUrl =\n typeof url === 'function'\n ? url()\n : typeof url === 'object' && 'value' in url\n ? url.value\n : url\n\n status.value = 'connecting'\n error.value = null\n\n try {\n eventSource = new EventSource(targetUrl)\n\n eventSource.onopen = (event) => {\n status.value = 'open'\n reconnectCount = 0\n onOpen?.(event)\n }\n\n eventSource.onmessage = (event: MessageEvent) => {\n // Attempt to parse JSON, fallback to raw string if it fails\n try {\n const parsed = JSON.parse(event.data)\n data.value = parsed\n onMessage?.(parsed, event)\n } catch {\n data.value = event.data as any\n onMessage?.(event.data, event)\n }\n }\n\n eventSource.onerror = (event) => {\n error.value = event\n onError?.(event)\n\n // Trigger reconnection\n tryReconnect()\n }\n } catch (err) {\n status.value = 'closed'\n error.value = err as any\n tryReconnect()\n }\n }\n\n const disconnect = () => {\n if (reconnectTimer) {\n clearTimeout(reconnectTimer)\n reconnectTimer = null\n }\n if (eventSource) {\n eventSource.close()\n eventSource = null\n }\n status.value = 'closed'\n }\n\n const tryReconnect = () => {\n disconnect()\n\n if (reconnectCount < maxReconnectAttempts) {\n status.value = 'connecting'\n reconnectCount++\n reconnectTimer = setTimeout(connect, reconnectDelay)\n } else {\n status.value = 'closed'\n }\n }\n\n // Monitor URL change if it is reactive\n if (typeof url === 'function' || (typeof url === 'object' && 'value' in url)) {\n watch(url, () => {\n if (status.value !== 'closed') {\n disconnect()\n connect()\n }\n })\n }\n\n if (autoConnect) {\n connect()\n }\n\n onUnmounted(() => {\n disconnect()\n })\n\n return {\n data,\n status,\n error,\n connect,\n disconnect\n }\n}\n"],"mappings":";;;;;CAWA,SAAgB,OACd,KACA,UAA4B,CAAC,GAC7B;EACA,MAAM,EACJ,cAAc,MACd,iBAAiB,KACjB,uBAAuB,GACvB,WACA,SACA,WACE;EAEJ,MAAM,QAAA,GAAA,SAAA,IAAA,CAAqB,IAAI;EAC/B,MAAM,UAAA,GAAA,SAAA,IAAA,CAA+C,QAAQ;EAC7D,MAAM,SAAA,GAAA,SAAA,IAAA,CAA0B,IAAI;EAEpC,IAAI,cAAkC;EACtC,IAAI,iBAAiB;EACrB,IAAI,iBAAsB;EAG1B,MAAM,QAAQ,OAAO,WAAW;EAEhC,MAAM,gBAAgB;GACpB,IAAI,SAAS,aAAa;GAG1B,MAAM,YACJ,OAAO,QAAQ,aACX,IAAI,IACJ,OAAO,QAAQ,YAAY,WAAW,MACpC,IAAI,QACJ;GAER,OAAO,QAAQ;GACf,MAAM,QAAQ;GAEd,IAAI;IACF,cAAc,IAAI,YAAY,SAAS;IAEvC,YAAY,UAAU,UAAU;KAC9B,OAAO,QAAQ;KACf,iBAAiB;KACjB,SAAS,KAAK;IAChB;IAEA,YAAY,aAAa,UAAwB;KAE/C,IAAI;MACF,MAAM,SAAS,KAAK,MAAM,MAAM,IAAI;MACpC,KAAK,QAAQ;MACb,YAAY,QAAQ,KAAK;KAC3B,QAAQ;MACN,KAAK,QAAQ,MAAM;MACnB,YAAY,MAAM,MAAM,KAAK;KAC/B;IACF;IAEA,YAAY,WAAW,UAAU;KAC/B,MAAM,QAAQ;KACd,UAAU,KAAK;KAGf,aAAa;IACf;GACF,SAAS,KAAK;IACZ,OAAO,QAAQ;IACf,MAAM,QAAQ;IACd,aAAa;GACf;EACF;EAEA,MAAM,mBAAmB;GACvB,IAAI,gBAAgB;IAClB,aAAa,cAAc;IAC3B,iBAAiB;GACnB;GACA,IAAI,aAAa;IACf,YAAY,MAAM;IAClB,cAAc;GAChB;GACA,OAAO,QAAQ;EACjB;EAEA,MAAM,qBAAqB;GACzB,WAAW;GAEX,IAAI,iBAAiB,sBAAsB;IACzC,OAAO,QAAQ;IACf;IACA,iBAAiB,WAAW,SAAS,cAAc;GACrD,OACE,OAAO,QAAQ;EAEnB;EAGA,IAAI,OAAO,QAAQ,cAAe,OAAO,QAAQ,YAAY,WAAW,KACtE,CAAA,GAAA,SAAA,MAAA,CAAM,WAAW;GACf,IAAI,OAAO,UAAU,UAAU;IAC7B,WAAW;IACX,QAAQ;GACV;EACF,CAAC;EAGH,IAAI,aACF,QAAQ;EAGV,CAAA,GAAA,SAAA,YAAA,OAAkB;GAChB,WAAW;EACb,CAAC;EAED,OAAO;GACL;GACA;GACA;GACA;GACA;EACF;CACF"}
|
package/dist/useSse.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Ref } from 'vue-demi';
|
|
2
|
+
export interface UseSseOptions<T = any> {
|
|
3
|
+
autoConnect?: boolean;
|
|
4
|
+
reconnectDelay?: number;
|
|
5
|
+
maxReconnectAttempts?: number;
|
|
6
|
+
onMessage?: (data: T, event: MessageEvent) => void;
|
|
7
|
+
onError?: (event: Event) => void;
|
|
8
|
+
onOpen?: (event: Event) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function useSse<T = any>(url: string | (() => string) | Ref<string>, options?: UseSseOptions<T>): {
|
|
11
|
+
data: Ref<T | null>;
|
|
12
|
+
status: Ref<"connecting" | "open" | "closed">;
|
|
13
|
+
error: Ref<{
|
|
14
|
+
readonly bubbles: boolean;
|
|
15
|
+
cancelBubble: boolean;
|
|
16
|
+
readonly cancelable: boolean;
|
|
17
|
+
readonly composed: boolean;
|
|
18
|
+
readonly currentTarget: {
|
|
19
|
+
addEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void;
|
|
20
|
+
dispatchEvent: (event: Event) => boolean;
|
|
21
|
+
removeEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean) => void;
|
|
22
|
+
} | null;
|
|
23
|
+
readonly defaultPrevented: boolean;
|
|
24
|
+
readonly eventPhase: number;
|
|
25
|
+
readonly isTrusted: boolean;
|
|
26
|
+
returnValue: boolean;
|
|
27
|
+
readonly srcElement: {
|
|
28
|
+
addEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void;
|
|
29
|
+
dispatchEvent: (event: Event) => boolean;
|
|
30
|
+
removeEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean) => void;
|
|
31
|
+
} | null;
|
|
32
|
+
readonly target: {
|
|
33
|
+
addEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void;
|
|
34
|
+
dispatchEvent: (event: Event) => boolean;
|
|
35
|
+
removeEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean) => void;
|
|
36
|
+
} | null;
|
|
37
|
+
readonly timeStamp: DOMHighResTimeStamp;
|
|
38
|
+
readonly type: string;
|
|
39
|
+
composedPath: () => EventTarget[];
|
|
40
|
+
initEvent: (type: string, bubbles?: boolean, cancelable?: boolean) => void;
|
|
41
|
+
preventDefault: () => void;
|
|
42
|
+
stopImmediatePropagation: () => void;
|
|
43
|
+
stopPropagation: () => void;
|
|
44
|
+
readonly NONE: 0;
|
|
45
|
+
readonly CAPTURING_PHASE: 1;
|
|
46
|
+
readonly AT_TARGET: 2;
|
|
47
|
+
readonly BUBBLING_PHASE: 3;
|
|
48
|
+
} | null>;
|
|
49
|
+
connect: () => void;
|
|
50
|
+
disconnect: () => void;
|
|
51
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "use-sse-vue",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "A lightweight, robust Vue and Nuxt composable for managing Server-Sent Events (SSE) connections with auto-reconnect, JSON parsing, and SSR safety",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Roman",
|
|
9
|
+
"homepage": "https://github.com/roman3205/use-sse-vue#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/roman3205/use-sse-vue.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/roman3205/use-sse-vue/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"vue",
|
|
19
|
+
"vue3",
|
|
20
|
+
"vue2",
|
|
21
|
+
"nuxt",
|
|
22
|
+
"nuxt3",
|
|
23
|
+
"sse",
|
|
24
|
+
"server-sent-events",
|
|
25
|
+
"composable",
|
|
26
|
+
"useSse",
|
|
27
|
+
"reconnect"
|
|
28
|
+
],
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"main": "./dist/index.umd.cjs",
|
|
31
|
+
"module": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js",
|
|
37
|
+
"require": "./dist/index.umd.cjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"dev": "node playground/server.js & vite playground --config vite.config.ts",
|
|
45
|
+
"playground": "vite playground --config vite.config.ts",
|
|
46
|
+
"server": "node playground/server.js",
|
|
47
|
+
"build": "vite build && vue-tsc",
|
|
48
|
+
"preview": "vite preview",
|
|
49
|
+
"type-check": "vue-tsc --noEmit && vue-tsc -p playground/tsconfig.json",
|
|
50
|
+
"lint": "eslint .",
|
|
51
|
+
"format": "prettier --write .",
|
|
52
|
+
"prepublishOnly": "npm run build"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@eslint/js": "^10.0.1",
|
|
56
|
+
"@tailwindcss/vite": "^4.3.1",
|
|
57
|
+
"@vitejs/plugin-vue": "^6.0.7",
|
|
58
|
+
"eslint": "^10.5.0",
|
|
59
|
+
"eslint-plugin-vue": "^10.9.2",
|
|
60
|
+
"globals": "^17.7.0",
|
|
61
|
+
"prettier": "^3.8.5",
|
|
62
|
+
"tailwindcss": "^4.3.1",
|
|
63
|
+
"typescript": "~6.0.2",
|
|
64
|
+
"typescript-eslint": "^8.62.0",
|
|
65
|
+
"vite": "^8.1.0",
|
|
66
|
+
"vue": "^3.4.5",
|
|
67
|
+
"vue-tsc": "^3.3.5"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"vue": "^2.7.0 || ^3.0.0"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"vue-demi": "^0.14.10"
|
|
74
|
+
}
|
|
75
|
+
}
|