nuxt-visitors 1.0.1 → 1.1.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Nuxt Active Users
1
+ # Nuxt Visitors 👀
2
2
 
3
3
  <!-- automd:badges color=black license provider=shields name=nuxt-visitors -->
4
4
 
@@ -17,6 +17,7 @@ Add live visitor counting to your Nuxt website in seconds. WebSocket-based, type
17
17
  - 🛠 Automatic connection management
18
18
  - 📊 Type-safe composable
19
19
  - 🧹 Auto cleanup on unmount
20
+ - 🌐 Leverages [Nitro WebSocket](https://nitro.unjs.io/guide/websocket) with Pub/Sub
20
21
 
21
22
  ## Installation
22
23
 
@@ -26,30 +27,19 @@ Install the module to your Nuxt application with one command:
26
27
  npx nuxi module add nuxt-visitors
27
28
  ```
28
29
 
29
- <!-- automd:pm-install name="nuxt-visitors" -->
30
+ As [Nitro WebSocket support](https://nitro.unjs.io/guide/websocket) is experimental, you need to enable it in your `nuxt.config.ts`:
30
31
 
31
- ```sh
32
- # Auto-detect
33
- npx nypm install nuxt-visitors
34
-
35
- # npm
36
- npm install nuxt-visitors
37
-
38
- # yarn
39
- yarn add nuxt-visitors
40
-
41
- # pnpm
42
- pnpm install nuxt-visitors
43
-
44
- # bun
45
- bun install nuxt-visitors
46
-
47
- # deno
48
- deno install nuxt-visitors
32
+ ```ts
33
+ export default defineNuxtConfig({
34
+ modules: ['nuxt-visitors'],
35
+ nitro: {
36
+ experimental: {
37
+ websocket: true
38
+ }
39
+ }
40
+ })
49
41
  ```
50
42
 
51
- <!-- /automd -->
52
-
53
43
  ## Usage
54
44
 
55
45
  ```vue
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-visitors",
3
3
  "configKey": "visitors",
4
- "version": "1.0.1",
4
+ "version": "1.1.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -7,14 +7,10 @@ const module = defineNuxtModule({
7
7
  },
8
8
  setup(_options, nuxt) {
9
9
  const resolver = createResolver(import.meta.url);
10
- nuxt.options = nuxt.options || {};
11
- nuxt.options.nitro = nuxt.options.nitro || {};
12
- nuxt.options.nitro.experimental = nuxt.options.nitro.experimental || {};
13
- nuxt.options.nitro.experimental.websocket = true;
14
- addImportsDir(resolver.resolve("runtime/composables"));
10
+ addImportsDir(resolver.resolve("./runtime/app/composables"));
15
11
  addServerHandler({
16
- route: "/api/_visitors_/ws",
17
- handler: resolver.resolve("./runtime/server/api/visitors.ts")
12
+ route: "/.nuxt-visitors/ws",
13
+ handler: resolver.resolve("./runtime/server/routes/visitors")
18
14
  });
19
15
  }
20
16
  });
@@ -10,7 +10,7 @@ export function useVisitors() {
10
10
  const getWebSocketUrl = () => {
11
11
  const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
12
12
  const baseUrl = window.location.host.replace(/^(http|https):\/\//, "");
13
- return `${protocol}//${baseUrl}/api/_visitors_/ws`;
13
+ return `${protocol}//${baseUrl}/.nuxt-visitors/ws`;
14
14
  };
15
15
  const cleanup = () => {
16
16
  if (wsRef.value) {
@@ -20,10 +20,11 @@ export function useVisitors() {
20
20
  isConnected.value = false;
21
21
  isLoading.value = false;
22
22
  };
23
- const handleMessage = (event) => {
23
+ const handleMessage = async (event) => {
24
24
  if (!isMounted.value) return;
25
25
  try {
26
- const visitorCount = parseInt(event.data, 10);
26
+ const data = typeof event.data === "string" ? event.data : await event.data.text();
27
+ const visitorCount = parseInt(data, 10);
27
28
  if (!isNaN(visitorCount) && visitorCount >= 0) {
28
29
  visitors.value = visitorCount;
29
30
  } else {
@@ -0,0 +1,11 @@
1
+ export default defineWebSocketHandler({
2
+ open(peer) {
3
+ peer.subscribe("nuxt-visitors");
4
+ peer.send(peer.peers.size);
5
+ peer.publish("nuxt-visitors", peer.peers.size);
6
+ },
7
+ close(peer) {
8
+ peer.publish("nuxt-visitors", peer.peers.size);
9
+ peer.unsubscribe("nuxt-visitors");
10
+ }
11
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-visitors",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Add real-time visitor tracking to your Nuxt app with one line of code. WebSocket made easy",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -50,11 +50,11 @@
50
50
  "@types/node": "latest",
51
51
  "changelogen": "^0.5.7",
52
52
  "eslint": "^9.19.0",
53
- "nuxt": "3.15.2",
53
+ "nuxt": "3.15.3",
54
54
  "typescript": "5.6.3",
55
55
  "vitest": "^3.0.4",
56
56
  "vue-tsc": "^2.2.0",
57
57
  "automd": "^0.3.12"
58
58
  },
59
- "packageManager": "pnpm@8.6.5+sha1.a074a371066567dcdeb19a1d1bd9a78cf3c9faa3"
59
+ "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
60
60
  }
@@ -1,54 +0,0 @@
1
- class StatsWebSocketManager {
2
- static instance;
3
- connectedPeers = /* @__PURE__ */ new Set();
4
- constructor() {
5
- }
6
- static getInstance() {
7
- if (!this.instance) {
8
- this.instance = new StatsWebSocketManager();
9
- }
10
- return this.instance;
11
- }
12
- addPeer(peer) {
13
- this.connectedPeers.add(peer);
14
- this.logConnectionStats();
15
- }
16
- removePeer(peer) {
17
- this.connectedPeers.delete(peer);
18
- this.logConnectionStats();
19
- }
20
- getActiveVisitors() {
21
- return this.connectedPeers.size;
22
- }
23
- updateActiveVisitors(visitors) {
24
- this.connectedPeers.forEach((peer) => {
25
- peer.send(JSON.stringify(visitors));
26
- });
27
- }
28
- logConnectionStats() {
29
- console.log(`Active visitors connections: ${this.connectedPeers.size}`);
30
- }
31
- }
32
- const wsManager = StatsWebSocketManager.getInstance();
33
- export default defineWebSocketHandler({
34
- open(peer) {
35
- try {
36
- wsManager.addPeer(peer);
37
- const visitors = wsManager.getActiveVisitors();
38
- wsManager.updateActiveVisitors(visitors);
39
- } catch (error) {
40
- console.error("Visitors WebSocket open error:", error);
41
- peer.close(1011, error instanceof Error ? error.message : "Unknown error");
42
- }
43
- },
44
- close(peer) {
45
- wsManager.removePeer(peer);
46
- const visitors = wsManager.getActiveVisitors();
47
- wsManager.updateActiveVisitors(visitors);
48
- console.log("Visitors WebSocket disconnected:", peer.id);
49
- },
50
- error(peer, error) {
51
- wsManager.removePeer(peer);
52
- console.error("Visitors WebSocket error:", error);
53
- }
54
- });