nextjs-hasura-auth 0.1.2 → 0.1.4

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.
@@ -0,0 +1,385 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.proxyGET = proxyGET;
49
+ exports.proxyPOST = proxyPOST;
50
+ exports.proxySOCKET = proxySOCKET;
51
+ const server_1 = require("next/server");
52
+ const ws_1 = __importStar(require("ws"));
53
+ const jwt_1 = require("next-auth/jwt");
54
+ const debug_1 = __importDefault(require("@/lib/debug"));
55
+ const jwt_2 = require("@/lib/jwt");
56
+ const debugGraphql = (0, debug_1.default)('graphql:proxy');
57
+ let HASURA_ENDPOINT;
58
+ let HASURA_WS_ENDPOINT;
59
+ let HASURA_ADMIN_SECRET;
60
+ let NEXTAUTH_SECRET;
61
+ if (typeof window === 'undefined') {
62
+ // --- Environment Variables --- (Moved here, consider centralizing further)
63
+ HASURA_ENDPOINT = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL;
64
+ HASURA_WS_ENDPOINT = HASURA_ENDPOINT === null || HASURA_ENDPOINT === void 0 ? void 0 : HASURA_ENDPOINT.replace('https', 'wss').replace('http', 'ws');
65
+ HASURA_ADMIN_SECRET = process.env.HASURA_ADMIN_SECRET;
66
+ NEXTAUTH_SECRET = process.env.NEXTAUTH_SECRET;
67
+ // --- Basic Checks --- (Moved here)
68
+ if (!HASURA_ENDPOINT) {
69
+ console.error("❌ CRITICAL: NEXT_PUBLIC_HASURA_GRAPHQL_URL environment variable is not set.");
70
+ debugGraphql("❌ CRITICAL: NEXT_PUBLIC_HASURA_GRAPHQL_URL environment variable is not set.");
71
+ }
72
+ if (!HASURA_WS_ENDPOINT) {
73
+ console.error("❌ CRITICAL: Cannot derive WebSocket endpoint from NEXT_PUBLIC_HASURA_GRAPHQL_URL.");
74
+ debugGraphql("❌ CRITICAL: Cannot derive WebSocket endpoint from NEXT_PUBLIC_HASURA_GRAPHQL_URL.");
75
+ }
76
+ if (!HASURA_ADMIN_SECRET) {
77
+ // Allow Admin Secret to be optional for WS if only JWT is used, but log warning
78
+ console.warn("⚠️ WARNING: HASURA_ADMIN_SECRET environment variable is not set. Anonymous WS access will fail.");
79
+ debugGraphql("⚠️ WARNING: HASURA_ADMIN_SECRET environment variable is not set. Anonymous WS access will fail.");
80
+ }
81
+ if (!NEXTAUTH_SECRET) {
82
+ console.error("❌ CRITICAL: NEXTAUTH_SECRET environment variable is not set.");
83
+ debugGraphql("❌ CRITICAL: NEXTAUTH_SECRET environment variable is not set.");
84
+ }
85
+ }
86
+ // =======================================================================
87
+ // GET Handler Logic
88
+ // =======================================================================
89
+ function proxyGET(request) {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ debugGraphql('Executing proxyGET');
92
+ return server_1.NextResponse.json({
93
+ status: 'ok',
94
+ message: 'GraphQL API and WebSocket proxy active',
95
+ endpoints: {
96
+ http: '/api/graphql',
97
+ ws: '/api/graphql' // WebSocket uses the same endpoint via upgrade
98
+ },
99
+ hasura_endpoint: HASURA_ENDPOINT,
100
+ });
101
+ });
102
+ }
103
+ // =======================================================================
104
+ // POST Handler Logic
105
+ // =======================================================================
106
+ function proxyPOST(request) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ debugGraphql('--- proxyPOST Start ---');
109
+ if (!HASURA_ENDPOINT) {
110
+ const errorMsg = 'Hasura HTTP endpoint is not configured on the server.';
111
+ console.error(`❌ ${errorMsg}`);
112
+ debugGraphql(`❌ ${errorMsg}`);
113
+ return server_1.NextResponse.json({ errors: [{ message: errorMsg }] }, { status: 500 });
114
+ }
115
+ try {
116
+ const body = yield request.json();
117
+ const queryStr = JSON.stringify(body).substring(0, 200);
118
+ debugGraphql(`📤 GraphQL Query Received (preview): ${queryStr}${queryStr.length >= 200 ? '...' : ''}`);
119
+ const headers = {
120
+ 'Content-Type': 'application/json',
121
+ };
122
+ if (!HASURA_ADMIN_SECRET) {
123
+ const errorMsg = 'HASURA_ADMIN_SECRET is not configured on the server for HTTP proxy.';
124
+ console.error(`❌ ${errorMsg}`);
125
+ debugGraphql(`❌ ${errorMsg}`);
126
+ // Important: Do not proceed if admin secret is missing for POST
127
+ return server_1.NextResponse.json({ errors: [{ message: errorMsg }] }, { status: 500 });
128
+ }
129
+ headers['x-hasura-admin-secret'] = HASURA_ADMIN_SECRET;
130
+ debugGraphql('🔑 Using Hasura Admin Secret for downstream HTTP request.');
131
+ debugGraphql(`🔗 Sending request to Hasura HTTP: ${HASURA_ENDPOINT}`);
132
+ const hasuraResponse = yield fetch(HASURA_ENDPOINT, {
133
+ method: 'POST',
134
+ headers,
135
+ body: JSON.stringify(body),
136
+ });
137
+ const data = yield hasuraResponse.json();
138
+ if (data.errors) {
139
+ console.error('❌ Error response from Hasura:', JSON.stringify(data.errors));
140
+ debugGraphql('❌ Error response from Hasura:', JSON.stringify(data.errors));
141
+ }
142
+ else {
143
+ debugGraphql('✅ Successful response from Hasura HTTP.');
144
+ }
145
+ debugGraphql('--- proxyPOST End ---');
146
+ return server_1.NextResponse.json(data, { status: hasuraResponse.status });
147
+ }
148
+ catch (error) {
149
+ console.error('❌ Error proxying HTTP GraphQL request:', error.stack || error);
150
+ debugGraphql('❌ Error proxying HTTP GraphQL request:', error.message);
151
+ debugGraphql('--- proxyPOST End (Error) ---');
152
+ return server_1.NextResponse.json({
153
+ errors: [
154
+ {
155
+ message: 'Error processing GraphQL request via proxy.',
156
+ extensions: {
157
+ code: 'INTERNAL_SERVER_ERROR',
158
+ path: 'graphql-proxy-http'
159
+ }
160
+ }
161
+ ]
162
+ }, { status: 500 });
163
+ }
164
+ });
165
+ }
166
+ // =======================================================================
167
+ // SOCKET Handler Logic
168
+ // =======================================================================
169
+ function proxySOCKET(client, request, server) {
170
+ return __awaiter(this, void 0, void 0, function* () {
171
+ const clientId = Math.random().toString(36).substring(2, 8); // Shorter ID
172
+ debugGraphql(`--- proxySOCKET [${clientId}] Start ---`);
173
+ if (!HASURA_WS_ENDPOINT) {
174
+ console.error(`❌ [${clientId}] Hasura WebSocket endpoint not configured.`);
175
+ debugGraphql(`❌ [${clientId}] Hasura WebSocket endpoint not configured.`);
176
+ client.close(1011, 'WebSocket endpoint not configured');
177
+ return;
178
+ }
179
+ if (!NEXTAUTH_SECRET) {
180
+ console.error(`❌ [${clientId}] NEXTAUTH_SECRET not configured.`);
181
+ debugGraphql(`❌ [${clientId}] NEXTAUTH_SECRET not configured.`);
182
+ client.close(1011, 'Server authentication secret not configured');
183
+ return;
184
+ }
185
+ let hasuraWs = null;
186
+ let clientConnectionInitialized = false;
187
+ let hasuraConnectionInitialized = false;
188
+ const closeConnections = (code = 1000, reason = 'Closing connection') => {
189
+ debugGraphql(`[${clientId}] Closing connections: Code=${code}, Reason=${reason}`);
190
+ if (client.readyState === ws_1.WebSocket.OPEN || client.readyState === ws_1.WebSocket.CONNECTING) {
191
+ client.close(code, reason);
192
+ }
193
+ if (hasuraWs && (hasuraWs.readyState === ws_1.WebSocket.OPEN || hasuraWs.readyState === ws_1.WebSocket.CONNECTING)) {
194
+ hasuraWs.close(code, reason);
195
+ }
196
+ debugGraphql(`[${clientId}] Connections closed.`);
197
+ };
198
+ try {
199
+ const token = yield (0, jwt_1.getToken)({
200
+ req: request,
201
+ secret: NEXTAUTH_SECRET
202
+ });
203
+ const headers = {};
204
+ if (token === null || token === void 0 ? void 0 : token.sub) {
205
+ debugGraphql(`👤 [${clientId}] User authenticated (ID: ${token.sub}). Generating Hasura JWT.`);
206
+ try {
207
+ const hasuraClaims = {
208
+ 'x-hasura-allowed-roles': ['user', 'anonymous', 'me'], // Keep fixed roles for simplicity in proxy
209
+ 'x-hasura-default-role': 'user',
210
+ 'x-hasura-user-id': token.sub,
211
+ };
212
+ const jwt = yield (0, jwt_2.generateJWT)(token.sub, hasuraClaims); // Assumes generateJWT uses env secret
213
+ headers['Authorization'] = `Bearer ${jwt}`;
214
+ debugGraphql(`🔑 [${clientId}] Using generated JWT (user role) for Hasura WS connection.`);
215
+ }
216
+ catch (jwtError) {
217
+ console.error(`❌ [${clientId}] Failed to generate Hasura JWT for user:`, jwtError);
218
+ debugGraphql(`❌ [${clientId}] Failed to generate Hasura JWT for user:`, jwtError.message);
219
+ closeConnections(1011, "JWT generation failed");
220
+ return;
221
+ }
222
+ }
223
+ else {
224
+ // --- MODIFICATION START: Generate Anonymous JWT instead of using Admin Secret ---
225
+ debugGraphql(`👤 [${clientId}] User not authenticated. Generating Anonymous JWT.`);
226
+ try {
227
+ const anonymousUserId = `anon-${clientId}`; // Create a unique-ish ID for anonymous user
228
+ const hasuraClaims = {
229
+ 'x-hasura-allowed-roles': ['anonymous'], // Only allow anonymous role
230
+ 'x-hasura-default-role': 'anonymous',
231
+ 'x-hasura-user-id': anonymousUserId, // Provide an ID
232
+ };
233
+ // Use the same secret mechanism as for authenticated users
234
+ const jwt = yield (0, jwt_2.generateJWT)(anonymousUserId, hasuraClaims); // Assumes generateJWT uses env secret
235
+ headers['Authorization'] = `Bearer ${jwt}`;
236
+ debugGraphql(`🔑 [${clientId}] Using generated JWT (anonymous role) for Hasura WS connection.`);
237
+ }
238
+ catch (jwtError) {
239
+ console.error(`❌ [${clientId}] Failed to generate Hasura JWT for anonymous:`, jwtError);
240
+ debugGraphql(`❌ [${clientId}] Failed to generate Hasura JWT for anonymous:`, jwtError.message);
241
+ // Fallback or error closing might depend on requirements, here we close.
242
+ closeConnections(1011, "Anonymous JWT generation failed");
243
+ return;
244
+ }
245
+ // --- MODIFICATION END ---
246
+ /* --- OLD CODE using Admin Secret ---
247
+ } else if (HASURA_ADMIN_SECRET) {
248
+ debugGraphql(`👤 [${clientId}] User not authenticated. Using Admin Secret for Hasura WS connection.`);
249
+ headers['x-hasura-admin-secret'] = HASURA_ADMIN_SECRET;
250
+ } else {
251
+ debugGraphql(`❌ [${clientId}] Anonymous connection attempted, but no Admin Secret configured.`);
252
+ console.error(`❌ [${clientId}] Anonymous connection attempted, but no Admin Secret configured.`);
253
+ closeConnections(1011, 'Server configuration error for anonymous access.');
254
+ return;
255
+ }
256
+ */
257
+ }
258
+ debugGraphql(`🔗 [${clientId}] Establishing connection to Hasura WS: ${HASURA_WS_ENDPOINT}`);
259
+ hasuraWs = new ws_1.default(HASURA_WS_ENDPOINT, 'graphql-ws', { headers });
260
+ // --- WebSocket Event Handlers (Moved logic here) ---
261
+ hasuraWs.on('open', () => {
262
+ debugGraphql(`✅ [${clientId}] Connection to Hasura WS established.`);
263
+ const initMessage = { type: 'connection_init', payload: {} };
264
+ debugGraphql(`📤 [${clientId}] Sending connection_init to Hasura.`);
265
+ hasuraWs === null || hasuraWs === void 0 ? void 0 : hasuraWs.send(JSON.stringify(initMessage));
266
+ });
267
+ client.on('message', (message) => {
268
+ if (!hasuraWs || hasuraWs.readyState !== ws_1.WebSocket.OPEN) {
269
+ debugGraphql(`⚠️ [${clientId}] Received message from client, but Hasura WS not open. Ignoring.`);
270
+ return;
271
+ }
272
+ try {
273
+ const messageStr = message.toString();
274
+ const parsedMessage = JSON.parse(messageStr);
275
+ const type = parsedMessage.type;
276
+ // const preview = messageStr.substring(0, 100) + (messageStr.length > 100 ? '...' : '');
277
+ if (type === 'connection_init') {
278
+ debugGraphql(`🤝 [${clientId}] Received connection_init from client.`);
279
+ clientConnectionInitialized = true;
280
+ if (hasuraConnectionInitialized) {
281
+ debugGraphql(`🤝 [${clientId}] Sending connection_ack to client (Hasura already acked).`);
282
+ client.send(JSON.stringify({ type: 'connection_ack' }));
283
+ }
284
+ return; // Do NOT forward client's connection_init
285
+ }
286
+ if (!clientConnectionInitialized) {
287
+ console.error(`❌ [${clientId}] Message type ${type} received from client before connection_init.`);
288
+ debugGraphql(`❌ [${clientId}] Message type ${type} received from client before connection_init.`);
289
+ closeConnections(4401, 'Connection not initialized');
290
+ return;
291
+ }
292
+ if (['start', 'stop', 'subscribe', 'complete'].includes(type)) {
293
+ debugGraphql(`📤 [${clientId}] Forwarding ${type} C -> H`);
294
+ hasuraWs.send(messageStr);
295
+ }
296
+ else {
297
+ debugGraphql(`❓ [${clientId}] Unknown message type from client: ${type}. Ignoring.`);
298
+ }
299
+ }
300
+ catch (err) {
301
+ console.error(`❌ [${clientId}] Error processing client message:`, err);
302
+ debugGraphql(`❌ [${clientId}] Error processing client message:`, err.message);
303
+ }
304
+ });
305
+ hasuraWs.on('message', (message) => {
306
+ if (client.readyState !== ws_1.WebSocket.OPEN) {
307
+ debugGraphql(`⚠️ [${clientId}] Received message from Hasura, but client WS not open. Ignoring.`);
308
+ return;
309
+ }
310
+ try {
311
+ const messageStr = message.toString();
312
+ const parsedMessage = JSON.parse(messageStr);
313
+ const type = parsedMessage.type;
314
+ // const preview = messageStr.substring(0, 100) + (messageStr.length > 100 ? '...' : '');
315
+ if (type === 'connection_ack') {
316
+ debugGraphql(`🤝 [${clientId}] Received connection_ack from Hasura.`);
317
+ hasuraConnectionInitialized = true;
318
+ if (clientConnectionInitialized) {
319
+ debugGraphql(`🤝 [${clientId}] Sending connection_ack to client (Hasura just acked).`);
320
+ client.send(JSON.stringify({ type: 'connection_ack' }));
321
+ }
322
+ return;
323
+ }
324
+ if (type === 'ka') {
325
+ // debugGraphql(`[${clientId}] Received keep-alive from Hasura. Ignoring.`);
326
+ return; // Ignore Hasura keep-alive
327
+ }
328
+ let messageToSend = messageStr;
329
+ if (type === 'data') {
330
+ debugGraphql(`🔄 [${clientId}] Translating message type 'data' -> 'next'`);
331
+ parsedMessage.type = 'next';
332
+ messageToSend = JSON.stringify(parsedMessage);
333
+ }
334
+ else if (type === 'error') {
335
+ debugGraphql(`❗ [${clientId}] Forwarding error H -> C`);
336
+ }
337
+ else if (type === 'complete') {
338
+ debugGraphql(`✅ [${clientId}] Forwarding complete H -> C`);
339
+ }
340
+ else {
341
+ debugGraphql(`❓ [${clientId}] Unknown message type from Hasura: ${type}. Forwarding as-is.`);
342
+ }
343
+ client.send(messageToSend);
344
+ }
345
+ catch (err) {
346
+ console.error(`❌ [${clientId}] Error processing Hasura message:`, err);
347
+ debugGraphql(`❌ [${clientId}] Error processing Hasura message:`, err.message);
348
+ }
349
+ });
350
+ client.on('close', (code, reason) => {
351
+ const reasonStr = reason.toString();
352
+ debugGraphql(`👋 [${clientId}] Client disconnected: ${code} ${reasonStr}`);
353
+ debugGraphql(`--- proxySOCKET [${clientId}] End (Client Close) ---`);
354
+ closeConnections(code, reasonStr);
355
+ });
356
+ hasuraWs.on('close', (code, reason) => {
357
+ const reasonStr = reason.toString();
358
+ debugGraphql(`👋 [${clientId}] Hasura disconnected: ${code} ${reasonStr}`);
359
+ debugGraphql(`--- proxySOCKET [${clientId}] End (Hasura Close) ---`);
360
+ closeConnections(code, reasonStr);
361
+ });
362
+ client.on('error', (error) => {
363
+ console.error(`❌ [${clientId}] Client WebSocket error:`, error);
364
+ debugGraphql(`❌ [${clientId}] Client WebSocket error:`, error.message);
365
+ debugGraphql(`--- proxySOCKET [${clientId}] End (Client Error) ---`);
366
+ closeConnections(1011, 'Client error');
367
+ });
368
+ hasuraWs.on('error', (error) => {
369
+ console.error(`❌ [${clientId}] Hasura WebSocket error:`, error);
370
+ debugGraphql(`❌ [${clientId}] Hasura WebSocket error:`, error.message);
371
+ debugGraphql(`--- proxySOCKET [${clientId}] End (Hasura Error) ---`);
372
+ closeConnections(1011, 'Hasura connection error');
373
+ });
374
+ }
375
+ catch (error) {
376
+ console.error(`❌ [${clientId}] Error setting up WebSocket proxy:`, error);
377
+ debugGraphql(`❌ [${clientId}] Error setting up WebSocket proxy:`, error.message);
378
+ debugGraphql(`--- proxySOCKET [${clientId}] End (Setup Error) ---`);
379
+ // Ensure client connection is closed on setup error
380
+ if (client.readyState === ws_1.WebSocket.OPEN || client.readyState === ws_1.WebSocket.CONNECTING) {
381
+ client.close(1011, 'Proxy setup error');
382
+ }
383
+ }
384
+ });
385
+ }
@@ -18,7 +18,6 @@ const dotenv_1 = __importDefault(require("dotenv"));
18
18
  const fs_1 = __importDefault(require("fs"));
19
19
  const path_1 = __importDefault(require("path"));
20
20
  const graphql_1 = require("graphql"); // Use standard introspection query function
21
- // Загружаем переменные окружения из корневого .env
22
21
  dotenv_1.default.config({ path: path_1.default.resolve(__dirname, '../.env') });
23
22
  const HASURA_GRAPHQL_URL = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL;
24
23
  const HASURA_ADMIN_SECRET = process.env.HASURA_ADMIN_SECRET;
@@ -52,12 +51,6 @@ function fetchSchema() {
52
51
  if (!response.data || !response.data.data || !response.data.data.__schema) {
53
52
  throw new Error('Некорректный ответ от сервера Hasura. Отсутствует data.__schema.');
54
53
  }
55
- // Структурируем схему для совместимости с генератором (опционально, можно просто сохранить __schema)
56
- // Пока оставим простую структуру, аналогичную schema.js, но только с __schema
57
- // const structuredSchema = {
58
- // __schema: response.data.data.__schema
59
- // };
60
- // Для начала сохраним полный результат интроспекции, codegen его поймет
61
54
  const introspectionResult = response.data;
62
55
  console.log(`💾 Сохранение схемы в ${OUTPUT_PATH}...`);
63
56
  fs_1.default.writeFileSync(OUTPUT_PATH, JSON.stringify(introspectionResult, null, 2)); // Сохраняем весь результат
@@ -0,0 +1,7 @@
1
+ type ConnectionStatus = 'connecting' | 'connected' | 'error';
2
+ /**
3
+ * Hook to check connection to Hasura GraphQL endpoint
4
+ * @returns {ConnectionStatus} Current connection status
5
+ */
6
+ export declare function useCheckConnection(): ConnectionStatus;
7
+ export default useCheckConnection;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.useCheckConnection = useCheckConnection;
17
+ const react_1 = require("react");
18
+ const apollo_1 = require("../apollo");
19
+ const debug_1 = __importDefault(require("@/lib/debug"));
20
+ // Create a debug logger for this module
21
+ const debug = (0, debug_1.default)('hooks:connection');
22
+ /**
23
+ * Hook to check connection to Hasura GraphQL endpoint
24
+ * @returns {ConnectionStatus} Current connection status
25
+ */
26
+ function useCheckConnection() {
27
+ const [status, setStatus] = (0, react_1.useState)('connecting');
28
+ (0, react_1.useEffect)(() => {
29
+ let mounted = true;
30
+ const checkConnectionStatus = () => __awaiter(this, void 0, void 0, function* () {
31
+ try {
32
+ if (mounted)
33
+ setStatus('connecting');
34
+ const client = (0, apollo_1.getClient)();
35
+ const isConnected = yield (0, apollo_1.checkConnection)(client);
36
+ if (!mounted)
37
+ return;
38
+ if (isConnected) {
39
+ // Use the debug function directly if log is undefined
40
+ debug('hooks:connection', '✅ Connected to Hasura GraphQL endpoint');
41
+ setStatus('connected');
42
+ }
43
+ else {
44
+ debug('hooks:connection', '❌ Failed to connect to Hasura GraphQL endpoint');
45
+ setStatus('error');
46
+ }
47
+ }
48
+ catch (error) {
49
+ if (mounted) {
50
+ debug('hooks:connection', '❌ Connection error:', error);
51
+ setStatus('error');
52
+ }
53
+ }
54
+ });
55
+ checkConnectionStatus();
56
+ return () => {
57
+ mounted = false;
58
+ };
59
+ }, []);
60
+ return status;
61
+ }
62
+ exports.default = useCheckConnection;
@@ -5,3 +5,4 @@ export * from './hasura';
5
5
  export * from './auth';
6
6
  export * from './client';
7
7
  export * from './jwt';
8
+ export * from './graphql-proxy';
package/dist/lib/index.js CHANGED
@@ -22,3 +22,4 @@ __exportStar(require("./hasura"), exports);
22
22
  __exportStar(require("./auth"), exports);
23
23
  __exportStar(require("./client"), exports);
24
24
  __exportStar(require("./jwt"), exports);
25
+ __exportStar(require("./graphql-proxy"), exports);
@@ -0,0 +1,11 @@
1
+ import { ReactElement } from 'react';
2
+ import { screen } from '@testing-library/react';
3
+ import { ApolloClient } from '@apollo/client';
4
+ /**
5
+ * Custom renderer that wraps the component with necessary providers
6
+ */
7
+ declare const customRender: (ui: ReactElement, { apolloClient, ...renderOptions }?: {
8
+ apolloClient?: ApolloClient<import("@apollo/client").NormalizedCacheObject> | undefined;
9
+ }) => import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
10
+ export * from '@testing-library/react';
11
+ export { customRender as render, screen };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __rest = (this && this.__rest) || function (s, e) {
17
+ var t = {};
18
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
19
+ t[p] = s[p];
20
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
21
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
22
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
23
+ t[p[i]] = s[p[i]];
24
+ }
25
+ return t;
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.screen = exports.render = void 0;
29
+ const jsx_runtime_1 = require("react/jsx-runtime");
30
+ const react_1 = require("@testing-library/react");
31
+ Object.defineProperty(exports, "screen", { enumerable: true, get: function () { return react_1.screen; } });
32
+ const client_1 = require("@apollo/client");
33
+ // Create a mock Apollo client for testing
34
+ const createMockClient = () => {
35
+ return new client_1.ApolloClient({
36
+ cache: new client_1.InMemoryCache(),
37
+ defaultOptions: {
38
+ watchQuery: {
39
+ fetchPolicy: 'no-cache',
40
+ },
41
+ query: {
42
+ fetchPolicy: 'no-cache',
43
+ },
44
+ },
45
+ });
46
+ };
47
+ /**
48
+ * Custom renderer that wraps the component with necessary providers
49
+ */
50
+ const customRender = (ui, _a = {}) => {
51
+ var { apolloClient = createMockClient() } = _a, renderOptions = __rest(_a, ["apolloClient"]);
52
+ const AllTheProviders = ({ children }) => {
53
+ return ((0, jsx_runtime_1.jsx)(client_1.ApolloProvider, { client: apolloClient, children: children }));
54
+ };
55
+ return (0, react_1.render)(ui, Object.assign({ wrapper: AllTheProviders }, renderOptions));
56
+ };
57
+ exports.render = customRender;
58
+ // re-export everything from testing-library
59
+ __exportStar(require("@testing-library/react"), exports);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Generates a short-lived JWT for email verification.
3
+ * @param userId - The ID of the user to verify.
4
+ * @returns Promise<string> - The generated verification token.
5
+ */
6
+ export declare function generateVerificationToken(userId: string): Promise<string>;
7
+ /**
8
+ * Verifies an email verification token.
9
+ * @param token - The token string to verify.
10
+ * @returns Promise<{ userId: string } | null> - The user ID if the token is valid and has the correct scope, otherwise null.
11
+ */
12
+ export declare function verifyVerificationToken(token: string): Promise<{
13
+ userId: string;
14
+ } | null>;