@calimero-network/mero-react 1.0.0-beta.1 → 1.0.2
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 +201 -125
- package/dist/index.cjs +248 -660
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -57
- package/dist/index.d.ts +61 -57
- package/dist/index.js +237 -657
- package/dist/index.js.map +1 -1
- package/package.json +23 -10
package/dist/index.cjs
CHANGED
|
@@ -3,10 +3,24 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var meroJs = require('@calimero-network/mero-js');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
var reactDom = require('react-dom');
|
|
7
6
|
|
|
8
7
|
// src/context/MeroContext.tsx
|
|
9
8
|
|
|
9
|
+
// src/types.ts
|
|
10
|
+
var AppMode = /* @__PURE__ */ ((AppMode2) => {
|
|
11
|
+
AppMode2["SingleContext"] = "single-context";
|
|
12
|
+
AppMode2["MultiContext"] = "multi-context";
|
|
13
|
+
AppMode2["Admin"] = "admin";
|
|
14
|
+
return AppMode2;
|
|
15
|
+
})(AppMode || {});
|
|
16
|
+
var ConnectionType = /* @__PURE__ */ ((ConnectionType2) => {
|
|
17
|
+
ConnectionType2["RemoteAndLocal"] = "remote-and-local";
|
|
18
|
+
ConnectionType2["Remote"] = "remote";
|
|
19
|
+
ConnectionType2["Local"] = "local";
|
|
20
|
+
ConnectionType2["Custom"] = "custom";
|
|
21
|
+
return ConnectionType2;
|
|
22
|
+
})(ConnectionType || {});
|
|
23
|
+
|
|
10
24
|
// src/storage/index.ts
|
|
11
25
|
var STORAGE_KEYS = {
|
|
12
26
|
ACCESS_TOKEN: "mero:access_token",
|
|
@@ -14,20 +28,25 @@ var STORAGE_KEYS = {
|
|
|
14
28
|
EXPIRES_AT: "mero:expires_at",
|
|
15
29
|
NODE_URL: "mero:node_url",
|
|
16
30
|
APPLICATION_ID: "mero:application_id",
|
|
17
|
-
CONTEXT_ID: "mero:context_id"
|
|
31
|
+
CONTEXT_ID: "mero:context_id",
|
|
32
|
+
CONTEXT_IDENTITY: "mero:context_identity"
|
|
18
33
|
};
|
|
34
|
+
var _storageAvailable = null;
|
|
19
35
|
function isLocalStorageAvailable() {
|
|
36
|
+
if (_storageAvailable !== null) return _storageAvailable;
|
|
20
37
|
try {
|
|
21
38
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
39
|
+
_storageAvailable = false;
|
|
22
40
|
return false;
|
|
23
41
|
}
|
|
24
42
|
const testKey = "__mero_test__";
|
|
25
43
|
localStorage.setItem(testKey, "test");
|
|
26
44
|
localStorage.removeItem(testKey);
|
|
27
|
-
|
|
45
|
+
_storageAvailable = true;
|
|
28
46
|
} catch {
|
|
29
|
-
|
|
47
|
+
_storageAvailable = false;
|
|
30
48
|
}
|
|
49
|
+
return _storageAvailable;
|
|
31
50
|
}
|
|
32
51
|
var localStorageTokenStorage = {
|
|
33
52
|
async get() {
|
|
@@ -108,46 +127,37 @@ function setContextId(id) {
|
|
|
108
127
|
if (!isLocalStorageAvailable()) return;
|
|
109
128
|
localStorage.setItem(STORAGE_KEYS.CONTEXT_ID, id);
|
|
110
129
|
}
|
|
130
|
+
function clearContextId() {
|
|
131
|
+
if (!isLocalStorageAvailable()) return;
|
|
132
|
+
localStorage.removeItem(STORAGE_KEYS.CONTEXT_ID);
|
|
133
|
+
}
|
|
134
|
+
function getContextIdentity() {
|
|
135
|
+
if (!isLocalStorageAvailable()) return null;
|
|
136
|
+
return localStorage.getItem(STORAGE_KEYS.CONTEXT_IDENTITY);
|
|
137
|
+
}
|
|
138
|
+
function setContextIdentity(id) {
|
|
139
|
+
if (!isLocalStorageAvailable()) return;
|
|
140
|
+
localStorage.setItem(STORAGE_KEYS.CONTEXT_IDENTITY, id);
|
|
141
|
+
}
|
|
142
|
+
function clearContextIdentity() {
|
|
143
|
+
if (!isLocalStorageAvailable()) return;
|
|
144
|
+
localStorage.removeItem(STORAGE_KEYS.CONTEXT_IDENTITY);
|
|
145
|
+
}
|
|
111
146
|
function clearAllStorage() {
|
|
112
147
|
if (!isLocalStorageAvailable()) return;
|
|
113
148
|
Object.values(STORAGE_KEYS).forEach((key) => {
|
|
114
149
|
localStorage.removeItem(key);
|
|
115
150
|
});
|
|
116
151
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
var
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
ConnectionType2["RemoteAndLocal"] = "remote-and-local";
|
|
127
|
-
ConnectionType2["Remote"] = "remote";
|
|
128
|
-
ConnectionType2["Local"] = "local";
|
|
129
|
-
ConnectionType2["Custom"] = "custom";
|
|
130
|
-
return ConnectionType2;
|
|
131
|
-
})(ConnectionType || {});
|
|
132
|
-
var EventStreamMode = /* @__PURE__ */ ((EventStreamMode2) => {
|
|
133
|
-
EventStreamMode2["WebSocket"] = "websocket";
|
|
134
|
-
EventStreamMode2["SSE"] = "sse";
|
|
135
|
-
return EventStreamMode2;
|
|
136
|
-
})(EventStreamMode || {});
|
|
137
|
-
var defaultContextValue = {
|
|
138
|
-
mero: null,
|
|
139
|
-
isAuthenticated: false,
|
|
140
|
-
isOnline: true,
|
|
141
|
-
nodeUrl: null,
|
|
142
|
-
applicationId: null,
|
|
143
|
-
contextId: null,
|
|
144
|
-
connectToNode: () => {
|
|
145
|
-
},
|
|
146
|
-
logout: () => {
|
|
147
|
-
},
|
|
148
|
-
isLoading: true
|
|
149
|
-
};
|
|
150
|
-
var MeroContext = react.createContext(defaultContextValue);
|
|
152
|
+
var MeroContext = react.createContext(null);
|
|
153
|
+
var isBrowser = typeof window !== "undefined";
|
|
154
|
+
var _tokenStore = null;
|
|
155
|
+
function getTokenStore() {
|
|
156
|
+
if (!_tokenStore) {
|
|
157
|
+
_tokenStore = new meroJs.LocalStorageTokenStore();
|
|
158
|
+
}
|
|
159
|
+
return _tokenStore;
|
|
160
|
+
}
|
|
151
161
|
function getPermissionsForMode(mode) {
|
|
152
162
|
switch (mode) {
|
|
153
163
|
case "single-context" /* SingleContext */:
|
|
@@ -160,27 +170,20 @@ function getPermissionsForMode(mode) {
|
|
|
160
170
|
throw new Error(`Unsupported application mode: ${mode}`);
|
|
161
171
|
}
|
|
162
172
|
}
|
|
163
|
-
function
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (params.registryUrl) {
|
|
174
|
-
authParams.append("registry-url", params.registryUrl);
|
|
173
|
+
function parseJwtExpiry(token) {
|
|
174
|
+
try {
|
|
175
|
+
const parts = token.split(".");
|
|
176
|
+
if (parts.length === 3) {
|
|
177
|
+
let b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
178
|
+
while (b64.length % 4) b64 += "=";
|
|
179
|
+
const payload = JSON.parse(atob(b64));
|
|
180
|
+
if (payload.exp && payload.exp > 0) {
|
|
181
|
+
return payload.exp * 1e3;
|
|
182
|
+
}
|
|
175
183
|
}
|
|
176
|
-
}
|
|
177
|
-
authParams.append("application-id", params.applicationId);
|
|
178
|
-
}
|
|
179
|
-
if (params.applicationPath) {
|
|
180
|
-
authParams.append("application-path", params.applicationPath);
|
|
184
|
+
} catch {
|
|
181
185
|
}
|
|
182
|
-
|
|
183
|
-
window.location.href = `${params.nodeUrl}/auth/login?${authParams.toString()}`;
|
|
186
|
+
return Date.now() + 36e5;
|
|
184
187
|
}
|
|
185
188
|
function MeroProvider({
|
|
186
189
|
children,
|
|
@@ -188,8 +191,6 @@ function MeroProvider({
|
|
|
188
191
|
packageName,
|
|
189
192
|
packageVersion,
|
|
190
193
|
registryUrl,
|
|
191
|
-
applicationId: propApplicationId,
|
|
192
|
-
applicationPath,
|
|
193
194
|
timeoutMs = 3e4
|
|
194
195
|
}) {
|
|
195
196
|
const [mero, setMero] = react.useState(null);
|
|
@@ -198,15 +199,23 @@ function MeroProvider({
|
|
|
198
199
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
199
200
|
const [nodeUrl, setNodeUrlState] = react.useState(() => getNodeUrl());
|
|
200
201
|
const [applicationId, setApplicationIdState] = react.useState(
|
|
201
|
-
() => getApplicationId() ||
|
|
202
|
+
() => getApplicationId() || null
|
|
202
203
|
);
|
|
203
204
|
const [contextId, setContextIdState] = react.useState(() => getContextId());
|
|
205
|
+
const [contextIdentity, setContextIdentityState] = react.useState(() => getContextIdentity());
|
|
204
206
|
const meroRef = react.useRef(null);
|
|
207
|
+
const callbackRef = react.useRef(void 0);
|
|
208
|
+
if (callbackRef.current === void 0 && isBrowser) {
|
|
209
|
+
callbackRef.current = meroJs.parseAuthCallback(window.location.href);
|
|
210
|
+
}
|
|
205
211
|
const createMeroInstance = react.useCallback(
|
|
206
212
|
(url) => {
|
|
213
|
+
if (meroRef.current) {
|
|
214
|
+
meroRef.current.close();
|
|
215
|
+
}
|
|
207
216
|
const instance = new meroJs.MeroJs({
|
|
208
217
|
baseUrl: url,
|
|
209
|
-
|
|
218
|
+
tokenStore: getTokenStore(),
|
|
210
219
|
timeoutMs
|
|
211
220
|
});
|
|
212
221
|
meroRef.current = instance;
|
|
@@ -216,127 +225,35 @@ function MeroProvider({
|
|
|
216
225
|
);
|
|
217
226
|
const checkAuth = react.useCallback(async (instance) => {
|
|
218
227
|
try {
|
|
219
|
-
await instance.admin.
|
|
228
|
+
await instance.admin.getContexts();
|
|
220
229
|
return true;
|
|
221
230
|
} catch {
|
|
222
231
|
return false;
|
|
223
232
|
}
|
|
224
233
|
}, []);
|
|
225
|
-
const processAuthCallback = react.useCallback(() => {
|
|
226
|
-
const url = new URL(window.location.href);
|
|
227
|
-
const rawHash = url.hash;
|
|
228
|
-
const hash = rawHash.slice(1);
|
|
229
|
-
console.log("========== AUTH CALLBACK DEBUG ==========");
|
|
230
|
-
console.log("Raw URL:", window.location.href);
|
|
231
|
-
console.log("Raw hash:", rawHash);
|
|
232
|
-
console.log("Hash (without #):", hash);
|
|
233
|
-
if (!hash) {
|
|
234
|
-
console.log("No hash found, skipping auth callback");
|
|
235
|
-
console.log("==========================================");
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
const params = new URLSearchParams(hash);
|
|
239
|
-
console.log("All hash params:");
|
|
240
|
-
for (const [key, value] of params.entries()) {
|
|
241
|
-
console.log(` ${key}: ${value.substring(0, 50)}${value.length > 50 ? "..." : ""}`);
|
|
242
|
-
}
|
|
243
|
-
console.log("==========================================");
|
|
244
|
-
const accessToken = params.get("access_token");
|
|
245
|
-
const refreshToken = params.get("refresh_token");
|
|
246
|
-
const appId = params.get("application_id") || params.get("applicationId") || params.get("app_id");
|
|
247
|
-
const ctxId = params.get("context_id") || params.get("contextId") || params.get("context");
|
|
248
|
-
const expiresIn = params.get("expires_in");
|
|
249
|
-
const nodeUrlParam = params.get("node_url") || params.get("nodeUrl") || params.get("node");
|
|
250
|
-
if (!accessToken || !refreshToken) return false;
|
|
251
|
-
if (nodeUrlParam) {
|
|
252
|
-
const decodedNodeUrl = decodeURIComponent(nodeUrlParam);
|
|
253
|
-
setNodeUrl(decodedNodeUrl);
|
|
254
|
-
setNodeUrlState(decodedNodeUrl);
|
|
255
|
-
console.log("[mero-react] SSO: Node URL from hash params:", decodedNodeUrl);
|
|
256
|
-
}
|
|
257
|
-
try {
|
|
258
|
-
const decodedAccess = decodeURIComponent(accessToken);
|
|
259
|
-
const decodedRefresh = decodeURIComponent(refreshToken);
|
|
260
|
-
let expiresAt = Date.now() + 36e5;
|
|
261
|
-
if (expiresIn) {
|
|
262
|
-
expiresAt = Date.now() + parseInt(expiresIn, 10) * 1e3;
|
|
263
|
-
} else {
|
|
264
|
-
try {
|
|
265
|
-
const parts = decodedAccess.split(".");
|
|
266
|
-
if (parts.length === 3) {
|
|
267
|
-
const payload = JSON.parse(atob(parts[1]));
|
|
268
|
-
if (payload.exp) {
|
|
269
|
-
expiresAt = payload.exp * 1e3;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
localStorageTokenStorage.set({
|
|
276
|
-
access_token: decodedAccess,
|
|
277
|
-
refresh_token: decodedRefresh,
|
|
278
|
-
expires_at: expiresAt
|
|
279
|
-
});
|
|
280
|
-
if (appId) {
|
|
281
|
-
setApplicationId(appId);
|
|
282
|
-
setApplicationIdState(appId);
|
|
283
|
-
}
|
|
284
|
-
if (ctxId) {
|
|
285
|
-
setContextId(ctxId);
|
|
286
|
-
setContextIdState(ctxId);
|
|
287
|
-
}
|
|
288
|
-
params.delete("access_token");
|
|
289
|
-
params.delete("refresh_token");
|
|
290
|
-
params.delete("application_id");
|
|
291
|
-
params.delete("applicationId");
|
|
292
|
-
params.delete("app_id");
|
|
293
|
-
params.delete("context_id");
|
|
294
|
-
params.delete("contextId");
|
|
295
|
-
params.delete("context");
|
|
296
|
-
params.delete("expires_in");
|
|
297
|
-
params.delete("node_url");
|
|
298
|
-
params.delete("nodeUrl");
|
|
299
|
-
params.delete("node");
|
|
300
|
-
const newHash = params.toString();
|
|
301
|
-
url.hash = newHash ? `#${newHash}` : "";
|
|
302
|
-
window.history.replaceState({}, document.title, url.toString());
|
|
303
|
-
console.log("[mero-react] Stored contextId:", ctxId, "applicationId:", appId);
|
|
304
|
-
return true;
|
|
305
|
-
} catch (e) {
|
|
306
|
-
console.error("[mero-react] Failed to process auth callback:", e);
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
}, []);
|
|
310
234
|
const connectToNode = react.useCallback(
|
|
311
235
|
(url) => {
|
|
236
|
+
if (!isBrowser) return;
|
|
312
237
|
setNodeUrl(url);
|
|
313
238
|
setNodeUrlState(url);
|
|
314
239
|
const callbackUrl = new URL(window.location.href);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
hashParams.delete("access_token");
|
|
318
|
-
hashParams.delete("refresh_token");
|
|
319
|
-
hashParams.delete("application_id");
|
|
320
|
-
callbackUrl.hash = hashParams.toString() ? `#${hashParams.toString()}` : "";
|
|
321
|
-
}
|
|
322
|
-
const permissions = getPermissionsForMode(mode);
|
|
323
|
-
redirectToAuthLogin({
|
|
324
|
-
nodeUrl: url,
|
|
240
|
+
callbackUrl.hash = "";
|
|
241
|
+
const loginUrl = meroJs.buildAuthLoginUrl(url, {
|
|
325
242
|
callbackUrl: callbackUrl.toString(),
|
|
326
|
-
permissions,
|
|
243
|
+
permissions: getPermissionsForMode(mode),
|
|
327
244
|
mode,
|
|
328
245
|
packageName,
|
|
329
246
|
packageVersion,
|
|
330
|
-
registryUrl
|
|
331
|
-
applicationId: propApplicationId,
|
|
332
|
-
applicationPath
|
|
247
|
+
registryUrl
|
|
333
248
|
});
|
|
249
|
+
window.location.href = loginUrl;
|
|
334
250
|
},
|
|
335
|
-
[mode, packageName, packageVersion, registryUrl
|
|
251
|
+
[mode, packageName, packageVersion, registryUrl]
|
|
336
252
|
);
|
|
337
|
-
const logout = react.useCallback(
|
|
253
|
+
const logout = react.useCallback(() => {
|
|
338
254
|
if (meroRef.current) {
|
|
339
|
-
|
|
255
|
+
meroRef.current.clearToken();
|
|
256
|
+
meroRef.current.close();
|
|
340
257
|
}
|
|
341
258
|
clearAllStorage();
|
|
342
259
|
setMero(null);
|
|
@@ -344,56 +261,90 @@ function MeroProvider({
|
|
|
344
261
|
setNodeUrlState(null);
|
|
345
262
|
setApplicationIdState(null);
|
|
346
263
|
setContextIdState(null);
|
|
264
|
+
setContextIdentityState(null);
|
|
347
265
|
meroRef.current = null;
|
|
348
266
|
}, []);
|
|
349
267
|
react.useEffect(() => {
|
|
268
|
+
let active = true;
|
|
350
269
|
const init = async () => {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
270
|
+
const callback = callbackRef.current;
|
|
271
|
+
if (callback) {
|
|
272
|
+
getTokenStore().setTokens({
|
|
273
|
+
access_token: callback.accessToken,
|
|
274
|
+
refresh_token: callback.refreshToken,
|
|
275
|
+
expires_at: parseJwtExpiry(callback.accessToken)
|
|
276
|
+
});
|
|
277
|
+
if (callback.applicationId) {
|
|
278
|
+
setApplicationId(callback.applicationId);
|
|
279
|
+
if (active) setApplicationIdState(callback.applicationId);
|
|
280
|
+
}
|
|
281
|
+
if (callback.contextId) {
|
|
282
|
+
setContextId(callback.contextId);
|
|
283
|
+
if (active) setContextIdState(callback.contextId);
|
|
284
|
+
}
|
|
285
|
+
if (callback.contextIdentity) {
|
|
286
|
+
setContextIdentity(callback.contextIdentity);
|
|
287
|
+
if (active) setContextIdentityState(callback.contextIdentity);
|
|
288
|
+
}
|
|
289
|
+
if (callback.nodeUrl) {
|
|
290
|
+
setNodeUrl(callback.nodeUrl);
|
|
291
|
+
if (active) setNodeUrlState(callback.nodeUrl);
|
|
292
|
+
}
|
|
293
|
+
if (isBrowser) {
|
|
294
|
+
window.history.replaceState({}, "", window.location.pathname + window.location.search);
|
|
295
|
+
}
|
|
296
|
+
callbackRef.current = null;
|
|
297
|
+
}
|
|
298
|
+
const savedUrl = callback?.nodeUrl || getNodeUrl();
|
|
359
299
|
if (!savedUrl) {
|
|
360
|
-
setIsLoading(false);
|
|
300
|
+
if (active) setIsLoading(false);
|
|
361
301
|
return;
|
|
362
302
|
}
|
|
363
303
|
const instance = createMeroInstance(savedUrl);
|
|
364
|
-
await instance.init();
|
|
365
304
|
const authed = await checkAuth(instance);
|
|
305
|
+
if (!active) return;
|
|
366
306
|
if (authed) {
|
|
367
307
|
setMero(instance);
|
|
368
308
|
setIsAuthenticated(true);
|
|
369
309
|
setIsOnline(true);
|
|
370
|
-
} else if (
|
|
310
|
+
} else if (callback) {
|
|
371
311
|
setMero(instance);
|
|
372
|
-
setIsAuthenticated(false);
|
|
373
312
|
}
|
|
374
313
|
setIsLoading(false);
|
|
375
314
|
};
|
|
376
|
-
init()
|
|
377
|
-
|
|
315
|
+
init().catch((err) => {
|
|
316
|
+
console.error("[MeroProvider] Initialization failed:", err);
|
|
317
|
+
if (active) setIsLoading(false);
|
|
318
|
+
});
|
|
319
|
+
return () => {
|
|
320
|
+
active = false;
|
|
321
|
+
};
|
|
322
|
+
}, [createMeroInstance, checkAuth]);
|
|
378
323
|
react.useEffect(() => {
|
|
379
324
|
if (!isAuthenticated || !meroRef.current) return;
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
325
|
+
let active = true;
|
|
326
|
+
const sse = meroRef.current.events;
|
|
327
|
+
const onConnect = () => {
|
|
328
|
+
if (active) setIsOnline(true);
|
|
329
|
+
};
|
|
330
|
+
const onError = (err) => {
|
|
331
|
+
if (!active) return;
|
|
332
|
+
setIsOnline(false);
|
|
333
|
+
if (err.message.includes("401")) {
|
|
334
|
+
logout();
|
|
388
335
|
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
336
|
+
};
|
|
337
|
+
sse.on("connect", onConnect);
|
|
338
|
+
sse.on("error", onError);
|
|
339
|
+
sse.connect().catch(() => {
|
|
340
|
+
if (active) setIsOnline(false);
|
|
341
|
+
});
|
|
342
|
+
return () => {
|
|
343
|
+
active = false;
|
|
344
|
+
sse.off("connect", onConnect);
|
|
345
|
+
sse.off("error", onError);
|
|
346
|
+
};
|
|
347
|
+
}, [isAuthenticated, mero]);
|
|
397
348
|
const contextValue = react.useMemo(
|
|
398
349
|
() => ({
|
|
399
350
|
mero,
|
|
@@ -402,512 +353,149 @@ function MeroProvider({
|
|
|
402
353
|
nodeUrl,
|
|
403
354
|
applicationId,
|
|
404
355
|
contextId,
|
|
356
|
+
contextIdentity,
|
|
405
357
|
connectToNode,
|
|
406
358
|
logout,
|
|
407
359
|
isLoading
|
|
408
360
|
}),
|
|
409
|
-
[mero, isAuthenticated, isOnline, nodeUrl, applicationId, contextId, connectToNode, logout, isLoading]
|
|
361
|
+
[mero, isAuthenticated, isOnline, nodeUrl, applicationId, contextId, contextIdentity, connectToNode, logout, isLoading]
|
|
410
362
|
);
|
|
411
363
|
return /* @__PURE__ */ jsxRuntime.jsx(MeroContext.Provider, { value: contextValue, children });
|
|
412
364
|
}
|
|
413
365
|
function useMero() {
|
|
414
366
|
const context = react.useContext(MeroContext);
|
|
415
|
-
if (context
|
|
367
|
+
if (!context) {
|
|
416
368
|
throw new Error("useMero must be used within a MeroProvider");
|
|
417
369
|
}
|
|
418
370
|
return context;
|
|
419
371
|
}
|
|
420
|
-
function
|
|
421
|
-
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
try {
|
|
425
|
-
const urlToTest = urlString.startsWith("http://") || urlString.startsWith("https://") ? urlString : `https://${urlString}`;
|
|
426
|
-
const url = new URL(urlToTest);
|
|
427
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
if (!url.hostname) {
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
const hostname = url.hostname;
|
|
434
|
-
if (hostname === "localhost") {
|
|
435
|
-
return true;
|
|
436
|
-
}
|
|
437
|
-
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
438
|
-
if (ipv4Regex.test(hostname)) {
|
|
439
|
-
const octets = hostname.split(".").map(Number);
|
|
440
|
-
return octets.every((octet) => octet >= 0 && octet <= 255);
|
|
441
|
-
}
|
|
442
|
-
const domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
443
|
-
return domainRegex.test(hostname);
|
|
444
|
-
} catch {
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
var styles = {
|
|
449
|
-
overlay: {
|
|
450
|
-
position: "fixed",
|
|
451
|
-
top: 0,
|
|
452
|
-
left: 0,
|
|
453
|
-
right: 0,
|
|
454
|
-
bottom: 0,
|
|
455
|
-
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
456
|
-
display: "flex",
|
|
457
|
-
alignItems: "center",
|
|
458
|
-
justifyContent: "center",
|
|
459
|
-
zIndex: 1e4,
|
|
460
|
-
padding: "1rem"
|
|
461
|
-
},
|
|
462
|
-
content: {
|
|
463
|
-
backgroundColor: "#1f2937",
|
|
464
|
-
borderRadius: "12px",
|
|
465
|
-
padding: "2rem",
|
|
466
|
-
maxWidth: "400px",
|
|
467
|
-
width: "100%",
|
|
468
|
-
position: "relative",
|
|
469
|
-
border: "1px solid #374151",
|
|
470
|
-
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)"
|
|
471
|
-
},
|
|
472
|
-
closeButton: {
|
|
473
|
-
position: "absolute",
|
|
474
|
-
top: "1rem",
|
|
475
|
-
right: "1rem",
|
|
476
|
-
background: "none",
|
|
477
|
-
border: "none",
|
|
478
|
-
fontSize: "1.5rem",
|
|
479
|
-
color: "#9ca3af",
|
|
480
|
-
cursor: "pointer",
|
|
481
|
-
padding: "0.25rem",
|
|
482
|
-
lineHeight: 1
|
|
483
|
-
},
|
|
484
|
-
header: {
|
|
485
|
-
display: "flex",
|
|
486
|
-
flexDirection: "column",
|
|
487
|
-
alignItems: "center",
|
|
488
|
-
gap: "0.75rem",
|
|
489
|
-
marginBottom: "1.5rem"
|
|
490
|
-
},
|
|
491
|
-
title: {
|
|
492
|
-
fontSize: "1.25rem",
|
|
493
|
-
fontWeight: 600,
|
|
494
|
-
color: "#f3f4f6",
|
|
495
|
-
margin: 0
|
|
496
|
-
},
|
|
497
|
-
info: {
|
|
498
|
-
color: "#9ca3af",
|
|
499
|
-
textAlign: "center",
|
|
500
|
-
marginBottom: "1.5rem",
|
|
501
|
-
fontSize: "0.875rem"
|
|
502
|
-
},
|
|
503
|
-
error: {
|
|
504
|
-
color: "#ef4444",
|
|
505
|
-
backgroundColor: "rgba(239, 68, 68, 0.1)",
|
|
506
|
-
border: "1px solid rgba(239, 68, 68, 0.3)",
|
|
507
|
-
borderRadius: "6px",
|
|
508
|
-
padding: "0.75rem",
|
|
509
|
-
marginBottom: "1rem",
|
|
510
|
-
fontSize: "0.875rem",
|
|
511
|
-
textAlign: "center"
|
|
512
|
-
},
|
|
513
|
-
radioGroup: {
|
|
514
|
-
display: "flex",
|
|
515
|
-
gap: "1rem",
|
|
516
|
-
marginBottom: "1rem",
|
|
517
|
-
justifyContent: "center"
|
|
518
|
-
},
|
|
519
|
-
radioLabel: {
|
|
520
|
-
display: "flex",
|
|
521
|
-
alignItems: "center",
|
|
522
|
-
gap: "0.5rem",
|
|
523
|
-
color: "#e5e7eb",
|
|
524
|
-
cursor: "pointer",
|
|
525
|
-
padding: "0.5rem 1rem",
|
|
526
|
-
borderRadius: "6px",
|
|
527
|
-
border: "1px solid #374151",
|
|
528
|
-
backgroundColor: "#111827",
|
|
529
|
-
transition: "all 0.2s"
|
|
530
|
-
},
|
|
531
|
-
radioLabelActive: {
|
|
532
|
-
borderColor: "#3b82f6",
|
|
533
|
-
backgroundColor: "rgba(59, 130, 246, 0.1)"
|
|
534
|
-
},
|
|
535
|
-
input: {
|
|
536
|
-
width: "100%",
|
|
537
|
-
padding: "0.75rem 1rem",
|
|
538
|
-
borderRadius: "6px",
|
|
539
|
-
border: "1px solid #374151",
|
|
540
|
-
backgroundColor: "#111827",
|
|
541
|
-
color: "#f3f4f6",
|
|
542
|
-
fontSize: "0.875rem",
|
|
543
|
-
outline: "none",
|
|
544
|
-
marginBottom: "1rem",
|
|
545
|
-
boxSizing: "border-box"
|
|
546
|
-
},
|
|
547
|
-
localInfo: {
|
|
548
|
-
color: "#9ca3af",
|
|
549
|
-
fontSize: "0.875rem",
|
|
550
|
-
textAlign: "center",
|
|
551
|
-
padding: "0.75rem",
|
|
552
|
-
backgroundColor: "#111827",
|
|
553
|
-
borderRadius: "6px",
|
|
554
|
-
marginBottom: "1rem"
|
|
555
|
-
},
|
|
556
|
-
buttonGroup: {
|
|
557
|
-
display: "flex",
|
|
558
|
-
justifyContent: "center"
|
|
559
|
-
},
|
|
560
|
-
button: {
|
|
561
|
-
padding: "0.75rem 2rem",
|
|
562
|
-
borderRadius: "6px",
|
|
563
|
-
border: "none",
|
|
564
|
-
fontSize: "0.875rem",
|
|
565
|
-
fontWeight: 600,
|
|
566
|
-
cursor: "pointer",
|
|
567
|
-
backgroundColor: "#3b82f6",
|
|
568
|
-
color: "white",
|
|
569
|
-
transition: "all 0.2s"
|
|
570
|
-
},
|
|
571
|
-
buttonDisabled: {
|
|
572
|
-
opacity: 0.5,
|
|
573
|
-
cursor: "not-allowed"
|
|
574
|
-
},
|
|
575
|
-
loading: {
|
|
576
|
-
display: "flex",
|
|
577
|
-
flexDirection: "column",
|
|
578
|
-
alignItems: "center",
|
|
579
|
-
gap: "1rem",
|
|
580
|
-
padding: "2rem",
|
|
581
|
-
color: "#9ca3af"
|
|
582
|
-
},
|
|
583
|
-
spinner: {
|
|
584
|
-
width: "2rem",
|
|
585
|
-
height: "2rem",
|
|
586
|
-
border: "3px solid #374151",
|
|
587
|
-
borderTopColor: "#3b82f6",
|
|
588
|
-
borderRadius: "50%",
|
|
589
|
-
animation: "spin 1s linear infinite"
|
|
590
|
-
}
|
|
591
|
-
};
|
|
592
|
-
function LoginModal({
|
|
593
|
-
onConnect,
|
|
594
|
-
onClose,
|
|
595
|
-
connectionType,
|
|
596
|
-
isOpen
|
|
597
|
-
}) {
|
|
598
|
-
const [nodeType, setNodeType] = react.useState("local");
|
|
599
|
-
const [nodeUrl, setNodeUrl2] = react.useState("");
|
|
600
|
-
const [isValid, setIsValid] = react.useState(true);
|
|
372
|
+
function useExecute(contextId, executorId) {
|
|
373
|
+
const { mero } = useMero();
|
|
601
374
|
const [loading, setLoading] = react.useState(false);
|
|
602
375
|
const [error, setError] = react.useState(null);
|
|
603
|
-
const
|
|
604
|
-
const shouldShowRemote = connectionType === "remote-and-local" /* RemoteAndLocal */ || connectionType === "remote" /* Remote */;
|
|
605
|
-
const shouldShowRadioGroup = shouldShowLocal && shouldShowRemote;
|
|
376
|
+
const mountedRef = react.useRef(true);
|
|
606
377
|
react.useEffect(() => {
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
378
|
+
mountedRef.current = true;
|
|
379
|
+
return () => {
|
|
380
|
+
mountedRef.current = false;
|
|
381
|
+
};
|
|
611
382
|
}, []);
|
|
612
|
-
react.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
}, [connectionType]);
|
|
619
|
-
react.useEffect(() => {
|
|
620
|
-
if (nodeType === "remote") {
|
|
621
|
-
setIsValid(isValidUrl(nodeUrl));
|
|
622
|
-
} else {
|
|
623
|
-
setIsValid(true);
|
|
624
|
-
}
|
|
625
|
-
}, [nodeUrl, nodeType]);
|
|
626
|
-
const handleConnect = react.useCallback(async () => {
|
|
627
|
-
if (!isValid) return;
|
|
628
|
-
setLoading(true);
|
|
629
|
-
setError(null);
|
|
630
|
-
const baseUrl = nodeType === "local" ? "http://node1.127.0.0.1.nip.io" : nodeUrl;
|
|
631
|
-
try {
|
|
632
|
-
const response = await fetch(
|
|
633
|
-
new URL("admin-api/is-authed", baseUrl).toString()
|
|
634
|
-
);
|
|
635
|
-
if (response.ok || response.status === 401) {
|
|
636
|
-
setLoading(false);
|
|
637
|
-
const normalizedUrl = baseUrl.replace(/\/+$/, "");
|
|
638
|
-
onConnect(normalizedUrl);
|
|
639
|
-
} else {
|
|
640
|
-
throw new Error(`Connection failed: ${response.statusText}`);
|
|
383
|
+
const execute = react.useCallback(
|
|
384
|
+
async (method, params) => {
|
|
385
|
+
if (!mero || !contextId || !executorId) {
|
|
386
|
+
if (mountedRef.current) setError(new Error("Not connected"));
|
|
387
|
+
return null;
|
|
641
388
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.loading, children: [
|
|
664
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Connecting to node..." }),
|
|
665
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.spinner })
|
|
666
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
667
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.info, children: shouldShowRadioGroup ? "Select your Calimero node type to continue." : connectionType === "local" /* Local */ ? "Connect to your local Calimero node." : "Enter your remote Calimero node URL." }),
|
|
668
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.error, children: error }),
|
|
669
|
-
shouldShowRadioGroup && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.radioGroup, children: [
|
|
670
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
671
|
-
"label",
|
|
672
|
-
{
|
|
673
|
-
style: {
|
|
674
|
-
...styles.radioLabel,
|
|
675
|
-
...nodeType === "local" ? styles.radioLabelActive : {}
|
|
676
|
-
},
|
|
677
|
-
onClick: () => setNodeType("local"),
|
|
678
|
-
children: [
|
|
679
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
680
|
-
"input",
|
|
681
|
-
{
|
|
682
|
-
type: "radio",
|
|
683
|
-
value: "local",
|
|
684
|
-
checked: nodeType === "local",
|
|
685
|
-
onChange: () => setNodeType("local"),
|
|
686
|
-
style: { display: "none" }
|
|
687
|
-
}
|
|
688
|
-
),
|
|
689
|
-
"\u{1F3E0} Local"
|
|
690
|
-
]
|
|
691
|
-
}
|
|
692
|
-
),
|
|
693
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
694
|
-
"label",
|
|
695
|
-
{
|
|
696
|
-
style: {
|
|
697
|
-
...styles.radioLabel,
|
|
698
|
-
...nodeType === "remote" ? styles.radioLabelActive : {}
|
|
699
|
-
},
|
|
700
|
-
onClick: () => setNodeType("remote"),
|
|
701
|
-
children: [
|
|
702
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
703
|
-
"input",
|
|
704
|
-
{
|
|
705
|
-
type: "radio",
|
|
706
|
-
value: "remote",
|
|
707
|
-
checked: nodeType === "remote",
|
|
708
|
-
onChange: () => setNodeType("remote"),
|
|
709
|
-
style: { display: "none" }
|
|
710
|
-
}
|
|
711
|
-
),
|
|
712
|
-
"\u{1F310} Remote"
|
|
713
|
-
]
|
|
714
|
-
}
|
|
715
|
-
)
|
|
716
|
-
] }),
|
|
717
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: shouldShowRemote && nodeType === "remote" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
718
|
-
"input",
|
|
719
|
-
{
|
|
720
|
-
type: "text",
|
|
721
|
-
value: nodeUrl,
|
|
722
|
-
onChange: (e) => setNodeUrl2(e.target.value),
|
|
723
|
-
placeholder: "https://your-node-url.calimero.network",
|
|
724
|
-
style: styles.input,
|
|
725
|
-
onKeyDown: (e) => {
|
|
726
|
-
if (e.key === "Enter" && isValid) {
|
|
727
|
-
handleConnect();
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
) : shouldShowLocal ? /* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles.localInfo, children: [
|
|
732
|
-
"Using default local node: ",
|
|
733
|
-
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
734
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { style: { color: "#60a5fa" }, children: "http://node1.127.0.0.1.nip.io" })
|
|
735
|
-
] }) : null }),
|
|
736
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.buttonGroup, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
737
|
-
"button",
|
|
738
|
-
{
|
|
739
|
-
onClick: handleConnect,
|
|
740
|
-
disabled: !isValid || loading,
|
|
741
|
-
style: {
|
|
742
|
-
...styles.button,
|
|
743
|
-
...!isValid || loading ? styles.buttonDisabled : {}
|
|
744
|
-
},
|
|
745
|
-
children: "Connect"
|
|
746
|
-
}
|
|
747
|
-
) })
|
|
748
|
-
] })
|
|
749
|
-
] }) })
|
|
750
|
-
] });
|
|
751
|
-
return reactDom.createPortal(modalContent, document.body);
|
|
752
|
-
}
|
|
753
|
-
function MeroLogo() {
|
|
754
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
755
|
-
"svg",
|
|
756
|
-
{
|
|
757
|
-
width: "40",
|
|
758
|
-
height: "40",
|
|
759
|
-
viewBox: "0 0 24 24",
|
|
760
|
-
fill: "#3b82f6",
|
|
761
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
762
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z" })
|
|
763
|
-
}
|
|
389
|
+
if (mountedRef.current) {
|
|
390
|
+
setLoading(true);
|
|
391
|
+
setError(null);
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
const result = await mero.rpc.execute({
|
|
395
|
+
contextId,
|
|
396
|
+
method,
|
|
397
|
+
argsJson: params,
|
|
398
|
+
executorPublicKey: executorId
|
|
399
|
+
});
|
|
400
|
+
return result;
|
|
401
|
+
} catch (err) {
|
|
402
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
403
|
+
if (mountedRef.current) setError(e);
|
|
404
|
+
return null;
|
|
405
|
+
} finally {
|
|
406
|
+
if (mountedRef.current) setLoading(false);
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
[mero, contextId, executorId]
|
|
764
410
|
);
|
|
411
|
+
return { execute, loading, error };
|
|
765
412
|
}
|
|
766
|
-
function
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const { isAuthenticated, connectToNode, logout, nodeUrl, isOnline } = useMero();
|
|
772
|
-
const [isDropdownOpen, setIsDropdownOpen] = react.useState(false);
|
|
773
|
-
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
774
|
-
const dropdownRef = react.useRef(null);
|
|
413
|
+
function useSubscription(contextIds, callback) {
|
|
414
|
+
const { mero } = useMero();
|
|
415
|
+
const callbackRef = react.useRef(callback);
|
|
416
|
+
callbackRef.current = callback;
|
|
417
|
+
const contextIdsKey = JSON.stringify(contextIds);
|
|
775
418
|
react.useEffect(() => {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
419
|
+
if (!mero || contextIds.length === 0) return;
|
|
420
|
+
const sse = mero.events;
|
|
421
|
+
const handler = (event) => {
|
|
422
|
+
callbackRef.current(event);
|
|
423
|
+
};
|
|
424
|
+
sse.on("event", handler);
|
|
425
|
+
sse.connect().catch(() => {
|
|
426
|
+
});
|
|
427
|
+
sse.subscribe(contextIds).catch(() => {
|
|
428
|
+
});
|
|
429
|
+
return () => {
|
|
430
|
+
sse.off("event", handler);
|
|
431
|
+
};
|
|
432
|
+
}, [mero, contextIdsKey]);
|
|
433
|
+
}
|
|
434
|
+
function useContexts(applicationId) {
|
|
435
|
+
const { mero } = useMero();
|
|
436
|
+
const [contexts, setContexts] = react.useState([]);
|
|
437
|
+
const [loading, setLoading] = react.useState(false);
|
|
438
|
+
const [error, setError] = react.useState(null);
|
|
439
|
+
const mountedRef = react.useRef(true);
|
|
440
|
+
react.useEffect(() => {
|
|
441
|
+
mountedRef.current = true;
|
|
442
|
+
return () => {
|
|
443
|
+
mountedRef.current = false;
|
|
780
444
|
};
|
|
781
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
782
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
783
445
|
}, []);
|
|
784
|
-
const
|
|
785
|
-
if (!
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
if (typeof connectionType === "object" && connectionType.type === "custom" /* Custom */) {
|
|
790
|
-
connectToNode(connectionType.url);
|
|
791
|
-
return;
|
|
446
|
+
const refetch = react.useCallback(async () => {
|
|
447
|
+
if (!mero) return;
|
|
448
|
+
if (mountedRef.current) {
|
|
449
|
+
setLoading(true);
|
|
450
|
+
setError(null);
|
|
792
451
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
};
|
|
799
|
-
if (isAuthenticated && !isOnline) {
|
|
800
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
801
|
-
"button",
|
|
802
|
-
{
|
|
803
|
-
className: `mero-connect-button mero-reconnecting ${className || ""}`,
|
|
804
|
-
style,
|
|
805
|
-
disabled: true,
|
|
806
|
-
children: [
|
|
807
|
-
/* @__PURE__ */ jsxRuntime.jsx(MeroLogo2, {}),
|
|
808
|
-
"Reconnecting..."
|
|
809
|
-
]
|
|
810
|
-
}
|
|
811
|
-
);
|
|
812
|
-
}
|
|
813
|
-
if (isAuthenticated) {
|
|
814
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: dropdownRef, className: "mero-connect-container", style: { position: "relative", display: "inline-block" }, children: [
|
|
815
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
816
|
-
"button",
|
|
817
|
-
{
|
|
818
|
-
className: `mero-connect-button mero-connected ${className || ""}`,
|
|
819
|
-
style,
|
|
820
|
-
onClick: () => setIsDropdownOpen((prev) => !prev),
|
|
821
|
-
children: [
|
|
822
|
-
/* @__PURE__ */ jsxRuntime.jsx(MeroLogo2, {}),
|
|
823
|
-
"Connected"
|
|
824
|
-
]
|
|
825
|
-
}
|
|
826
|
-
),
|
|
827
|
-
isDropdownOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mero-dropdown", children: [
|
|
828
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mero-dropdown-info", title: nodeUrl || "", children: nodeUrl }),
|
|
829
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
830
|
-
"a",
|
|
831
|
-
{
|
|
832
|
-
href: dashboardUrl,
|
|
833
|
-
target: "_blank",
|
|
834
|
-
rel: "noopener noreferrer",
|
|
835
|
-
className: "mero-dropdown-item",
|
|
836
|
-
children: "Dashboard"
|
|
837
|
-
}
|
|
838
|
-
),
|
|
839
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
840
|
-
"button",
|
|
841
|
-
{
|
|
842
|
-
className: "mero-dropdown-item",
|
|
843
|
-
onClick: () => {
|
|
844
|
-
setIsDropdownOpen(false);
|
|
845
|
-
logout();
|
|
846
|
-
},
|
|
847
|
-
children: "Log out"
|
|
848
|
-
}
|
|
849
|
-
)
|
|
850
|
-
] })
|
|
851
|
-
] });
|
|
852
|
-
}
|
|
853
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
854
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
855
|
-
"button",
|
|
856
|
-
{
|
|
857
|
-
className: `mero-connect-button ${className || ""}`,
|
|
858
|
-
style,
|
|
859
|
-
onClick: handleConnect,
|
|
860
|
-
children: [
|
|
861
|
-
/* @__PURE__ */ jsxRuntime.jsx(MeroLogo2, {}),
|
|
862
|
-
"Connect"
|
|
863
|
-
]
|
|
864
|
-
}
|
|
865
|
-
),
|
|
866
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
867
|
-
LoginModal,
|
|
868
|
-
{
|
|
869
|
-
isOpen: isModalOpen,
|
|
870
|
-
onConnect: handleModalConnect,
|
|
871
|
-
onClose: () => setIsModalOpen(false),
|
|
872
|
-
connectionType: typeof connectionType === "object" ? "remote-and-local" /* RemoteAndLocal */ : connectionType
|
|
452
|
+
try {
|
|
453
|
+
const response = await mero.admin.getContexts();
|
|
454
|
+
let list = (response.contexts ?? []).map((c) => ({ contextId: c.id, applicationId: c.applicationId }));
|
|
455
|
+
if (applicationId) {
|
|
456
|
+
list = list.filter((c) => c.applicationId === applicationId);
|
|
873
457
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
{
|
|
881
|
-
className: "mero-logo",
|
|
882
|
-
width: "24",
|
|
883
|
-
height: "24",
|
|
884
|
-
viewBox: "0 0 24 24",
|
|
885
|
-
fill: "currentColor",
|
|
886
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
887
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z" })
|
|
458
|
+
if (mountedRef.current) setContexts(list);
|
|
459
|
+
} catch (err) {
|
|
460
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
461
|
+
if (mountedRef.current) setError(e);
|
|
462
|
+
} finally {
|
|
463
|
+
if (mountedRef.current) setLoading(false);
|
|
888
464
|
}
|
|
889
|
-
);
|
|
465
|
+
}, [mero, applicationId]);
|
|
466
|
+
react.useEffect(() => {
|
|
467
|
+
void refetch();
|
|
468
|
+
}, [refetch]);
|
|
469
|
+
return { contexts, loading, error, refetch };
|
|
890
470
|
}
|
|
891
471
|
|
|
892
|
-
Object.defineProperty(exports, "MeroJs", {
|
|
893
|
-
enumerable: true,
|
|
894
|
-
get: function () { return meroJs.MeroJs; }
|
|
895
|
-
});
|
|
896
472
|
exports.AppMode = AppMode;
|
|
897
|
-
exports.ConnectButton = ConnectButton;
|
|
898
473
|
exports.ConnectionType = ConnectionType;
|
|
899
|
-
exports.EventStreamMode = EventStreamMode;
|
|
900
|
-
exports.LoginModal = LoginModal;
|
|
901
474
|
exports.MeroContext = MeroContext;
|
|
902
475
|
exports.MeroProvider = MeroProvider;
|
|
903
476
|
exports.clearAllStorage = clearAllStorage;
|
|
904
477
|
exports.clearApplicationId = clearApplicationId;
|
|
478
|
+
exports.clearContextId = clearContextId;
|
|
479
|
+
exports.clearContextIdentity = clearContextIdentity;
|
|
905
480
|
exports.clearNodeUrl = clearNodeUrl;
|
|
906
481
|
exports.getApplicationId = getApplicationId;
|
|
482
|
+
exports.getContextId = getContextId;
|
|
483
|
+
exports.getContextIdentity = getContextIdentity;
|
|
907
484
|
exports.getNodeUrl = getNodeUrl;
|
|
908
485
|
exports.localStorageTokenStorage = localStorageTokenStorage;
|
|
909
486
|
exports.setApplicationId = setApplicationId;
|
|
487
|
+
exports.setContextId = setContextId;
|
|
488
|
+
exports.setContextIdentity = setContextIdentity;
|
|
910
489
|
exports.setNodeUrl = setNodeUrl;
|
|
490
|
+
exports.useContexts = useContexts;
|
|
491
|
+
exports.useExecute = useExecute;
|
|
911
492
|
exports.useMero = useMero;
|
|
493
|
+
exports.useSubscription = useSubscription;
|
|
494
|
+
Object.keys(meroJs).forEach(function (k) {
|
|
495
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
496
|
+
enumerable: true,
|
|
497
|
+
get: function () { return meroJs[k]; }
|
|
498
|
+
});
|
|
499
|
+
});
|
|
912
500
|
//# sourceMappingURL=index.cjs.map
|
|
913
501
|
//# sourceMappingURL=index.cjs.map
|