nextjs-hasura-auth 0.1.1 → 0.1.3

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.
@@ -12,52 +12,41 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getJwtSecret = void 0;
16
- exports.createClient = createClient;
15
+ exports.CHECK_CONNECTION_QUERY = exports.CHECK_CONNECTION_SUBSCRIPTION = void 0;
16
+ exports.createApolloClient = createApolloClient;
17
17
  exports.getClient = getClient;
18
- exports.useClient = useClient;
18
+ exports.useCreateApolloClient = useCreateApolloClient;
19
19
  exports.checkConnection = checkConnection;
20
+ const jsx_runtime_1 = require("react/jsx-runtime");
20
21
  const client_1 = require("@apollo/client");
21
22
  const context_1 = require("@apollo/client/link/context");
22
23
  const utilities_1 = require("@apollo/client/utilities");
24
+ // Restore GraphQLWsLink imports
23
25
  const subscriptions_1 = require("@apollo/client/link/subscriptions");
24
26
  const graphql_ws_1 = require("graphql-ws");
25
27
  const cross_fetch_1 = __importDefault(require("cross-fetch"));
26
28
  const debug_1 = __importDefault(require("./debug"));
27
29
  const react_1 = require("react");
30
+ const jwt_1 = require("./jwt");
31
+ // Remove deprecated WebSocketLink import
32
+ // import { WebSocketLink } from '@apollo/client/link/ws';
33
+ const error_1 = require("@apollo/client/link/error");
28
34
  // Create a debug logger for this module
29
35
  const debug = (0, debug_1.default)('apollo');
30
36
  // Determine if running on client
31
37
  const isClient = typeof window !== 'undefined';
32
- /**
33
- * Get JWT secret from environment variables
34
- * @returns {Uint8Array} Secret key for JWT signing
35
- */
36
- const getJwtSecret = () => {
37
- try {
38
- const jwtSecret = process.env.HASURA_JWT_SECRET || '{"type":"HS256","key":"your-secret-key"}';
39
- // Parse JWT configuration (may be in JSON format)
40
- let secretKey;
41
- try {
42
- const jwtConfig = typeof jwtSecret === 'string' ? JSON.parse(jwtSecret) : jwtSecret;
43
- secretKey = jwtConfig.key;
44
- if (!secretKey) {
45
- throw new Error('JWT key not found in configuration');
46
- }
47
- }
48
- catch (e) {
49
- // If failed to parse as JSON, use as string
50
- secretKey = jwtSecret;
51
- }
52
- // Convert key to Uint8Array (required for jose)
53
- return new TextEncoder().encode(secretKey);
54
- }
55
- catch (error) {
56
- debug('apollo', '❌ Error getting JWT secret:', error);
57
- throw error;
38
+ const createRoleLink = () => (0, context_1.setContext)((request, previousContext) => {
39
+ // Get the role from the operation's context passed in the hook options
40
+ const role = previousContext === null || previousContext === void 0 ? void 0 : previousContext.role; // Correctly access context via the second argument
41
+ debug(`roleLink: Role from context: ${role}`);
42
+ if (role) {
43
+ return {
44
+ headers: Object.assign(Object.assign({}, previousContext.headers), { 'X-Hasura-Role': role }),
45
+ };
58
46
  }
59
- };
60
- exports.getJwtSecret = getJwtSecret;
47
+ // If no role is provided in the context, don't add the header
48
+ return {};
49
+ });
61
50
  /**
62
51
  * Create Apollo Client
63
52
  *
@@ -67,81 +56,113 @@ exports.getJwtSecret = getJwtSecret;
67
56
  * @param {string} options.secret - Admin secret for Hasura
68
57
  * @returns {ApolloClient} Apollo Client
69
58
  */
70
- function createClient(options = {}) {
59
+ function createApolloClient(options = {}) {
71
60
  // Default values
72
61
  const { url = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL, ws = false, token = undefined, secret = process.env.HASURA_ADMIN_SECRET } = options;
73
62
  if (!url) {
74
63
  throw new Error('❌ options.url or NEXT_PUBLIC_HASURA_GRAPHQL_URL not defined');
75
64
  }
76
65
  debug('apollo', '🔌 Creating Apollo client with endpoint:', url);
77
- // HTTP connection without authorization
78
- const publicHttpLink = new client_1.HttpLink({
66
+ // --- NEW: Link to set Hasura Role Header ---
67
+ const roleLink = createRoleLink();
68
+ // --- END NEW ---
69
+ // --- Existing Links ---
70
+ // Create base HttpLink (no auth here initially)
71
+ const baseHttpLink = new client_1.HttpLink({
79
72
  uri: url,
80
73
  fetch: cross_fetch_1.default,
81
74
  });
82
- // Create auth link with JWT token
83
- const authLink = token
84
- ? (0, context_1.setContext)((_, { headers }) => {
75
+ // Create link for adding auth (JWT or Admin Secret)
76
+ const authHeaderLink = (0, context_1.setContext)((_, { headers }) => {
77
+ // Return the headers to the context so httpLink can read them
78
+ if (token) {
79
+ debug('apollo', '🔒 Using JWT token for Authorization header');
85
80
  return {
86
81
  headers: Object.assign(Object.assign({}, headers), { Authorization: `Bearer ${token}` })
87
82
  };
88
- })
89
- : client_1.ApolloLink.from([]);
90
- // Choose link based on token or secret availability
91
- let httpLink;
92
- if (token) {
93
- // If token provided, use it for authorization
94
- httpLink = client_1.ApolloLink.from([authLink, publicHttpLink]);
95
- }
96
- else if (secret) {
97
- // If no token but admin secret exists, use it
98
- httpLink = new client_1.HttpLink({
99
- uri: url,
100
- fetch: cross_fetch_1.default,
101
- headers: {
102
- 'x-hasura-admin-secret': secret || ''
103
- }
104
- });
105
- ;
106
- }
107
- else {
108
- // If neither token nor secret, use public access
109
- httpLink = publicHttpLink;
110
- }
111
- // Create link splitter for queries
112
- let splitLink = httpLink;
113
- // If WebSocket connection needed and we're in browser
114
- if (ws && isClient) {
115
- const wsEndpoint = url.replace('http', 'ws').replace('https', 'wss');
116
- // Configure connection parameters
117
- const connectionParams = {};
118
- if (token) {
119
- // If token provided, use it for WebSocket authorization
120
- connectionParams.headers = {
121
- Authorization: `Bearer ${token}`,
122
- };
123
83
  }
124
84
  else if (secret) {
125
- // If no token but admin secret exists, use it
126
- connectionParams.headers = {
127
- 'x-hasura-admin-secret': secret,
85
+ debug('apollo', '🔑 Using Admin Secret for x-hasura-admin-secret header');
86
+ return {
87
+ headers: Object.assign(Object.assign({}, headers), { 'x-hasura-admin-secret': secret })
128
88
  };
129
89
  }
130
- // Create WebSocket client
90
+ debug('apollo', '🔓 Sending request without authentication headers');
91
+ return { headers };
92
+ });
93
+ // Chain the links: roleLink -> authHeaderLink -> baseHttpLink
94
+ const httpLink = client_1.ApolloLink.from([roleLink, authHeaderLink, baseHttpLink]);
95
+ // --- End Existing Links Modification ---
96
+ // --- WebSocket Link Setup (Remains largely the same) ---
97
+ let link = httpLink; // Start with the combined HTTP link
98
+ // --- Debugging WS Link Creation ---
99
+ debug('apollo', `🚀 Checking WS setup: ws=${ws}, isClient=${isClient}`);
100
+ if (ws && isClient) {
101
+ debug('apollo', '✅ Entering WS Link creation block.'); // Log entry
102
+ const wsEndpoint = url.replace('http', 'ws').replace('https://', 'wss');
103
+ debug('apollo', '🔌 Setting up GraphQLWsLink for:', wsEndpoint);
104
+ // --- Restore GraphQLWsLink ---
131
105
  const wsLink = new subscriptions_1.GraphQLWsLink((0, graphql_ws_1.createClient)({
132
106
  url: wsEndpoint,
133
- connectionParams: () => connectionParams
107
+ connectionParams: () => __awaiter(this, void 0, void 0, function* () {
108
+ debug('apollo', '⚙️ Evaluating connectionParams function...');
109
+ const params = {};
110
+ if (token) {
111
+ debug('apollo', '🔒 Using JWT token for WS connectionParams (from function)');
112
+ params.headers = { Authorization: `Bearer ${token}` };
113
+ }
114
+ else if (secret) {
115
+ debug('apollo', '🔑 Using Admin Secret for WS connectionParams (from function)');
116
+ params.headers = { 'x-hasura-admin-secret': secret };
117
+ }
118
+ else {
119
+ debug('apollo', '🔓 WebSocket connection without specific auth params (from function)');
120
+ }
121
+ debug('apollo', '⚙️ connectionParams function returning:', params);
122
+ return params;
123
+ }),
124
+ // Note: Dynamically changing headers per subscription via context
125
+ // is not standard in GraphQLWsLink. The roleLink above won't affect this.
126
+ // --- Add event handlers for diagnostics ---
127
+ on: {
128
+ connected: (socket) => debug('apollo', '🔗 [graphql-ws] WebSocket connected:', socket),
129
+ ping: (received) => debug('apollo', `➡️ [graphql-ws] Ping ${received ? 'received' : 'sent'}`),
130
+ pong: (received) => debug('apollo', `⬅️ [graphql-ws] Pong ${received ? 'received' : 'sent'}`),
131
+ error: (err) => debug('apollo', '❌ [graphql-ws] WebSocket error:', err),
132
+ closed: (event) => debug('apollo', '🚪 [graphql-ws] WebSocket closed:', event),
133
+ }
134
+ // --- End event handlers ---
134
135
  }));
135
- // Split requests: WebSocket for subscriptions, HTTP for others
136
- splitLink = (0, client_1.split)(({ query }) => {
136
+ /* --- Remove Deprecated WebSocketLink ---
137
+ const wsLink = new WebSocketLink({
138
+ uri: wsEndpoint,
139
+ options: {
140
+ reconnect: true,
141
+ connectionParams: connectionParams, // Pass prepared headers here
142
+ // Note: Timeout options might be needed depending on env
143
+ }
144
+ });
145
+ debug('apollo', '🔗 DEPRECATED WebSocketLink created.');
146
+ */
147
+ // Split based on operation type
148
+ link = (0, client_1.split)(({ query }) => {
137
149
  const definition = (0, utilities_1.getMainDefinition)(query);
150
+ const isSubscription = definition.kind === 'OperationDefinition' &&
151
+ definition.operation === 'subscription';
152
+ debug('apollo', `🔗 Split link decision: isSubscription=${isSubscription}`);
138
153
  return (definition.kind === 'OperationDefinition' &&
139
154
  definition.operation === 'subscription');
140
- }, wsLink, httpLink);
155
+ }, wsLink, // Use wsLink for subscriptions
156
+ httpLink // Use httpLink (with roleLink and authHeaderLink) for query/mutation
157
+ );
158
+ }
159
+ else {
160
+ debug('apollo', '❌ Skipping WS Link creation.', { ws, isClient });
141
161
  }
142
- // Create Apollo Client
143
- return new client_1.ApolloClient({
144
- link: splitLink,
162
+ // --- End WebSocket Setup ---
163
+ // Create Apollo Client with the final composed link
164
+ const apolloClient = new client_1.ApolloClient({
165
+ link: link, // Use the potentially split link
145
166
  cache: new client_1.InMemoryCache(),
146
167
  defaultOptions: {
147
168
  watchQuery: {
@@ -157,6 +178,10 @@ function createClient(options = {}) {
157
178
  },
158
179
  }
159
180
  });
181
+ apolloClient.Provider = function Provider({ children }) {
182
+ return (0, jsx_runtime_1.jsx)(client_1.ApolloProvider, { client: apolloClient, children: children });
183
+ };
184
+ return apolloClient;
160
185
  }
161
186
  // Default client instance
162
187
  let clientInstance = null;
@@ -167,7 +192,7 @@ let clientInstance = null;
167
192
  */
168
193
  function getClient(options = {}) {
169
194
  if (!clientInstance) {
170
- clientInstance = createClient(options);
195
+ clientInstance = createApolloClient(options);
171
196
  }
172
197
  return clientInstance;
173
198
  }
@@ -175,10 +200,19 @@ function getClient(options = {}) {
175
200
  * React hook to get Apollo client instance
176
201
  * @returns Apollo client instance
177
202
  */
178
- function useClient(options) {
179
- return (0, react_1.useMemo)(() => createClient(options), [options]);
203
+ function useCreateApolloClient(options) {
204
+ return (0, react_1.useMemo)(() => createApolloClient(options), [options]);
180
205
  }
181
- const CHECK_CONNECTION = (0, client_1.gql) `
206
+ exports.CHECK_CONNECTION_SUBSCRIPTION = (0, client_1.gql) `
207
+ subscription CheckConnection {
208
+ __schema {
209
+ queryType {
210
+ name
211
+ }
212
+ }
213
+ }
214
+ `;
215
+ exports.CHECK_CONNECTION_QUERY = (0, client_1.gql) `
182
216
  query CheckConnection {
183
217
  __schema {
184
218
  queryType {
@@ -194,13 +228,16 @@ query CheckConnection {
194
228
  function checkConnection() {
195
229
  return __awaiter(this, arguments, void 0, function* (client = getClient()) {
196
230
  var _a, _b, _c;
197
- const result = yield client.query({ query: CHECK_CONNECTION });
231
+ const result = yield client.query({ query: exports.CHECK_CONNECTION_QUERY });
198
232
  return !!((_c = (_b = (_a = result.data) === null || _a === void 0 ? void 0 : _a.__schema) === null || _b === void 0 ? void 0 : _b.queryType) === null || _c === void 0 ? void 0 : _c.name);
199
233
  });
200
234
  }
235
+ const errorLink = (0, error_1.onError)(({ graphQLErrors, networkError, operation, forward }) => {
236
+ // Handle errors
237
+ });
201
238
  exports.default = {
202
- createClient,
239
+ createApolloClient,
203
240
  getClient,
204
- getJwtSecret: exports.getJwtSecret,
241
+ getJwtSecret: jwt_1.getJwtSecret,
205
242
  checkConnection
206
243
  };
@@ -0,0 +1,16 @@
1
+ import { NextRequest } from "next/server";
2
+ import { IncomingMessage } from "http";
3
+ import { JWT } from 'next-auth/jwt';
4
+ import WebSocket from "ws";
5
+ export declare function getTokenFromRequest(request: NextRequest): Promise<JWT | null>;
6
+ export declare function WsClientsManager(route?: string): {
7
+ Client: (client: WebSocket) => string;
8
+ getToken(request: IncomingMessage, clientId: string): Promise<string | JWT | null>;
9
+ parseUser(request: IncomingMessage, clientId: string): Promise<any>;
10
+ delete(clientId: string): void;
11
+ getClient(clientId: string): {
12
+ ws: WebSocket;
13
+ userId?: string;
14
+ user?: any;
15
+ } | undefined;
16
+ };
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.getTokenFromRequest = getTokenFromRequest;
27
+ exports.WsClientsManager = WsClientsManager;
28
+ const debug_1 = __importDefault(require("@/lib/debug"));
29
+ const jwt_1 = require("next-auth/jwt");
30
+ const uuid_1 = require("uuid");
31
+ const debug = (0, debug_1.default)('auth');
32
+ function getTokenFromRequest(request) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const secureCookie = request.url.startsWith('https');
35
+ const cookieName = secureCookie
36
+ ? '__Secure-next-auth.session-token'
37
+ : 'next-auth.session-token';
38
+ debug(`GET /api/auth: Using cookie name: ${cookieName}, secure: ${secureCookie}`);
39
+ const token = yield (0, jwt_1.getToken)({
40
+ req: request, // Cast to any to satisfy getToken, NextRequest works
41
+ secret: process.env.NEXTAUTH_SECRET,
42
+ cookieName: cookieName,
43
+ });
44
+ return token;
45
+ });
46
+ }
47
+ function WsClientsManager(route = '') {
48
+ const clientManagerId = route + (0, uuid_1.v4)();
49
+ debug(`(${clientManagerId}): New WebSocket clients manager established.`);
50
+ const clients = new Map();
51
+ return {
52
+ Client: (client) => {
53
+ const clientId = (0, uuid_1.v4)();
54
+ clients.set(clientId, { ws: client });
55
+ debug(`(${clientManagerId}): New client (${clientId}) connected.`);
56
+ return clientId;
57
+ },
58
+ getToken(request, clientId) {
59
+ return __awaiter(this, void 0, void 0, function* () {
60
+ var _a;
61
+ const cookieHeader = request.headers.cookie;
62
+ const userAgent = request.headers['user-agent'];
63
+ const forwardedProto = request.headers['x-forwarded-proto'];
64
+ const connectionEncrypted = (_a = request.connection) === null || _a === void 0 ? void 0 : _a.encrypted;
65
+ debug(`${clientManagerId}: (${clientId}): Incoming request details - URL: ${request.url}, Method: ${request.method}, User-Agent: ${userAgent}`);
66
+ debug(`${clientManagerId}: (${clientId}): Incoming headers:`, request.headers);
67
+ debug(`${clientManagerId}: (${clientId}): Connection encrypted: ${connectionEncrypted}`);
68
+ debug(`${clientManagerId}: (${clientId}): X-Forwarded-Proto: ${forwardedProto}`);
69
+ debug(`${clientManagerId}: (${clientId}): Full cookie header:`, cookieHeader || 'No cookies header');
70
+ // Determine secure context and cookie name
71
+ const isSecure = forwardedProto === 'https' || connectionEncrypted;
72
+ const sessionCookieName = isSecure
73
+ ? '__Secure-next-auth.session-token'
74
+ : 'next-auth.session-token';
75
+ debug(`${clientManagerId}: (${clientId}): Determined secure context: ${isSecure}`);
76
+ debug(`${clientManagerId}: (${clientId}): Expecting session cookie name: ${sessionCookieName}`);
77
+ let token = null;
78
+ let payload = null;
79
+ let userId = null;
80
+ const rawToken = false; // Keep false
81
+ try {
82
+ debug(`SOCKET /api/auth (${clientId}): Preparing adapted request for getToken (raw: ${rawToken})...`);
83
+ const parsedCookies = request.headers.cookie ?
84
+ Object.fromEntries(request.headers.cookie.split('; ').map(c => {
85
+ const [key, ...val] = c.split('=');
86
+ return [key, decodeURIComponent(val.join('='))];
87
+ }))
88
+ : {};
89
+ debug(`SOCKET /api/auth (${clientId}): Parsed cookies object:`, parsedCookies);
90
+ const adaptedReq = {
91
+ headers: request.headers,
92
+ cookies: parsedCookies,
93
+ url: request.url || '',
94
+ method: request.method || 'GET',
95
+ };
96
+ debug(`SOCKET /api/auth (${clientId}): Final adapted request object for getToken:`, adaptedReq);
97
+ const getTokenParams = {
98
+ req: adaptedReq,
99
+ secret: process.env.NEXTAUTH_SECRET,
100
+ cookieName: sessionCookieName,
101
+ raw: rawToken, // Should be false now
102
+ };
103
+ debug(`${clientManagerId}: (${clientId}): Calling getToken with params:`, {
104
+ cookieName: getTokenParams.cookieName,
105
+ raw: getTokenParams.raw,
106
+ secretProvided: !!getTokenParams.secret,
107
+ });
108
+ token = yield (0, jwt_1.getToken)(getTokenParams);
109
+ debug(`${clientManagerId}: (${clientId}): getToken result received.`);
110
+ debug(`${clientManagerId}: (${clientId}): Decoded token value from getToken:`, token);
111
+ debug(`${clientManagerId}: (${clientId}): getToken result type: ${typeof token}, isNull: ${token === null}`);
112
+ if (token && typeof token === 'object' && token.sub) {
113
+ payload = token;
114
+ userId = payload.sub;
115
+ debug(`${clientManagerId}: (${clientId}): User ${userId} authenticated via decoded token from getToken.`);
116
+ }
117
+ else {
118
+ debug(`${clientManagerId}: (${clientId}): No valid token found or token is not an object with sub property.`);
119
+ }
120
+ return token;
121
+ }
122
+ catch (error) {
123
+ debug(`${clientManagerId}: (${clientId}): Error preparing adapted request for getToken:`, error);
124
+ throw error;
125
+ }
126
+ });
127
+ },
128
+ parseUser(request, clientId) {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ const token = yield this.getToken(request, clientId);
131
+ if (token && typeof token === 'object' && token.sub) {
132
+ const _a = token, { accessToken } = _a, user = __rest(_a, ["accessToken"]);
133
+ const client = clients.get(clientId);
134
+ if (client) {
135
+ client.userId = token.sub;
136
+ client.user = user;
137
+ clients.set(clientId, client);
138
+ debug(`${clientManagerId}: (${clientId}): Client parsed and updated.`);
139
+ }
140
+ else {
141
+ debug(`${clientManagerId}: (${clientId}): No client found in clients map.`);
142
+ }
143
+ return user;
144
+ }
145
+ else {
146
+ debug(`${clientManagerId}: (${clientId}): No valid token found or token is not an object with sub property.`);
147
+ }
148
+ return null;
149
+ });
150
+ },
151
+ delete(clientId) {
152
+ clients.delete(clientId);
153
+ debug(`${clientManagerId}: (${clientId}): Client deleted from clients map.`);
154
+ },
155
+ getClient(clientId) {
156
+ return clients.get(clientId);
157
+ }
158
+ };
159
+ }
@@ -0,0 +1,48 @@
1
+ import { Client } from 'nextjs-hasura-auth';
2
+ /**
3
+ * Hashes a password using bcrypt.
4
+ * @param password The plain text password.
5
+ * @returns The hashed password.
6
+ */
7
+ export declare function hashPassword(password: string): Promise<string>;
8
+ /**
9
+ * Compares a plain text password with a hash.
10
+ * @param password The plain text password.
11
+ * @param hash The hash to compare against.
12
+ * @returns True if the password matches the hash, false otherwise.
13
+ */
14
+ export declare function comparePassword(password: string, hash: string): Promise<boolean>;
15
+ interface UserProfileFromProvider {
16
+ name?: string | null;
17
+ email?: string | null;
18
+ image?: string | null;
19
+ }
20
+ export interface HasuraUser {
21
+ id: string;
22
+ name?: string | null;
23
+ email?: string | null;
24
+ email_verified?: string | null;
25
+ image?: string | null;
26
+ password?: string | null;
27
+ created_at: string;
28
+ updated_at: string;
29
+ is_admin?: boolean | null;
30
+ hasura_role?: string | null;
31
+ accounts?: {
32
+ provider: string;
33
+ provider_account_id: string;
34
+ }[];
35
+ }
36
+ /**
37
+ * Finds or creates a user and their associated account based on provider information.
38
+ * This function handles the core logic of linking OAuth/Credentials logins to Hasura users.
39
+ *
40
+ * @param client The initialized NHA Client instance.
41
+ * @param provider The OAuth provider name (e.g., 'google', 'credentials').
42
+ * @param providerAccountId The user's unique ID from the provider.
43
+ * @param profile Optional profile information from the provider (name, email, image).
44
+ * @returns The Hasura user object associated with the account.
45
+ * @throws Error if user/account processing fails.
46
+ */
47
+ export declare function getOrCreateUserAndAccount(client: Client, provider: string, providerAccountId: string, profile?: UserProfileFromProvider | null): Promise<HasuraUser>;
48
+ export {};