@enfyra/sdk-nuxt 0.7.5 → 0.7.6
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 +19 -1
- package/dist/module.cjs +3 -0
- package/dist/module.d.ts.map +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +3 -0
- package/dist/runtime/server/plugins/socket-relay.d.ts +3 -0
- package/dist/runtime/server/plugins/socket-relay.d.ts.map +1 -0
- package/dist/runtime/server/plugins/socket-relay.js +69 -0
- package/package.json +6 -2
- package/src/module.ts +4 -0
- package/src/runtime/server/plugins/socket-relay.ts +83 -0
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Nuxt SDK for Enfyra CMS - A lightweight composable-based API client with full Ty
|
|
|
7
7
|
✅ **Simple & Flexible** - Get base URL and build your own composables
|
|
8
8
|
✅ **Authentication Integration** - Built-in auth composables with automatic header forwarding
|
|
9
9
|
✅ **Asset Proxy** - Automatic `/assets/**` proxy to backend with no configuration needed
|
|
10
|
+
✅ **WebSocket Relay** - Relay Socket.IO through Nuxt at `/ws/:path` (keeps backend hidden)
|
|
10
11
|
✅ **TypeScript Support** - Full type safety with auto-generated declarations
|
|
11
12
|
✅ **SSR Ready** - Works seamlessly with Nuxt's `useFetch` and `$fetch`
|
|
12
13
|
|
|
@@ -43,10 +44,27 @@ The SDK automatically detects your application URL:
|
|
|
43
44
|
|
|
44
45
|
```typescript
|
|
45
46
|
// Get the base URL for your API requests
|
|
46
|
-
const { baseUrl, apiPrefix } = useEnfyra();
|
|
47
|
+
const { baseUrl, apiPrefix, wsBaseUrl, wsPath } = useEnfyra();
|
|
47
48
|
|
|
48
49
|
// baseUrl: "http://localhost:3001/enfyra/api"
|
|
49
50
|
// apiPrefix: "/enfyra/api"
|
|
51
|
+
// wsBaseUrl: "http://localhost:3001" (for WebSocket relay)
|
|
52
|
+
// wsPath: "/ws/socket.io" (engine path)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### WebSocket Relay
|
|
56
|
+
|
|
57
|
+
The SDK relays Socket.IO through Nuxt so the backend can stay non-public. Use `socket.io-client` with `wsBaseUrl` and `wsPath`:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { io } from 'socket.io-client';
|
|
61
|
+
|
|
62
|
+
const { wsBaseUrl, wsPath } = useEnfyra();
|
|
63
|
+
|
|
64
|
+
const socket = io(wsBaseUrl + '/chat', {
|
|
65
|
+
path: wsPath,
|
|
66
|
+
auth: { token }, // if gateway requireAuth
|
|
67
|
+
});
|
|
50
68
|
```
|
|
51
69
|
|
|
52
70
|
### Using with `useFetch` (SSR)
|
package/dist/module.cjs
CHANGED
|
@@ -106,6 +106,9 @@ declare module '#imports' {
|
|
|
106
106
|
route: `${apiPrefix}/**`,
|
|
107
107
|
handler: resolve("./runtime/server/api/all")
|
|
108
108
|
});
|
|
109
|
+
nuxt.options.nitro = nuxt.options.nitro || {};
|
|
110
|
+
nuxt.options.nitro.experimental = nuxt.options.nitro.experimental || {};
|
|
111
|
+
nuxt.options.nitro.experimental.websocket = true;
|
|
109
112
|
}
|
|
110
113
|
});
|
|
111
114
|
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;AAED,
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;AAED,wBAiIG"}
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -103,6 +103,9 @@ declare module '#imports' {
|
|
|
103
103
|
route: `${apiPrefix}/**`,
|
|
104
104
|
handler: resolve("./runtime/server/api/all")
|
|
105
105
|
});
|
|
106
|
+
nuxt.options.nitro = nuxt.options.nitro || {};
|
|
107
|
+
nuxt.options.nitro.experimental = nuxt.options.nitro.experimental || {};
|
|
108
|
+
nuxt.options.nitro.experimental.websocket = true;
|
|
106
109
|
}
|
|
107
110
|
});
|
|
108
111
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-relay.d.ts","sourceRoot":"","sources":["../../../../src/runtime/server/plugins/socket-relay.ts"],"names":[],"mappings":";AAUA,wBAwEG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
2
|
+
import { Server as Engine } from "engine.io";
|
|
3
|
+
import { Server } from "socket.io";
|
|
4
|
+
import { io as ioClient } from "socket.io-client";
|
|
5
|
+
import { defineEventHandler } from "h3";
|
|
6
|
+
import { useRuntimeConfig } from "#imports";
|
|
7
|
+
const ENGINE_PATH = "/socket.io";
|
|
8
|
+
const ENGINE_PATH_SLASH = `${ENGINE_PATH}/`;
|
|
9
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
10
|
+
const config = useRuntimeConfig();
|
|
11
|
+
const apiUrl = config.public?.enfyraSDK?.apiUrl;
|
|
12
|
+
if (!apiUrl) return;
|
|
13
|
+
const backendUrl = String(apiUrl).replace(/\/+$/, "");
|
|
14
|
+
const engine = new Engine();
|
|
15
|
+
const io = new Server();
|
|
16
|
+
io.bind(engine);
|
|
17
|
+
io.on("connection", (clientSocket) => {
|
|
18
|
+
const namespace = clientSocket.nsp.name;
|
|
19
|
+
const backendNamespace = namespace === "/" || namespace === "" ? "/" : namespace;
|
|
20
|
+
const backendNsUrl = `${backendUrl}${backendNamespace}`;
|
|
21
|
+
const backendSocket = ioClient(backendNsUrl, {
|
|
22
|
+
path: "/socket.io",
|
|
23
|
+
auth: clientSocket.handshake.auth,
|
|
24
|
+
transports: ["websocket", "polling"]
|
|
25
|
+
});
|
|
26
|
+
clientSocket.onAny((event, ...args) => {
|
|
27
|
+
if (event !== "disconnect") {
|
|
28
|
+
backendSocket.emit(event, ...args);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
backendSocket.onAny((event, ...args) => {
|
|
32
|
+
clientSocket.emit(event, ...args);
|
|
33
|
+
});
|
|
34
|
+
clientSocket.on("disconnect", () => {
|
|
35
|
+
backendSocket.disconnect();
|
|
36
|
+
});
|
|
37
|
+
backendSocket.on("disconnect", () => {
|
|
38
|
+
clientSocket.disconnect();
|
|
39
|
+
});
|
|
40
|
+
backendSocket.on("connect_error", (err) => {
|
|
41
|
+
clientSocket.emit("connect_error", err.message);
|
|
42
|
+
clientSocket.disconnect();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
nitroApp.router.use(
|
|
46
|
+
`${ENGINE_PATH_SLASH}`,
|
|
47
|
+
defineEventHandler({
|
|
48
|
+
handler(event) {
|
|
49
|
+
const req = event.node.req;
|
|
50
|
+
const res = event.node.res;
|
|
51
|
+
engine.handleRequest(req, res);
|
|
52
|
+
event._handled = true;
|
|
53
|
+
},
|
|
54
|
+
websocket: {
|
|
55
|
+
open(peer) {
|
|
56
|
+
const nodeReq = peer._internal?.nodeReq;
|
|
57
|
+
if (nodeReq) {
|
|
58
|
+
engine.prepare(nodeReq);
|
|
59
|
+
engine.onWebSocket(
|
|
60
|
+
nodeReq,
|
|
61
|
+
nodeReq.socket,
|
|
62
|
+
peer.websocket
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enfyra/sdk-nuxt",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Nuxt SDK for Enfyra CMS",
|
|
6
6
|
"repository": {
|
|
@@ -55,13 +55,17 @@
|
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@nuxt/kit": "^3.18.1",
|
|
58
|
+
"nitropack": ">=2.0.0",
|
|
58
59
|
"vue": "^3.0.0"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
62
|
"defu": "^6.1.4",
|
|
63
|
+
"engine.io": "^6.6.3",
|
|
62
64
|
"h3": "^1.15.4",
|
|
63
65
|
"http-proxy": "^1.18.1",
|
|
64
|
-
"ofetch": "^1.3.3"
|
|
66
|
+
"ofetch": "^1.3.3",
|
|
67
|
+
"socket.io": "^4.8.3",
|
|
68
|
+
"socket.io-client": "^4.8.3"
|
|
65
69
|
},
|
|
66
70
|
"devDependencies": {
|
|
67
71
|
"@nuxt/module-builder": "^0.8.4",
|
package/src/module.ts
CHANGED
|
@@ -139,5 +139,9 @@ declare module '#imports' {
|
|
|
139
139
|
route: `${apiPrefix}/**`,
|
|
140
140
|
handler: resolve("./runtime/server/api/all"),
|
|
141
141
|
});
|
|
142
|
+
|
|
143
|
+
nuxt.options.nitro = nuxt.options.nitro || {};
|
|
144
|
+
nuxt.options.nitro.experimental = nuxt.options.nitro.experimental || {};
|
|
145
|
+
nuxt.options.nitro.experimental.websocket = true;
|
|
142
146
|
},
|
|
143
147
|
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// @ts-nocheck - Nitro plugin
|
|
2
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
3
|
+
import { Server as Engine } from "engine.io";
|
|
4
|
+
import { Server } from "socket.io";
|
|
5
|
+
import { io as ioClient } from "socket.io-client";
|
|
6
|
+
import { defineEventHandler } from "h3";
|
|
7
|
+
import { useRuntimeConfig } from "#imports";
|
|
8
|
+
const ENGINE_PATH = "/socket.io";
|
|
9
|
+
const ENGINE_PATH_SLASH = `${ENGINE_PATH}/`;
|
|
10
|
+
|
|
11
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
12
|
+
const config = useRuntimeConfig();
|
|
13
|
+
const apiUrl = config.public?.enfyraSDK?.apiUrl;
|
|
14
|
+
if (!apiUrl) return;
|
|
15
|
+
|
|
16
|
+
const backendUrl = String(apiUrl).replace(/\/+$/, "");
|
|
17
|
+
const engine = new Engine();
|
|
18
|
+
const io = new Server();
|
|
19
|
+
io.bind(engine);
|
|
20
|
+
|
|
21
|
+
io.on("connection", (clientSocket) => {
|
|
22
|
+
const namespace = clientSocket.nsp.name;
|
|
23
|
+
const backendNamespace =
|
|
24
|
+
namespace === "/" || namespace === "" ? "/" : namespace;
|
|
25
|
+
const backendNsUrl = `${backendUrl}${backendNamespace}`;
|
|
26
|
+
|
|
27
|
+
const backendSocket = ioClient(backendNsUrl, {
|
|
28
|
+
path: "/socket.io",
|
|
29
|
+
auth: clientSocket.handshake.auth,
|
|
30
|
+
transports: ["websocket", "polling"],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
clientSocket.onAny((event: string, ...args: unknown[]) => {
|
|
34
|
+
if (event !== "disconnect") {
|
|
35
|
+
backendSocket.emit(event, ...args);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
backendSocket.onAny((event: string, ...args: unknown[]) => {
|
|
40
|
+
clientSocket.emit(event, ...args);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
clientSocket.on("disconnect", () => {
|
|
44
|
+
backendSocket.disconnect();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
backendSocket.on("disconnect", () => {
|
|
48
|
+
clientSocket.disconnect();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
backendSocket.on("connect_error", (err: Error) => {
|
|
52
|
+
clientSocket.emit("connect_error", err.message);
|
|
53
|
+
clientSocket.disconnect();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
nitroApp.router.use(
|
|
58
|
+
`${ENGINE_PATH_SLASH}`,
|
|
59
|
+
defineEventHandler({
|
|
60
|
+
handler(event) {
|
|
61
|
+
const req = event.node.req as Parameters<InstanceType<typeof Engine>["handleRequest"]>[0];
|
|
62
|
+
const res = event.node.res as Parameters<InstanceType<typeof Engine>["handleRequest"]>[1];
|
|
63
|
+
engine.handleRequest(req, res);
|
|
64
|
+
event._handled = true;
|
|
65
|
+
},
|
|
66
|
+
websocket: {
|
|
67
|
+
open(peer) {
|
|
68
|
+
// Nitro/crossws peer with nodeReq for engine.io integration
|
|
69
|
+
const nodeReq = (peer as { _internal?: { nodeReq?: { socket?: unknown } } })._internal?.nodeReq;
|
|
70
|
+
if (nodeReq) {
|
|
71
|
+
(engine as unknown as { prepare(r: unknown): void; onWebSocket(a: unknown, b: unknown, c: WebSocket): void })
|
|
72
|
+
.prepare(nodeReq);
|
|
73
|
+
(engine as unknown as { onWebSocket(a: unknown, b: unknown, c: WebSocket): void }).onWebSocket(
|
|
74
|
+
nodeReq,
|
|
75
|
+
(nodeReq as { socket?: unknown }).socket,
|
|
76
|
+
peer.websocket,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
});
|