@elqnt/nats 1.0.0
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/dist/index.d.mts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +392 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +365 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +44 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { NatsConnection, JetStreamClient, KV, ObjectStore } from 'nats.ws';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
type NATSRequestFunction = <R, S>(topic: string, data: R, headers?: object) => Promise<S>;
|
|
6
|
+
type NATSPublishFunction = <T>(topic: string, data: T) => Promise<void>;
|
|
7
|
+
type NATSContextType = {
|
|
8
|
+
nats: NatsConnection | undefined;
|
|
9
|
+
JetStream: () => JetStreamClient;
|
|
10
|
+
KV: (bucket: string) => Promise<KV>;
|
|
11
|
+
ObjectStore: (bucket: string) => Promise<ObjectStore>;
|
|
12
|
+
natsConnected: boolean;
|
|
13
|
+
natsError: any;
|
|
14
|
+
request: NATSRequestFunction;
|
|
15
|
+
publish: NATSPublishFunction;
|
|
16
|
+
subscribe: <T>(topic: string, callback: (data: T | Error) => void) => Promise<void>;
|
|
17
|
+
parseJson: <T>(data: Uint8Array) => T;
|
|
18
|
+
parseString: (data: Uint8Array) => string;
|
|
19
|
+
encodePayLoad: (data: unknown) => Uint8Array;
|
|
20
|
+
loading: boolean;
|
|
21
|
+
retry: () => void;
|
|
22
|
+
retryCount: number;
|
|
23
|
+
isRetrying: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
declare const initialNATS: NATSContextType;
|
|
27
|
+
declare const NatsContext: react.Context<NATSContextType>;
|
|
28
|
+
declare const useNatsContext: () => NATSContextType;
|
|
29
|
+
|
|
30
|
+
type NATSProviderProps = {
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
apiEndpoint: string;
|
|
33
|
+
};
|
|
34
|
+
declare function NATSProvider(props: NATSProviderProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
|
|
36
|
+
declare const useNATS: (authApiUrl: string) => {
|
|
37
|
+
nats: NatsConnection | undefined;
|
|
38
|
+
JetStream: () => JetStreamClient;
|
|
39
|
+
KV: (bucket: string) => Promise<KV>;
|
|
40
|
+
ObjectStore: (bucket: string) => Promise<ObjectStore>;
|
|
41
|
+
natsConnected: boolean;
|
|
42
|
+
natsError: any;
|
|
43
|
+
request: <R, S>(topic: string, data: R, headersObj?: object) => Promise<S>;
|
|
44
|
+
publish: (topic: string, data: any, headersObj?: object) => Promise<void>;
|
|
45
|
+
subscribe: <S>(topic: string, callbackFn: (data: S | Error) => void) => Promise<void>;
|
|
46
|
+
parseJson: <T>(data: Uint8Array) => T;
|
|
47
|
+
parseString: (data: Uint8Array) => string;
|
|
48
|
+
encodePayLoad: (data: unknown) => Uint8Array;
|
|
49
|
+
loading: boolean;
|
|
50
|
+
retry: () => void;
|
|
51
|
+
retryCount: number;
|
|
52
|
+
isRetrying: boolean;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
declare function stringToReadableStream(str: string): ReadableStream<any>;
|
|
56
|
+
declare function readStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array>;
|
|
57
|
+
|
|
58
|
+
export { type NATSContextType, NATSProvider, type NATSPublishFunction, type NATSRequestFunction, NatsContext, initialNATS, readStream, stringToReadableStream, useNATS, useNatsContext };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { NatsConnection, JetStreamClient, KV, ObjectStore } from 'nats.ws';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
type NATSRequestFunction = <R, S>(topic: string, data: R, headers?: object) => Promise<S>;
|
|
6
|
+
type NATSPublishFunction = <T>(topic: string, data: T) => Promise<void>;
|
|
7
|
+
type NATSContextType = {
|
|
8
|
+
nats: NatsConnection | undefined;
|
|
9
|
+
JetStream: () => JetStreamClient;
|
|
10
|
+
KV: (bucket: string) => Promise<KV>;
|
|
11
|
+
ObjectStore: (bucket: string) => Promise<ObjectStore>;
|
|
12
|
+
natsConnected: boolean;
|
|
13
|
+
natsError: any;
|
|
14
|
+
request: NATSRequestFunction;
|
|
15
|
+
publish: NATSPublishFunction;
|
|
16
|
+
subscribe: <T>(topic: string, callback: (data: T | Error) => void) => Promise<void>;
|
|
17
|
+
parseJson: <T>(data: Uint8Array) => T;
|
|
18
|
+
parseString: (data: Uint8Array) => string;
|
|
19
|
+
encodePayLoad: (data: unknown) => Uint8Array;
|
|
20
|
+
loading: boolean;
|
|
21
|
+
retry: () => void;
|
|
22
|
+
retryCount: number;
|
|
23
|
+
isRetrying: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
declare const initialNATS: NATSContextType;
|
|
27
|
+
declare const NatsContext: react.Context<NATSContextType>;
|
|
28
|
+
declare const useNatsContext: () => NATSContextType;
|
|
29
|
+
|
|
30
|
+
type NATSProviderProps = {
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
apiEndpoint: string;
|
|
33
|
+
};
|
|
34
|
+
declare function NATSProvider(props: NATSProviderProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
|
|
36
|
+
declare const useNATS: (authApiUrl: string) => {
|
|
37
|
+
nats: NatsConnection | undefined;
|
|
38
|
+
JetStream: () => JetStreamClient;
|
|
39
|
+
KV: (bucket: string) => Promise<KV>;
|
|
40
|
+
ObjectStore: (bucket: string) => Promise<ObjectStore>;
|
|
41
|
+
natsConnected: boolean;
|
|
42
|
+
natsError: any;
|
|
43
|
+
request: <R, S>(topic: string, data: R, headersObj?: object) => Promise<S>;
|
|
44
|
+
publish: (topic: string, data: any, headersObj?: object) => Promise<void>;
|
|
45
|
+
subscribe: <S>(topic: string, callbackFn: (data: S | Error) => void) => Promise<void>;
|
|
46
|
+
parseJson: <T>(data: Uint8Array) => T;
|
|
47
|
+
parseString: (data: Uint8Array) => string;
|
|
48
|
+
encodePayLoad: (data: unknown) => Uint8Array;
|
|
49
|
+
loading: boolean;
|
|
50
|
+
retry: () => void;
|
|
51
|
+
retryCount: number;
|
|
52
|
+
isRetrying: boolean;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
declare function stringToReadableStream(str: string): ReadableStream<any>;
|
|
56
|
+
declare function readStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array>;
|
|
57
|
+
|
|
58
|
+
export { type NATSContextType, NATSProvider, type NATSPublishFunction, type NATSRequestFunction, NatsContext, initialNATS, readStream, stringToReadableStream, useNATS, useNatsContext };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// index.tsx
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
NATSProvider: () => NATSProvider,
|
|
24
|
+
NatsContext: () => NatsContext,
|
|
25
|
+
initialNATS: () => initialNATS,
|
|
26
|
+
readStream: () => readStream,
|
|
27
|
+
stringToReadableStream: () => stringToReadableStream,
|
|
28
|
+
useNATS: () => useNATS,
|
|
29
|
+
useNatsContext: () => useNatsContext
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
|
|
33
|
+
// context/nats-context.ts
|
|
34
|
+
var import_react = require("react");
|
|
35
|
+
var initialNATS = {
|
|
36
|
+
nats: void 0,
|
|
37
|
+
JetStream: () => null,
|
|
38
|
+
KV: async (bucket) => Promise.resolve({}),
|
|
39
|
+
ObjectStore: async (bucket) => Promise.resolve({}),
|
|
40
|
+
natsConnected: false,
|
|
41
|
+
natsError: null,
|
|
42
|
+
request: (topic, data) => Promise.resolve({}),
|
|
43
|
+
publish: (topic, data) => Promise.resolve(),
|
|
44
|
+
subscribe: (topic, callback) => Promise.resolve(),
|
|
45
|
+
parseJson: (data) => JSON.parse(data.toString()),
|
|
46
|
+
parseString: (data) => data.toString(),
|
|
47
|
+
encodePayLoad: (data) => new TextEncoder().encode(JSON.stringify(data)),
|
|
48
|
+
loading: false,
|
|
49
|
+
retry: () => {
|
|
50
|
+
},
|
|
51
|
+
retryCount: 0,
|
|
52
|
+
isRetrying: false
|
|
53
|
+
};
|
|
54
|
+
var NatsContext = (0, import_react.createContext)(initialNATS);
|
|
55
|
+
var useNatsContext = () => (0, import_react.useContext)(NatsContext);
|
|
56
|
+
|
|
57
|
+
// context/nats-provider.tsx
|
|
58
|
+
var import_react3 = require("react");
|
|
59
|
+
|
|
60
|
+
// hooks/use-nats.ts
|
|
61
|
+
var import_nats = require("nats.ws");
|
|
62
|
+
var import_react2 = require("react");
|
|
63
|
+
var TIMEOUT = 9e8;
|
|
64
|
+
var AUTH_FETCH_TIMEOUT = 1e4;
|
|
65
|
+
var MAX_RETRIES = 5;
|
|
66
|
+
var INITIAL_RETRY_DELAY = 1e3;
|
|
67
|
+
var useNATS = (authApiUrl) => {
|
|
68
|
+
const [nats, setNATS] = (0, import_react2.useState)(void 0);
|
|
69
|
+
const [natsConnected, setNATSConnected] = (0, import_react2.useState)(false);
|
|
70
|
+
const [natsError, setNATSError] = (0, import_react2.useState)(void 0);
|
|
71
|
+
const [loading, setLoading] = (0, import_react2.useState)(false);
|
|
72
|
+
const [retryCount, setRetryCount] = (0, import_react2.useState)(0);
|
|
73
|
+
const [isRetrying, setIsRetrying] = (0, import_react2.useState)(false);
|
|
74
|
+
const connectionRef = (0, import_react2.useRef)(null);
|
|
75
|
+
const retryTimeoutRef = (0, import_react2.useRef)(null);
|
|
76
|
+
const isConnectingRef = (0, import_react2.useRef)(false);
|
|
77
|
+
const isMountedRef = (0, import_react2.useRef)(true);
|
|
78
|
+
const connectNATS = (0, import_react2.useCallback)(
|
|
79
|
+
async (attempt = 0) => {
|
|
80
|
+
if (isConnectingRef.current || connectionRef.current) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
isConnectingRef.current = true;
|
|
84
|
+
setLoading(true);
|
|
85
|
+
setNATSError(void 0);
|
|
86
|
+
if (attempt > 0) {
|
|
87
|
+
setIsRetrying(true);
|
|
88
|
+
setRetryCount(attempt);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const controller = new AbortController();
|
|
92
|
+
const fetchTimeout = setTimeout(
|
|
93
|
+
() => controller.abort(),
|
|
94
|
+
AUTH_FETCH_TIMEOUT
|
|
95
|
+
);
|
|
96
|
+
const resp = await fetch(authApiUrl, { signal: controller.signal });
|
|
97
|
+
clearTimeout(fetchTimeout);
|
|
98
|
+
if (!resp.ok) {
|
|
99
|
+
throw new Error(`Auth fetch failed: ${resp.status}`);
|
|
100
|
+
}
|
|
101
|
+
const { jwt, natsUrl } = await resp.json();
|
|
102
|
+
const authenticator = (0, import_nats.jwtAuthenticator)(jwt);
|
|
103
|
+
const nc = await (0, import_nats.connect)({
|
|
104
|
+
servers: natsUrl,
|
|
105
|
+
authenticator,
|
|
106
|
+
timeout: TIMEOUT,
|
|
107
|
+
reconnect: true,
|
|
108
|
+
maxReconnectAttempts: -1,
|
|
109
|
+
// Unlimited reconnect attempts
|
|
110
|
+
reconnectTimeWait: 2e3
|
|
111
|
+
// Wait 2 seconds between reconnect attempts
|
|
112
|
+
});
|
|
113
|
+
if (!isMountedRef.current) {
|
|
114
|
+
await nc.close();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
connectionRef.current = nc;
|
|
118
|
+
setNATS(nc);
|
|
119
|
+
setNATSConnected(true);
|
|
120
|
+
setIsRetrying(false);
|
|
121
|
+
setRetryCount(0);
|
|
122
|
+
isConnectingRef.current = false;
|
|
123
|
+
setLoading(false);
|
|
124
|
+
console.log("NATS connected:", natsUrl);
|
|
125
|
+
(async () => {
|
|
126
|
+
for await (const status of nc.status()) {
|
|
127
|
+
if (!isMountedRef.current) break;
|
|
128
|
+
if (status.type === "disconnect") {
|
|
129
|
+
console.log("NATS disconnected, will auto-reconnect...");
|
|
130
|
+
setNATSConnected(false);
|
|
131
|
+
} else if (status.type === "reconnect") {
|
|
132
|
+
console.log("NATS reconnected");
|
|
133
|
+
setNATSConnected(true);
|
|
134
|
+
} else if (status.type === "error") {
|
|
135
|
+
console.error("NATS error:", status.data);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
})();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
isConnectingRef.current = false;
|
|
141
|
+
setLoading(false);
|
|
142
|
+
if (!isMountedRef.current) return;
|
|
143
|
+
const errorMessage = error.name === "AbortError" ? "Auth request timed out" : error;
|
|
144
|
+
console.error(
|
|
145
|
+
`NATS connection failed (attempt ${attempt + 1}/${MAX_RETRIES}):`,
|
|
146
|
+
errorMessage
|
|
147
|
+
);
|
|
148
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
149
|
+
const delay = INITIAL_RETRY_DELAY * Math.pow(2, attempt);
|
|
150
|
+
console.log(`Retrying NATS connection in ${delay / 1e3}s...`);
|
|
151
|
+
retryTimeoutRef.current = setTimeout(() => {
|
|
152
|
+
if (isMountedRef.current) {
|
|
153
|
+
connectNATS(attempt + 1);
|
|
154
|
+
}
|
|
155
|
+
}, delay);
|
|
156
|
+
} else {
|
|
157
|
+
setNATSError(error);
|
|
158
|
+
setIsRetrying(false);
|
|
159
|
+
console.error("NATS connection failed after max retries");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
[authApiUrl]
|
|
164
|
+
);
|
|
165
|
+
const retry = (0, import_react2.useCallback)(() => {
|
|
166
|
+
if (retryTimeoutRef.current) {
|
|
167
|
+
clearTimeout(retryTimeoutRef.current);
|
|
168
|
+
}
|
|
169
|
+
connectionRef.current = null;
|
|
170
|
+
isConnectingRef.current = false;
|
|
171
|
+
setNATSError(void 0);
|
|
172
|
+
connectNATS(0);
|
|
173
|
+
}, [connectNATS]);
|
|
174
|
+
(0, import_react2.useEffect)(() => {
|
|
175
|
+
isMountedRef.current = true;
|
|
176
|
+
connectNATS(0);
|
|
177
|
+
return () => {
|
|
178
|
+
isMountedRef.current = false;
|
|
179
|
+
if (retryTimeoutRef.current) {
|
|
180
|
+
clearTimeout(retryTimeoutRef.current);
|
|
181
|
+
}
|
|
182
|
+
if (connectionRef.current) {
|
|
183
|
+
connectionRef.current.close();
|
|
184
|
+
connectionRef.current = null;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}, [connectNATS]);
|
|
188
|
+
async function request(topic, data, headersObj = {}) {
|
|
189
|
+
if (!nats || !natsConnected) throw new Error("nats not connected !!");
|
|
190
|
+
const h = (0, import_nats.headers)();
|
|
191
|
+
Object.entries(headersObj).forEach(([key, value]) => {
|
|
192
|
+
if (!value) return;
|
|
193
|
+
h.append(key, value.toString());
|
|
194
|
+
});
|
|
195
|
+
const reqJC = (0, import_nats.JSONCodec)();
|
|
196
|
+
const resJC = (0, import_nats.JSONCodec)();
|
|
197
|
+
try {
|
|
198
|
+
const msg = await nats.request(topic, reqJC.encode(data), {
|
|
199
|
+
timeout: TIMEOUT,
|
|
200
|
+
headers: h
|
|
201
|
+
});
|
|
202
|
+
return resJC.decode(msg.data);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function parseJson(data) {
|
|
208
|
+
const jc = (0, import_nats.JSONCodec)();
|
|
209
|
+
try {
|
|
210
|
+
return jc.decode(data);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function parseString(data) {
|
|
216
|
+
const sc = (0, import_nats.StringCodec)();
|
|
217
|
+
try {
|
|
218
|
+
return sc.decode(data);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function publish(topic, data, headersObj = {}) {
|
|
224
|
+
if (!nats || !natsConnected) {
|
|
225
|
+
console.log("nats not connected !!");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const jc = (0, import_nats.JSONCodec)();
|
|
229
|
+
const h = (0, import_nats.headers)();
|
|
230
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
231
|
+
h.append(key, value);
|
|
232
|
+
}
|
|
233
|
+
nats.publish(topic, jc.encode(data), {
|
|
234
|
+
headers: h
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function encodePayLoad(data) {
|
|
238
|
+
const jc = (0, import_nats.JSONCodec)();
|
|
239
|
+
return jc.encode(data);
|
|
240
|
+
}
|
|
241
|
+
async function subscribe(topic, callbackFn) {
|
|
242
|
+
if (!nats || !natsConnected) {
|
|
243
|
+
console.log("nats not connected !!");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
nats.subscribe(topic, {
|
|
247
|
+
callback: (err, msg) => {
|
|
248
|
+
const jc = (0, import_nats.JSONCodec)();
|
|
249
|
+
const data = jc.decode(msg.data);
|
|
250
|
+
if (err) {
|
|
251
|
+
callbackFn(err);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
callbackFn(data);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
function JetStream() {
|
|
259
|
+
if (!nats || !natsConnected) {
|
|
260
|
+
throw new Error("nats not connected !!");
|
|
261
|
+
}
|
|
262
|
+
return nats.jetstream();
|
|
263
|
+
}
|
|
264
|
+
async function KV2(bucket) {
|
|
265
|
+
if (!nats || !natsConnected) {
|
|
266
|
+
throw new Error("nats not connected !!");
|
|
267
|
+
}
|
|
268
|
+
const js = JetStream();
|
|
269
|
+
return js.views.kv(bucket);
|
|
270
|
+
}
|
|
271
|
+
async function ObjectStore2(bucket) {
|
|
272
|
+
const js = JetStream();
|
|
273
|
+
return js.views.os(bucket);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
nats,
|
|
277
|
+
JetStream,
|
|
278
|
+
KV: KV2,
|
|
279
|
+
ObjectStore: ObjectStore2,
|
|
280
|
+
natsConnected,
|
|
281
|
+
natsError,
|
|
282
|
+
request,
|
|
283
|
+
publish,
|
|
284
|
+
subscribe,
|
|
285
|
+
parseJson,
|
|
286
|
+
parseString,
|
|
287
|
+
encodePayLoad,
|
|
288
|
+
loading,
|
|
289
|
+
// New retry-related properties
|
|
290
|
+
retry,
|
|
291
|
+
retryCount,
|
|
292
|
+
isRetrying
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
// context/nats-provider.tsx
|
|
297
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
298
|
+
function NATSProvider(props) {
|
|
299
|
+
const { children, apiEndpoint } = props;
|
|
300
|
+
const {
|
|
301
|
+
nats,
|
|
302
|
+
JetStream,
|
|
303
|
+
KV: KV2,
|
|
304
|
+
ObjectStore: ObjectStore2,
|
|
305
|
+
natsConnected,
|
|
306
|
+
natsError,
|
|
307
|
+
request,
|
|
308
|
+
publish,
|
|
309
|
+
subscribe,
|
|
310
|
+
parseJson,
|
|
311
|
+
parseString,
|
|
312
|
+
encodePayLoad,
|
|
313
|
+
loading,
|
|
314
|
+
retry,
|
|
315
|
+
retryCount,
|
|
316
|
+
isRetrying
|
|
317
|
+
} = useNATS(apiEndpoint);
|
|
318
|
+
const [ready, setReady] = (0, import_react3.useState)(false);
|
|
319
|
+
(0, import_react3.useEffect)(() => {
|
|
320
|
+
setReady(true);
|
|
321
|
+
}, []);
|
|
322
|
+
if (!ready) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
const contextValue = {
|
|
326
|
+
nats,
|
|
327
|
+
JetStream,
|
|
328
|
+
KV: KV2,
|
|
329
|
+
ObjectStore: ObjectStore2,
|
|
330
|
+
natsConnected,
|
|
331
|
+
natsError,
|
|
332
|
+
request,
|
|
333
|
+
publish,
|
|
334
|
+
subscribe,
|
|
335
|
+
parseJson,
|
|
336
|
+
parseString,
|
|
337
|
+
encodePayLoad,
|
|
338
|
+
loading,
|
|
339
|
+
retry,
|
|
340
|
+
retryCount,
|
|
341
|
+
isRetrying
|
|
342
|
+
};
|
|
343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NatsContext.Provider, { value: contextValue, children });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// utils/nats.ts
|
|
347
|
+
function stringToReadableStream(str) {
|
|
348
|
+
let currentOffset = 0;
|
|
349
|
+
const encoder = new TextEncoder();
|
|
350
|
+
const uint8Array = encoder.encode(str);
|
|
351
|
+
return new ReadableStream({
|
|
352
|
+
pull(controller) {
|
|
353
|
+
const chunkSize = 1;
|
|
354
|
+
const start = currentOffset;
|
|
355
|
+
const end = start + chunkSize <= uint8Array.length ? start + chunkSize : uint8Array.length;
|
|
356
|
+
controller.enqueue(uint8Array.slice(start, end));
|
|
357
|
+
currentOffset = end;
|
|
358
|
+
if (currentOffset == uint8Array.length) {
|
|
359
|
+
controller.close();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async function readStream(stream) {
|
|
365
|
+
const reader = stream.getReader();
|
|
366
|
+
const chunks = [];
|
|
367
|
+
let totalLength = 0;
|
|
368
|
+
while (true) {
|
|
369
|
+
const { done, value } = await reader.read();
|
|
370
|
+
if (done) break;
|
|
371
|
+
chunks.push(value);
|
|
372
|
+
totalLength += value.length;
|
|
373
|
+
}
|
|
374
|
+
const result = new Uint8Array(totalLength);
|
|
375
|
+
let offset = 0;
|
|
376
|
+
for (const chunk of chunks) {
|
|
377
|
+
result.set(chunk, offset);
|
|
378
|
+
offset += chunk.length;
|
|
379
|
+
}
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
382
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
383
|
+
0 && (module.exports = {
|
|
384
|
+
NATSProvider,
|
|
385
|
+
NatsContext,
|
|
386
|
+
initialNATS,
|
|
387
|
+
readStream,
|
|
388
|
+
stringToReadableStream,
|
|
389
|
+
useNATS,
|
|
390
|
+
useNatsContext
|
|
391
|
+
});
|
|
392
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../index.tsx","../context/nats-context.ts","../context/nats-provider.tsx","../hooks/use-nats.ts","../utils/nats.ts"],"sourcesContent":["// export * from \"./consts\";\nexport * from \"./context\";\nexport * from \"./hooks\";\n// export * from \"./jobs\";\n// export * from \"./models\";\nexport * from \"./types\";\nexport * from \"./utils\";\n// export * from \"./client-types\";\n","\"use client\";\n\nimport { KV, ObjectStore } from \"nats.ws\";\nimport { createContext, useContext } from \"react\";\nimport { NATSContextType } from \"../types/nats\";\n\nexport const initialNATS: NATSContextType = {\n nats: undefined,\n JetStream: () => null as any,\n KV: async (bucket: string) => Promise.resolve({} as KV),\n ObjectStore: async (bucket: string) => Promise.resolve({} as ObjectStore),\n natsConnected: false,\n natsError: null,\n request: <R, S>(topic: string, data: R) => Promise.resolve<S>({} as S),\n publish: <T>(topic: string, data: T) => Promise.resolve(),\n subscribe: <T>(topic: string, callback: (data: T | Error) => void) =>\n Promise.resolve(),\n parseJson: <T>(data: Uint8Array) => JSON.parse(data.toString()),\n parseString: (data: Uint8Array) => data.toString(),\n encodePayLoad: (data: unknown) =>\n new TextEncoder().encode(JSON.stringify(data)),\n loading: false,\n retry: () => {},\n retryCount: 0,\n isRetrying: false,\n};\n\nexport const NatsContext = createContext(initialNATS);\n\nexport const useNatsContext = () => useContext(NatsContext);\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useNATS } from \"../hooks\";\nimport { NATSContextType } from \"../types\";\nimport { NatsContext } from \"./nats-context\";\n\ntype NATSProviderProps = {\n children: React.ReactNode;\n apiEndpoint: string;\n};\n\nexport function NATSProvider(props: NATSProviderProps) {\n const { children, apiEndpoint } = props;\n\n const {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n retry,\n retryCount,\n isRetrying,\n } = useNATS(apiEndpoint);\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n setReady(true);\n }, []);\n\n if (!ready) {\n return null;\n }\n\n const contextValue: NATSContextType = {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n retry,\n retryCount,\n isRetrying,\n };\n\n return (\n <NatsContext.Provider value={contextValue}>{children}</NatsContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n JSONCodec,\n JetStreamClient,\n KV,\n NatsConnection,\n ObjectStore,\n StringCodec,\n connect,\n headers,\n jwtAuthenticator,\n} from \"nats.ws\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nconst TIMEOUT = 900000000;\nconst AUTH_FETCH_TIMEOUT = 10000; // 10 seconds for auth fetch\nconst MAX_RETRIES = 5;\nconst INITIAL_RETRY_DELAY = 1000; // 1 second\n\nexport const useNATS = (authApiUrl: string) => {\n const [nats, setNATS] = useState<NatsConnection | undefined>(undefined);\n const [natsConnected, setNATSConnected] = useState(false);\n const [natsError, setNATSError] = useState<any>(undefined);\n const [loading, setLoading] = useState(false);\n const [retryCount, setRetryCount] = useState(0);\n const [isRetrying, setIsRetrying] = useState(false);\n\n const connectionRef = useRef<NatsConnection | null>(null);\n const retryTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isConnectingRef = useRef(false);\n const isMountedRef = useRef(true);\n\n const connectNATS = useCallback(\n async (attempt: number = 0) => {\n // Prevent concurrent connection attempts\n if (isConnectingRef.current || connectionRef.current) {\n return;\n }\n\n isConnectingRef.current = true;\n setLoading(true);\n setNATSError(undefined);\n\n if (attempt > 0) {\n setIsRetrying(true);\n setRetryCount(attempt);\n }\n\n try {\n // Fetch auth with timeout\n const controller = new AbortController();\n const fetchTimeout = setTimeout(\n () => controller.abort(),\n AUTH_FETCH_TIMEOUT\n );\n\n const resp = await fetch(authApiUrl, { signal: controller.signal });\n clearTimeout(fetchTimeout);\n\n if (!resp.ok) {\n throw new Error(`Auth fetch failed: ${resp.status}`);\n }\n\n const { jwt, natsUrl } = await resp.json();\n\n const authenticator = jwtAuthenticator(jwt);\n\n const nc = await connect({\n servers: natsUrl,\n authenticator,\n timeout: TIMEOUT,\n reconnect: true,\n maxReconnectAttempts: -1, // Unlimited reconnect attempts\n reconnectTimeWait: 2000, // Wait 2 seconds between reconnect attempts\n });\n\n if (!isMountedRef.current) {\n await nc.close();\n return;\n }\n\n connectionRef.current = nc;\n setNATS(nc);\n setNATSConnected(true);\n setIsRetrying(false);\n setRetryCount(0);\n isConnectingRef.current = false;\n setLoading(false);\n\n console.log(\"NATS connected:\", natsUrl);\n\n // Monitor connection status\n (async () => {\n for await (const status of nc.status()) {\n if (!isMountedRef.current) break;\n\n if (status.type === \"disconnect\") {\n console.log(\"NATS disconnected, will auto-reconnect...\");\n setNATSConnected(false);\n } else if (status.type === \"reconnect\") {\n console.log(\"NATS reconnected\");\n setNATSConnected(true);\n } else if (status.type === \"error\") {\n console.error(\"NATS error:\", status.data);\n }\n }\n })();\n } catch (error: any) {\n isConnectingRef.current = false;\n setLoading(false);\n\n if (!isMountedRef.current) return;\n\n const errorMessage =\n error.name === \"AbortError\" ? \"Auth request timed out\" : error;\n console.error(\n `NATS connection failed (attempt ${attempt + 1}/${MAX_RETRIES}):`,\n errorMessage\n );\n\n if (attempt < MAX_RETRIES - 1) {\n // Exponential backoff: 1s, 2s, 4s, 8s, 16s\n const delay = INITIAL_RETRY_DELAY * Math.pow(2, attempt);\n console.log(`Retrying NATS connection in ${delay / 1000}s...`);\n\n retryTimeoutRef.current = setTimeout(() => {\n if (isMountedRef.current) {\n connectNATS(attempt + 1);\n }\n }, delay);\n } else {\n // Max retries reached\n setNATSError(error);\n setIsRetrying(false);\n console.error(\"NATS connection failed after max retries\");\n }\n }\n },\n [authApiUrl]\n );\n\n // Manual retry function exposed to consumers\n const retry = useCallback(() => {\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n connectionRef.current = null;\n isConnectingRef.current = false;\n setNATSError(undefined);\n connectNATS(0);\n }, [connectNATS]);\n\n useEffect(() => {\n isMountedRef.current = true;\n connectNATS(0);\n\n return () => {\n isMountedRef.current = false;\n\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n\n if (connectionRef.current) {\n connectionRef.current.close();\n connectionRef.current = null;\n }\n };\n }, [connectNATS]);\n\n async function request<R, S>(\n topic: string,\n data: R,\n headersObj: object = {}\n ): Promise<S> {\n if (!nats || !natsConnected) throw new Error(\"nats not connected !!\");\n\n const h = headers();\n Object.entries(headersObj).forEach(([key, value]) => {\n if (!value) return;\n h.append(key, value.toString());\n });\n\n const reqJC = JSONCodec<R>();\n const resJC = JSONCodec<S>();\n\n try {\n const msg = await nats.request(topic, reqJC.encode(data), {\n timeout: TIMEOUT,\n headers: h,\n });\n return resJC.decode(msg.data);\n } catch (error: any) {\n throw error;\n }\n }\n\n function parseJson<T>(data: Uint8Array): T {\n const jc = JSONCodec<T>();\n try {\n return jc.decode(data) as unknown as T;\n } catch (error: any) {\n throw error;\n }\n }\n\n function parseString(data: Uint8Array): string {\n const sc = StringCodec();\n try {\n return sc.decode(data);\n } catch (error: any) {\n throw error;\n }\n }\n\n // publish data asynchronously\n async function publish(topic: string, data: any, headersObj: object = {}) {\n if (!nats || !natsConnected) {\n console.log(\"nats not connected !!\");\n return;\n }\n\n // console.time(\"publish: \" + topic);\n const jc = JSONCodec();\n\n const h = headers();\n\n for (const [key, value] of Object.entries(headersObj)) {\n h.append(key, value);\n }\n\n nats.publish(topic, jc.encode(data), {\n headers: h,\n });\n // console.timeEnd(\"publish: \" + topic);\n }\n\n function encodePayLoad(data: unknown): Uint8Array {\n const jc = JSONCodec();\n return jc.encode(data);\n }\n\n async function subscribe<S>(\n topic: string,\n callbackFn: (data: S | Error) => void\n ) {\n if (!nats || !natsConnected) {\n console.log(\"nats not connected !!\");\n return;\n }\n\n nats.subscribe(topic, {\n callback: (err, msg) => {\n const jc = JSONCodec<S>();\n const data = jc.decode(msg.data);\n\n if (err) {\n callbackFn(err);\n return;\n }\n\n callbackFn(data);\n },\n });\n }\n\n function JetStream(): JetStreamClient {\n if (!nats || !natsConnected) {\n throw new Error(\"nats not connected !!\");\n }\n\n return nats.jetstream();\n }\n\n // todo: move to a separate hook\n async function KV(bucket: string): Promise<KV> {\n if (!nats || !natsConnected) {\n throw new Error(\"nats not connected !!\");\n }\n const js = JetStream();\n\n // if (js instanceof Error) {\n // throw js;\n // }\n\n return js.views.kv(bucket);\n }\n\n // todo: move to a separate hook\n async function ObjectStore(bucket: string): Promise<ObjectStore> {\n const js = JetStream();\n\n return js.views.os(bucket);\n }\n\n return {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n // New retry-related properties\n retry,\n retryCount,\n isRetrying,\n };\n};\n","export function stringToReadableStream(str: string) {\n let currentOffset = 0;\n const encoder = new TextEncoder(); // this is used to convert a string into Uint8Array\n const uint8Array = encoder.encode(str);\n\n return new ReadableStream({\n pull(controller) {\n // this method is called when the stream's internal queue is not full\n const chunkSize = 1; // adjust as per your needs\n const start = currentOffset;\n const end =\n start + chunkSize <= uint8Array.length\n ? start + chunkSize\n : uint8Array.length;\n\n controller.enqueue(uint8Array.slice(start, end)); // put data into the stream's internal queue\n\n currentOffset = end;\n if (currentOffset == uint8Array.length) {\n controller.close(); // close the stream if we've put all the data into the stream's internal queue\n }\n },\n });\n}\n\nexport async function readStream(\n stream: ReadableStream<Uint8Array>\n): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLength += value.length;\n }\n\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n "],"mappings":"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","names":["import_react","import_react","KV","ObjectStore","KV","ObjectStore"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// context/nats-context.ts
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
var initialNATS = {
|
|
4
|
+
nats: void 0,
|
|
5
|
+
JetStream: () => null,
|
|
6
|
+
KV: async (bucket) => Promise.resolve({}),
|
|
7
|
+
ObjectStore: async (bucket) => Promise.resolve({}),
|
|
8
|
+
natsConnected: false,
|
|
9
|
+
natsError: null,
|
|
10
|
+
request: (topic, data) => Promise.resolve({}),
|
|
11
|
+
publish: (topic, data) => Promise.resolve(),
|
|
12
|
+
subscribe: (topic, callback) => Promise.resolve(),
|
|
13
|
+
parseJson: (data) => JSON.parse(data.toString()),
|
|
14
|
+
parseString: (data) => data.toString(),
|
|
15
|
+
encodePayLoad: (data) => new TextEncoder().encode(JSON.stringify(data)),
|
|
16
|
+
loading: false,
|
|
17
|
+
retry: () => {
|
|
18
|
+
},
|
|
19
|
+
retryCount: 0,
|
|
20
|
+
isRetrying: false
|
|
21
|
+
};
|
|
22
|
+
var NatsContext = createContext(initialNATS);
|
|
23
|
+
var useNatsContext = () => useContext(NatsContext);
|
|
24
|
+
|
|
25
|
+
// context/nats-provider.tsx
|
|
26
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
27
|
+
|
|
28
|
+
// hooks/use-nats.ts
|
|
29
|
+
import {
|
|
30
|
+
JSONCodec,
|
|
31
|
+
StringCodec,
|
|
32
|
+
connect,
|
|
33
|
+
headers,
|
|
34
|
+
jwtAuthenticator
|
|
35
|
+
} from "nats.ws";
|
|
36
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
37
|
+
var TIMEOUT = 9e8;
|
|
38
|
+
var AUTH_FETCH_TIMEOUT = 1e4;
|
|
39
|
+
var MAX_RETRIES = 5;
|
|
40
|
+
var INITIAL_RETRY_DELAY = 1e3;
|
|
41
|
+
var useNATS = (authApiUrl) => {
|
|
42
|
+
const [nats, setNATS] = useState(void 0);
|
|
43
|
+
const [natsConnected, setNATSConnected] = useState(false);
|
|
44
|
+
const [natsError, setNATSError] = useState(void 0);
|
|
45
|
+
const [loading, setLoading] = useState(false);
|
|
46
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
47
|
+
const [isRetrying, setIsRetrying] = useState(false);
|
|
48
|
+
const connectionRef = useRef(null);
|
|
49
|
+
const retryTimeoutRef = useRef(null);
|
|
50
|
+
const isConnectingRef = useRef(false);
|
|
51
|
+
const isMountedRef = useRef(true);
|
|
52
|
+
const connectNATS = useCallback(
|
|
53
|
+
async (attempt = 0) => {
|
|
54
|
+
if (isConnectingRef.current || connectionRef.current) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
isConnectingRef.current = true;
|
|
58
|
+
setLoading(true);
|
|
59
|
+
setNATSError(void 0);
|
|
60
|
+
if (attempt > 0) {
|
|
61
|
+
setIsRetrying(true);
|
|
62
|
+
setRetryCount(attempt);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
const fetchTimeout = setTimeout(
|
|
67
|
+
() => controller.abort(),
|
|
68
|
+
AUTH_FETCH_TIMEOUT
|
|
69
|
+
);
|
|
70
|
+
const resp = await fetch(authApiUrl, { signal: controller.signal });
|
|
71
|
+
clearTimeout(fetchTimeout);
|
|
72
|
+
if (!resp.ok) {
|
|
73
|
+
throw new Error(`Auth fetch failed: ${resp.status}`);
|
|
74
|
+
}
|
|
75
|
+
const { jwt, natsUrl } = await resp.json();
|
|
76
|
+
const authenticator = jwtAuthenticator(jwt);
|
|
77
|
+
const nc = await connect({
|
|
78
|
+
servers: natsUrl,
|
|
79
|
+
authenticator,
|
|
80
|
+
timeout: TIMEOUT,
|
|
81
|
+
reconnect: true,
|
|
82
|
+
maxReconnectAttempts: -1,
|
|
83
|
+
// Unlimited reconnect attempts
|
|
84
|
+
reconnectTimeWait: 2e3
|
|
85
|
+
// Wait 2 seconds between reconnect attempts
|
|
86
|
+
});
|
|
87
|
+
if (!isMountedRef.current) {
|
|
88
|
+
await nc.close();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
connectionRef.current = nc;
|
|
92
|
+
setNATS(nc);
|
|
93
|
+
setNATSConnected(true);
|
|
94
|
+
setIsRetrying(false);
|
|
95
|
+
setRetryCount(0);
|
|
96
|
+
isConnectingRef.current = false;
|
|
97
|
+
setLoading(false);
|
|
98
|
+
console.log("NATS connected:", natsUrl);
|
|
99
|
+
(async () => {
|
|
100
|
+
for await (const status of nc.status()) {
|
|
101
|
+
if (!isMountedRef.current) break;
|
|
102
|
+
if (status.type === "disconnect") {
|
|
103
|
+
console.log("NATS disconnected, will auto-reconnect...");
|
|
104
|
+
setNATSConnected(false);
|
|
105
|
+
} else if (status.type === "reconnect") {
|
|
106
|
+
console.log("NATS reconnected");
|
|
107
|
+
setNATSConnected(true);
|
|
108
|
+
} else if (status.type === "error") {
|
|
109
|
+
console.error("NATS error:", status.data);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
})();
|
|
113
|
+
} catch (error) {
|
|
114
|
+
isConnectingRef.current = false;
|
|
115
|
+
setLoading(false);
|
|
116
|
+
if (!isMountedRef.current) return;
|
|
117
|
+
const errorMessage = error.name === "AbortError" ? "Auth request timed out" : error;
|
|
118
|
+
console.error(
|
|
119
|
+
`NATS connection failed (attempt ${attempt + 1}/${MAX_RETRIES}):`,
|
|
120
|
+
errorMessage
|
|
121
|
+
);
|
|
122
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
123
|
+
const delay = INITIAL_RETRY_DELAY * Math.pow(2, attempt);
|
|
124
|
+
console.log(`Retrying NATS connection in ${delay / 1e3}s...`);
|
|
125
|
+
retryTimeoutRef.current = setTimeout(() => {
|
|
126
|
+
if (isMountedRef.current) {
|
|
127
|
+
connectNATS(attempt + 1);
|
|
128
|
+
}
|
|
129
|
+
}, delay);
|
|
130
|
+
} else {
|
|
131
|
+
setNATSError(error);
|
|
132
|
+
setIsRetrying(false);
|
|
133
|
+
console.error("NATS connection failed after max retries");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
[authApiUrl]
|
|
138
|
+
);
|
|
139
|
+
const retry = useCallback(() => {
|
|
140
|
+
if (retryTimeoutRef.current) {
|
|
141
|
+
clearTimeout(retryTimeoutRef.current);
|
|
142
|
+
}
|
|
143
|
+
connectionRef.current = null;
|
|
144
|
+
isConnectingRef.current = false;
|
|
145
|
+
setNATSError(void 0);
|
|
146
|
+
connectNATS(0);
|
|
147
|
+
}, [connectNATS]);
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
isMountedRef.current = true;
|
|
150
|
+
connectNATS(0);
|
|
151
|
+
return () => {
|
|
152
|
+
isMountedRef.current = false;
|
|
153
|
+
if (retryTimeoutRef.current) {
|
|
154
|
+
clearTimeout(retryTimeoutRef.current);
|
|
155
|
+
}
|
|
156
|
+
if (connectionRef.current) {
|
|
157
|
+
connectionRef.current.close();
|
|
158
|
+
connectionRef.current = null;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}, [connectNATS]);
|
|
162
|
+
async function request(topic, data, headersObj = {}) {
|
|
163
|
+
if (!nats || !natsConnected) throw new Error("nats not connected !!");
|
|
164
|
+
const h = headers();
|
|
165
|
+
Object.entries(headersObj).forEach(([key, value]) => {
|
|
166
|
+
if (!value) return;
|
|
167
|
+
h.append(key, value.toString());
|
|
168
|
+
});
|
|
169
|
+
const reqJC = JSONCodec();
|
|
170
|
+
const resJC = JSONCodec();
|
|
171
|
+
try {
|
|
172
|
+
const msg = await nats.request(topic, reqJC.encode(data), {
|
|
173
|
+
timeout: TIMEOUT,
|
|
174
|
+
headers: h
|
|
175
|
+
});
|
|
176
|
+
return resJC.decode(msg.data);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function parseJson(data) {
|
|
182
|
+
const jc = JSONCodec();
|
|
183
|
+
try {
|
|
184
|
+
return jc.decode(data);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function parseString(data) {
|
|
190
|
+
const sc = StringCodec();
|
|
191
|
+
try {
|
|
192
|
+
return sc.decode(data);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function publish(topic, data, headersObj = {}) {
|
|
198
|
+
if (!nats || !natsConnected) {
|
|
199
|
+
console.log("nats not connected !!");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const jc = JSONCodec();
|
|
203
|
+
const h = headers();
|
|
204
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
205
|
+
h.append(key, value);
|
|
206
|
+
}
|
|
207
|
+
nats.publish(topic, jc.encode(data), {
|
|
208
|
+
headers: h
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function encodePayLoad(data) {
|
|
212
|
+
const jc = JSONCodec();
|
|
213
|
+
return jc.encode(data);
|
|
214
|
+
}
|
|
215
|
+
async function subscribe(topic, callbackFn) {
|
|
216
|
+
if (!nats || !natsConnected) {
|
|
217
|
+
console.log("nats not connected !!");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
nats.subscribe(topic, {
|
|
221
|
+
callback: (err, msg) => {
|
|
222
|
+
const jc = JSONCodec();
|
|
223
|
+
const data = jc.decode(msg.data);
|
|
224
|
+
if (err) {
|
|
225
|
+
callbackFn(err);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
callbackFn(data);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function JetStream() {
|
|
233
|
+
if (!nats || !natsConnected) {
|
|
234
|
+
throw new Error("nats not connected !!");
|
|
235
|
+
}
|
|
236
|
+
return nats.jetstream();
|
|
237
|
+
}
|
|
238
|
+
async function KV2(bucket) {
|
|
239
|
+
if (!nats || !natsConnected) {
|
|
240
|
+
throw new Error("nats not connected !!");
|
|
241
|
+
}
|
|
242
|
+
const js = JetStream();
|
|
243
|
+
return js.views.kv(bucket);
|
|
244
|
+
}
|
|
245
|
+
async function ObjectStore2(bucket) {
|
|
246
|
+
const js = JetStream();
|
|
247
|
+
return js.views.os(bucket);
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
nats,
|
|
251
|
+
JetStream,
|
|
252
|
+
KV: KV2,
|
|
253
|
+
ObjectStore: ObjectStore2,
|
|
254
|
+
natsConnected,
|
|
255
|
+
natsError,
|
|
256
|
+
request,
|
|
257
|
+
publish,
|
|
258
|
+
subscribe,
|
|
259
|
+
parseJson,
|
|
260
|
+
parseString,
|
|
261
|
+
encodePayLoad,
|
|
262
|
+
loading,
|
|
263
|
+
// New retry-related properties
|
|
264
|
+
retry,
|
|
265
|
+
retryCount,
|
|
266
|
+
isRetrying
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// context/nats-provider.tsx
|
|
271
|
+
import { jsx } from "react/jsx-runtime";
|
|
272
|
+
function NATSProvider(props) {
|
|
273
|
+
const { children, apiEndpoint } = props;
|
|
274
|
+
const {
|
|
275
|
+
nats,
|
|
276
|
+
JetStream,
|
|
277
|
+
KV: KV2,
|
|
278
|
+
ObjectStore: ObjectStore2,
|
|
279
|
+
natsConnected,
|
|
280
|
+
natsError,
|
|
281
|
+
request,
|
|
282
|
+
publish,
|
|
283
|
+
subscribe,
|
|
284
|
+
parseJson,
|
|
285
|
+
parseString,
|
|
286
|
+
encodePayLoad,
|
|
287
|
+
loading,
|
|
288
|
+
retry,
|
|
289
|
+
retryCount,
|
|
290
|
+
isRetrying
|
|
291
|
+
} = useNATS(apiEndpoint);
|
|
292
|
+
const [ready, setReady] = useState2(false);
|
|
293
|
+
useEffect2(() => {
|
|
294
|
+
setReady(true);
|
|
295
|
+
}, []);
|
|
296
|
+
if (!ready) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
const contextValue = {
|
|
300
|
+
nats,
|
|
301
|
+
JetStream,
|
|
302
|
+
KV: KV2,
|
|
303
|
+
ObjectStore: ObjectStore2,
|
|
304
|
+
natsConnected,
|
|
305
|
+
natsError,
|
|
306
|
+
request,
|
|
307
|
+
publish,
|
|
308
|
+
subscribe,
|
|
309
|
+
parseJson,
|
|
310
|
+
parseString,
|
|
311
|
+
encodePayLoad,
|
|
312
|
+
loading,
|
|
313
|
+
retry,
|
|
314
|
+
retryCount,
|
|
315
|
+
isRetrying
|
|
316
|
+
};
|
|
317
|
+
return /* @__PURE__ */ jsx(NatsContext.Provider, { value: contextValue, children });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// utils/nats.ts
|
|
321
|
+
function stringToReadableStream(str) {
|
|
322
|
+
let currentOffset = 0;
|
|
323
|
+
const encoder = new TextEncoder();
|
|
324
|
+
const uint8Array = encoder.encode(str);
|
|
325
|
+
return new ReadableStream({
|
|
326
|
+
pull(controller) {
|
|
327
|
+
const chunkSize = 1;
|
|
328
|
+
const start = currentOffset;
|
|
329
|
+
const end = start + chunkSize <= uint8Array.length ? start + chunkSize : uint8Array.length;
|
|
330
|
+
controller.enqueue(uint8Array.slice(start, end));
|
|
331
|
+
currentOffset = end;
|
|
332
|
+
if (currentOffset == uint8Array.length) {
|
|
333
|
+
controller.close();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async function readStream(stream) {
|
|
339
|
+
const reader = stream.getReader();
|
|
340
|
+
const chunks = [];
|
|
341
|
+
let totalLength = 0;
|
|
342
|
+
while (true) {
|
|
343
|
+
const { done, value } = await reader.read();
|
|
344
|
+
if (done) break;
|
|
345
|
+
chunks.push(value);
|
|
346
|
+
totalLength += value.length;
|
|
347
|
+
}
|
|
348
|
+
const result = new Uint8Array(totalLength);
|
|
349
|
+
let offset = 0;
|
|
350
|
+
for (const chunk of chunks) {
|
|
351
|
+
result.set(chunk, offset);
|
|
352
|
+
offset += chunk.length;
|
|
353
|
+
}
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
export {
|
|
357
|
+
NATSProvider,
|
|
358
|
+
NatsContext,
|
|
359
|
+
initialNATS,
|
|
360
|
+
readStream,
|
|
361
|
+
stringToReadableStream,
|
|
362
|
+
useNATS,
|
|
363
|
+
useNatsContext
|
|
364
|
+
};
|
|
365
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../context/nats-context.ts","../context/nats-provider.tsx","../hooks/use-nats.ts","../utils/nats.ts"],"sourcesContent":["\"use client\";\n\nimport { KV, ObjectStore } from \"nats.ws\";\nimport { createContext, useContext } from \"react\";\nimport { NATSContextType } from \"../types/nats\";\n\nexport const initialNATS: NATSContextType = {\n nats: undefined,\n JetStream: () => null as any,\n KV: async (bucket: string) => Promise.resolve({} as KV),\n ObjectStore: async (bucket: string) => Promise.resolve({} as ObjectStore),\n natsConnected: false,\n natsError: null,\n request: <R, S>(topic: string, data: R) => Promise.resolve<S>({} as S),\n publish: <T>(topic: string, data: T) => Promise.resolve(),\n subscribe: <T>(topic: string, callback: (data: T | Error) => void) =>\n Promise.resolve(),\n parseJson: <T>(data: Uint8Array) => JSON.parse(data.toString()),\n parseString: (data: Uint8Array) => data.toString(),\n encodePayLoad: (data: unknown) =>\n new TextEncoder().encode(JSON.stringify(data)),\n loading: false,\n retry: () => {},\n retryCount: 0,\n isRetrying: false,\n};\n\nexport const NatsContext = createContext(initialNATS);\n\nexport const useNatsContext = () => useContext(NatsContext);\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useNATS } from \"../hooks\";\nimport { NATSContextType } from \"../types\";\nimport { NatsContext } from \"./nats-context\";\n\ntype NATSProviderProps = {\n children: React.ReactNode;\n apiEndpoint: string;\n};\n\nexport function NATSProvider(props: NATSProviderProps) {\n const { children, apiEndpoint } = props;\n\n const {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n retry,\n retryCount,\n isRetrying,\n } = useNATS(apiEndpoint);\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n setReady(true);\n }, []);\n\n if (!ready) {\n return null;\n }\n\n const contextValue: NATSContextType = {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n retry,\n retryCount,\n isRetrying,\n };\n\n return (\n <NatsContext.Provider value={contextValue}>{children}</NatsContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n JSONCodec,\n JetStreamClient,\n KV,\n NatsConnection,\n ObjectStore,\n StringCodec,\n connect,\n headers,\n jwtAuthenticator,\n} from \"nats.ws\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nconst TIMEOUT = 900000000;\nconst AUTH_FETCH_TIMEOUT = 10000; // 10 seconds for auth fetch\nconst MAX_RETRIES = 5;\nconst INITIAL_RETRY_DELAY = 1000; // 1 second\n\nexport const useNATS = (authApiUrl: string) => {\n const [nats, setNATS] = useState<NatsConnection | undefined>(undefined);\n const [natsConnected, setNATSConnected] = useState(false);\n const [natsError, setNATSError] = useState<any>(undefined);\n const [loading, setLoading] = useState(false);\n const [retryCount, setRetryCount] = useState(0);\n const [isRetrying, setIsRetrying] = useState(false);\n\n const connectionRef = useRef<NatsConnection | null>(null);\n const retryTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isConnectingRef = useRef(false);\n const isMountedRef = useRef(true);\n\n const connectNATS = useCallback(\n async (attempt: number = 0) => {\n // Prevent concurrent connection attempts\n if (isConnectingRef.current || connectionRef.current) {\n return;\n }\n\n isConnectingRef.current = true;\n setLoading(true);\n setNATSError(undefined);\n\n if (attempt > 0) {\n setIsRetrying(true);\n setRetryCount(attempt);\n }\n\n try {\n // Fetch auth with timeout\n const controller = new AbortController();\n const fetchTimeout = setTimeout(\n () => controller.abort(),\n AUTH_FETCH_TIMEOUT\n );\n\n const resp = await fetch(authApiUrl, { signal: controller.signal });\n clearTimeout(fetchTimeout);\n\n if (!resp.ok) {\n throw new Error(`Auth fetch failed: ${resp.status}`);\n }\n\n const { jwt, natsUrl } = await resp.json();\n\n const authenticator = jwtAuthenticator(jwt);\n\n const nc = await connect({\n servers: natsUrl,\n authenticator,\n timeout: TIMEOUT,\n reconnect: true,\n maxReconnectAttempts: -1, // Unlimited reconnect attempts\n reconnectTimeWait: 2000, // Wait 2 seconds between reconnect attempts\n });\n\n if (!isMountedRef.current) {\n await nc.close();\n return;\n }\n\n connectionRef.current = nc;\n setNATS(nc);\n setNATSConnected(true);\n setIsRetrying(false);\n setRetryCount(0);\n isConnectingRef.current = false;\n setLoading(false);\n\n console.log(\"NATS connected:\", natsUrl);\n\n // Monitor connection status\n (async () => {\n for await (const status of nc.status()) {\n if (!isMountedRef.current) break;\n\n if (status.type === \"disconnect\") {\n console.log(\"NATS disconnected, will auto-reconnect...\");\n setNATSConnected(false);\n } else if (status.type === \"reconnect\") {\n console.log(\"NATS reconnected\");\n setNATSConnected(true);\n } else if (status.type === \"error\") {\n console.error(\"NATS error:\", status.data);\n }\n }\n })();\n } catch (error: any) {\n isConnectingRef.current = false;\n setLoading(false);\n\n if (!isMountedRef.current) return;\n\n const errorMessage =\n error.name === \"AbortError\" ? \"Auth request timed out\" : error;\n console.error(\n `NATS connection failed (attempt ${attempt + 1}/${MAX_RETRIES}):`,\n errorMessage\n );\n\n if (attempt < MAX_RETRIES - 1) {\n // Exponential backoff: 1s, 2s, 4s, 8s, 16s\n const delay = INITIAL_RETRY_DELAY * Math.pow(2, attempt);\n console.log(`Retrying NATS connection in ${delay / 1000}s...`);\n\n retryTimeoutRef.current = setTimeout(() => {\n if (isMountedRef.current) {\n connectNATS(attempt + 1);\n }\n }, delay);\n } else {\n // Max retries reached\n setNATSError(error);\n setIsRetrying(false);\n console.error(\"NATS connection failed after max retries\");\n }\n }\n },\n [authApiUrl]\n );\n\n // Manual retry function exposed to consumers\n const retry = useCallback(() => {\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n connectionRef.current = null;\n isConnectingRef.current = false;\n setNATSError(undefined);\n connectNATS(0);\n }, [connectNATS]);\n\n useEffect(() => {\n isMountedRef.current = true;\n connectNATS(0);\n\n return () => {\n isMountedRef.current = false;\n\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n\n if (connectionRef.current) {\n connectionRef.current.close();\n connectionRef.current = null;\n }\n };\n }, [connectNATS]);\n\n async function request<R, S>(\n topic: string,\n data: R,\n headersObj: object = {}\n ): Promise<S> {\n if (!nats || !natsConnected) throw new Error(\"nats not connected !!\");\n\n const h = headers();\n Object.entries(headersObj).forEach(([key, value]) => {\n if (!value) return;\n h.append(key, value.toString());\n });\n\n const reqJC = JSONCodec<R>();\n const resJC = JSONCodec<S>();\n\n try {\n const msg = await nats.request(topic, reqJC.encode(data), {\n timeout: TIMEOUT,\n headers: h,\n });\n return resJC.decode(msg.data);\n } catch (error: any) {\n throw error;\n }\n }\n\n function parseJson<T>(data: Uint8Array): T {\n const jc = JSONCodec<T>();\n try {\n return jc.decode(data) as unknown as T;\n } catch (error: any) {\n throw error;\n }\n }\n\n function parseString(data: Uint8Array): string {\n const sc = StringCodec();\n try {\n return sc.decode(data);\n } catch (error: any) {\n throw error;\n }\n }\n\n // publish data asynchronously\n async function publish(topic: string, data: any, headersObj: object = {}) {\n if (!nats || !natsConnected) {\n console.log(\"nats not connected !!\");\n return;\n }\n\n // console.time(\"publish: \" + topic);\n const jc = JSONCodec();\n\n const h = headers();\n\n for (const [key, value] of Object.entries(headersObj)) {\n h.append(key, value);\n }\n\n nats.publish(topic, jc.encode(data), {\n headers: h,\n });\n // console.timeEnd(\"publish: \" + topic);\n }\n\n function encodePayLoad(data: unknown): Uint8Array {\n const jc = JSONCodec();\n return jc.encode(data);\n }\n\n async function subscribe<S>(\n topic: string,\n callbackFn: (data: S | Error) => void\n ) {\n if (!nats || !natsConnected) {\n console.log(\"nats not connected !!\");\n return;\n }\n\n nats.subscribe(topic, {\n callback: (err, msg) => {\n const jc = JSONCodec<S>();\n const data = jc.decode(msg.data);\n\n if (err) {\n callbackFn(err);\n return;\n }\n\n callbackFn(data);\n },\n });\n }\n\n function JetStream(): JetStreamClient {\n if (!nats || !natsConnected) {\n throw new Error(\"nats not connected !!\");\n }\n\n return nats.jetstream();\n }\n\n // todo: move to a separate hook\n async function KV(bucket: string): Promise<KV> {\n if (!nats || !natsConnected) {\n throw new Error(\"nats not connected !!\");\n }\n const js = JetStream();\n\n // if (js instanceof Error) {\n // throw js;\n // }\n\n return js.views.kv(bucket);\n }\n\n // todo: move to a separate hook\n async function ObjectStore(bucket: string): Promise<ObjectStore> {\n const js = JetStream();\n\n return js.views.os(bucket);\n }\n\n return {\n nats,\n JetStream,\n KV,\n ObjectStore,\n natsConnected,\n natsError,\n request,\n publish,\n subscribe,\n parseJson,\n parseString,\n encodePayLoad,\n loading,\n // New retry-related properties\n retry,\n retryCount,\n isRetrying,\n };\n};\n","export function stringToReadableStream(str: string) {\n let currentOffset = 0;\n const encoder = new TextEncoder(); // this is used to convert a string into Uint8Array\n const uint8Array = encoder.encode(str);\n\n return new ReadableStream({\n pull(controller) {\n // this method is called when the stream's internal queue is not full\n const chunkSize = 1; // adjust as per your needs\n const start = currentOffset;\n const end =\n start + chunkSize <= uint8Array.length\n ? start + chunkSize\n : uint8Array.length;\n\n controller.enqueue(uint8Array.slice(start, end)); // put data into the stream's internal queue\n\n currentOffset = end;\n if (currentOffset == uint8Array.length) {\n controller.close(); // close the stream if we've put all the data into the stream's internal queue\n }\n },\n });\n}\n\nexport async function readStream(\n stream: ReadableStream<Uint8Array>\n): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLength += value.length;\n }\n\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n "],"mappings":"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","names":["useEffect","useState","KV","ObjectStore","KV","ObjectStore","useState","useEffect"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elqnt/nats",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NATS messaging integration for Eloquent platform",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"dev": "tsup --watch",
|
|
19
|
+
"clean": "rm -rf dist",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/Blazi-Commerce/eloquent-packages.git",
|
|
25
|
+
"directory": "packages/nats"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@elqnt/types": "^1.0.0",
|
|
29
|
+
"nats.ws": "^1.29.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@reduxjs/toolkit": "^2.0.0",
|
|
33
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
34
|
+
"react-redux": "^9.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@reduxjs/toolkit": "^2.3.0",
|
|
38
|
+
"@types/react": "^19.0.0",
|
|
39
|
+
"react": "^19.0.0",
|
|
40
|
+
"react-redux": "^9.1.2",
|
|
41
|
+
"tsup": "^8.0.0",
|
|
42
|
+
"typescript": "^5.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|