nextjs-hasura-auth 0.1.1 → 0.1.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/APOLLO.md CHANGED
@@ -17,13 +17,13 @@ The Apollo Client setup provides a unified interface for sending GraphQL queries
17
17
  * **Admin Secret Fallback:** If no `token` is provided, but the `HASURA_ADMIN_SECRET` environment variable is set (or a `secret` is passed explicitly), it's sent in the `x-hasura-admin-secret` header (for both HTTP and WS).
18
18
  * **Public Access:** If neither a token nor a secret is available, requests are sent without authentication headers.
19
19
  * **Server-Side Rendering (SSR) / Client-Side Rendering (CSR) Compatibility:** The client can be created and used both on the server and the client.
20
- * **Convenient Provider:** The `createClient` function returns an enhanced client instance that includes a `.Provider` component (`ApolloClientWithProvider`) for easily wrapping parts of your React application.
20
+ * **Convenient Provider:** The `createApolloClient` function returns an enhanced client instance that includes a `.Provider` component (`ApolloClientWithProvider`) for easily wrapping parts of your React application.
21
21
  * **Helper Hook:** Provides `useCreateApolloClient` hook for easily creating memoized client instances in React components, especially useful for integrating with authentication state.
22
22
 
23
23
  <details>
24
24
  <summary>Core Exports & Options (`lib/apollo.tsx`)</summary>
25
25
 
26
- * `createClient(options: ApolloOptions): ApolloClientWithProvider`: Creates a new Apollo Client instance.
26
+ * `createApolloClient(options: ApolloOptions): ApolloClientWithProvider`: Creates a new Apollo Client instance.
27
27
  * `options.url`: Hasura GraphQL endpoint URL (defaults to `process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL`).
28
28
  * `options.ws`: Boolean, enable WebSocket link for subscriptions (defaults to `false`, only works client-side).
29
29
  * `options.token`: String, JWT token for Bearer authentication.
@@ -124,26 +124,26 @@ The Apollo Client setup provides a unified interface for sending GraphQL queries
124
124
 
125
125
  ### Server-Side (SSR/SSG/Server Components/API Routes)
126
126
 
127
- 1. **Create Client Instance:** Use `createClient` directly. You need to decide how to authenticate:
127
+ 1. **Create Client Instance:** Use `createApolloClient` directly. You need to decide how to authenticate:
128
128
  * **Admin Access:** Pass the admin secret (e.g., from environment variables) using the `secret` option if you need privileged access.
129
129
  * **User Access:** If running in the context of a specific user request, obtain their Hasura JWT (e.g., from session data, request headers) and pass it using the `token` option.
130
130
 
131
131
  ```typescript
132
132
  // Example in an API Route or Server Component
133
- import { createClient } from '@/lib/apollo'; // Adjust path
133
+ import { createApolloClient } from '@/lib/apollo'; // Adjust path
134
134
  import { gql } from '@apollo/client';
135
135
  // import { getToken } from "next-auth/jwt"
136
136
 
137
137
  async function getUserDataOnServer(userId: string, request?: Request) {
138
138
  // Option 1: Use Admin Secret for privileged access
139
- // const client = createClient({
139
+ // const client = createApolloClient({
140
140
  // secret: process.env.HASURA_ADMIN_SECRET // Ensure secret is available server-side
141
141
  // });
142
142
 
143
143
  // Option 2: Use User Token (if available from request/session)
144
144
  // Example: const sessionToken = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET });
145
145
  // const hasuraToken = sessionToken?.accessToken;
146
- const client = createClient({
146
+ const client = createApolloClient({
147
147
  token: process.env.SOME_SERVICE_ACCOUNT_TOKEN_IF_NEEDED // Or fetch user token if applicable
148
148
  // url: process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL // URL can also be passed explicitly
149
149
  });
package/GENERATOR.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- This document describes the `Generator` function located in `lib/generator.ts`. Its purpose is to dynamically generate GraphQL query strings, `DocumentNode` objects (compatible with Apollo Client), and corresponding variables based on a provided set of options and a Hasura-like schema (`schema.json`). This simplifies the process of constructing GraphQL operations (queries, mutations, subscriptions) within the application.
5
+ This document describes the `Generator` function located in `lib/generator.ts`. Its purpose is to dynamically generate GraphQL query strings, `DocumentNode` objects (compatible with Apollo Client), and corresponding variables based on a provided set of options and a Hasura-like schema (`public/hasura-schema.json`). This simplifies the process of constructing GraphQL operations (queries, mutations, subscriptions) within the application.
6
6
 
7
7
  ## Usage
8
8
 
@@ -14,11 +14,10 @@ This document describes the `Generator` function located in `lib/generator.ts`.
14
14
  // Assuming 'nextjs-hasura-auth' is your published package name
15
15
  import { Generator, GenerateOptions, GenerateResult } from 'nextjs-hasura-auth';
16
16
  // Assuming schema is correctly loaded (you might need to handle schema loading differently when using the package)
17
- // import schema from './schema.json';
17
+ import schema from './public/hasura-schema.json';
18
18
 
19
19
  // Initialize the generator (Schema needs to be passed)
20
- // const generate = Generator(schema);
21
- // TODO: Document how schema should be provided when using the package
20
+ const generate = Generator(schema);
22
21
 
23
22
  // Define options for your query
24
23
  const options: GenerateOptions = {
@@ -77,7 +76,7 @@ The `generate` function accepts an object with the following properties:
77
76
 
78
77
  ## Examples
79
78
 
80
- *(Note: Variable types like `users_bool_exp`, `[users_order_by!]`, `uuid!`, `users_pk_columns_input!`, `users_set_input!`, `[users_insert_input!]!` are inferred based on schema structure and conventions. Ensure your `schema.json` reflects the actual types used by Hasura.)*
79
+ *(Note: Variable types like `users_bool_exp`, `[users_order_by!]`, `uuid!`, `users_pk_columns_input!`, `users_set_input!`, `[users_insert_input!]!` are inferred based on schema structure and conventions. Ensure your `public/hasura-schema.json` reflects the actual types used by Hasura.)*
81
80
 
82
81
  **Navigation**
83
82
 
package/README.md CHANGED
@@ -4,6 +4,7 @@ This project provides a robust starting point for building applications using Ne
4
4
 
5
5
  [![Generator Documentation](https://img.shields.io/badge/Generator%20Docs-MD-blue)](GENERATOR.md) [![Apollo Client Documentation](https://img.shields.io/badge/Apollo%20Client%20Docs-MD-orange)](APOLLO.md)
6
6
  [![Authentication Helpers Documentation](https://img.shields.io/badge/Auth%20Helpers%20Docs-MD-green)](AUTH.md) [![Hasura Admin Client Documentation](https://img.shields.io/badge/Hasura%20Client%20Docs-MD-purple)](HASURA.md)
7
+ [![Generated Client Documentation](https://img.shields.io/badge/Generated%20Client%20Docs-MD-cyan)](CLIENT.md)
7
8
 
8
9
  See [`GENERATOR.md`](GENERATOR.md) for detailed documentation on the dynamic GraphQL query generator, which simplifies creating queries, mutations, and subscriptions based on your Hasura schema.
9
10
 
@@ -13,6 +14,8 @@ See [`AUTH.md`](AUTH.md) for documentation on WebSocket and request authenticati
13
14
 
14
15
  See [`HASURA.md`](HASURA.md) for details on the Hasura Admin API client used for migrations.
15
16
 
17
+ See [`CLIENT.md`](CLIENT.md) for details on the `Client` class and React hooks that combine the Generator and Apollo Client for easy data operations.
18
+
16
19
  ## ✨ Features Checklist
17
20
 
18
21
  **Implemented:**
@@ -22,16 +25,17 @@ See [`HASURA.md`](HASURA.md) for details on the Hasura Admin API client used for
22
25
  * [x] **Unified Apollo Client:** A configured Apollo Client instance handles both authenticated HTTP requests (via the proxy) and direct, authenticated WebSocket connections for subscriptions.
23
26
  * [x] **Dynamic Query Generator:** A versatile query generator (`lib/generator.ts`) allows dynamic creation of GraphQL operations based on options and schema, suitable for client/server use.
24
27
  * [x] **WebSocket Authentication:** Real-time subscriptions connect directly to Hasura via WebSockets, authenticated using the user's session JWT.
28
+ * [x] **Generated Client Wrapper:** A `Client` class and associated React hooks (`useQuery`, `useSubscription`) that combine the Generator and Apollo Client for simplified data fetching and mutations (`lib/client.tsx`).
25
29
 
26
30
  **Planned / Future Ideas:**
27
31
 
28
- * [ ] **Convenience Hooks:** Create easy-to-use React hooks (`useQuery`, `useSubscription`, potentially a `useCRUD` hook/class) that integrate the `Generator` with Apollo Client for streamlined data fetching in components.
32
+ * [ ] **Advanced Convenience Hooks:** Potentially create a more advanced `useCRUD` hook/class built on top of the existing `Client` or hooks for even more streamlined common CRUD operations in components.
29
33
  * [ ] **Multi-Platform Builds:** Native builders for Android, iOS, MacOS, Windows, Linux, Oculus (e.g., using Tauri, Capacitor, or Electron).
30
34
  * [ ] **Unique Environment Builders:** Specific builds for Chrome Extensions, Firefox Extensions, and VSCode Extensions (including custom UI elements).
31
35
  * [ ] Additional Authentication Providers (OAuth: Google, GitHub, etc.).
32
36
  * [ ] Role-based access control examples.
33
37
  * [ ] Advanced caching strategies.
34
- * [ ] Comprehensive end-to-end testing setup.
38
+ * [ ] Comprehensive end-to-end testing setup for UI and hooks.
35
39
 
36
40
  ## 🚀 Core Concepts
37
41
 
@@ -67,7 +71,7 @@ Interaction with the Hasura GraphQL Engine is handled in two primary ways:
67
71
 
68
72
  ### 4. Dynamic Query Generation (`GENERATOR.md`)
69
73
 
70
- * The core `Generator` function in `lib/generator.ts` allows you to build complex GraphQL operations dynamically based on a simple options object and your `schema.json`.
74
+ * The core `Generator` function in `lib/generator.ts` allows you to build complex GraphQL operations dynamically based on a simple options object and your `public/hasura-schema.json`.
71
75
  * This avoids writing lengthy GraphQL query strings manually.
72
76
  * See [`GENERATOR.md`](GENERATOR.md) for full usage details and examples.
73
77
  * *Convenience hooks (like `useQuery`, `useSubscription`, `useCRUD`) are planned to further simplify using the generator within React components.*
@@ -89,10 +93,10 @@ Interaction with the Hasura GraphQL Engine is handled in two primary ways:
89
93
  │ ├── debug.ts # Debug utility
90
94
  │ └── ...
91
95
  ├── public/ # Static assets
96
+ │ ├── hasura-schema.json # Hasura GraphQL schema (for Generator)
92
97
  ├── styles/ # Global styles
93
98
  ├── .env # Environment variables (Gitignored)
94
99
  ├── GENERATOR.md # Query Generator Documentation
95
- ├── schema.json # Hasura GraphQL schema (for Generator)
96
100
  ├── next.config.js # Next.js configuration
97
101
  ├── package.json # Project dependencies and scripts
98
102
  └── tsconfig.json # TypeScript configuration
@@ -159,7 +163,7 @@ Interaction with the Hasura GraphQL Engine is handled in two primary ways:
159
163
  * Ensure `NEXTAUTH_URL` points to your application's base URL.
160
164
 
161
165
  4. **Update Hasura Schema:**
162
- Make sure the `schema.json` file in the root is up-to-date with your Hasura instance's schema. You might need to fetch this from Hasura if you've made changes.
166
+ Make sure the `public/hasura-schema.json` file in the root is up-to-date with your Hasura instance's schema. You might need to fetch this from Hasura if you've made changes.
163
167
 
164
168
  5. **Run the development server:**
165
169
  ```bash
@@ -1,15 +1,15 @@
1
1
  import { ApolloClient } from '@apollo/client';
2
- /**
3
- * Get JWT secret from environment variables
4
- * @returns {Uint8Array} Secret key for JWT signing
5
- */
6
- export declare const getJwtSecret: () => Uint8Array;
7
- interface ApolloOptions {
2
+ export interface ApolloOptions {
8
3
  url?: string;
9
4
  ws?: boolean;
10
5
  token?: string;
11
6
  secret?: string;
12
7
  }
8
+ export interface ApolloClientWithProvider extends ApolloClient<any> {
9
+ Provider: React.ComponentType<{
10
+ children: React.ReactNode;
11
+ }>;
12
+ }
13
13
  /**
14
14
  * Create Apollo Client
15
15
  *
@@ -19,7 +19,7 @@ interface ApolloOptions {
19
19
  * @param {string} options.secret - Admin secret for Hasura
20
20
  * @returns {ApolloClient} Apollo Client
21
21
  */
22
- export declare function createClient(options?: ApolloOptions): ApolloClient<import("@apollo/client").NormalizedCacheObject>;
22
+ export declare function createApolloClient(options?: ApolloOptions): ApolloClientWithProvider;
23
23
  /**
24
24
  * Get or create Apollo client instance
25
25
  * @param options Client options
@@ -30,14 +30,14 @@ export declare function getClient(options?: {}): ApolloClient<any>;
30
30
  * React hook to get Apollo client instance
31
31
  * @returns Apollo client instance
32
32
  */
33
- export declare function useClient(options: ApolloOptions): ApolloClient<import("@apollo/client").NormalizedCacheObject>;
33
+ export declare function useCreateApolloClient(options: ApolloOptions): ApolloClientWithProvider;
34
34
  /**
35
35
  * Check connection to Hasura GraphQL endpoint
36
36
  * @returns {Promise<boolean>} True if connection is successful
37
37
  */
38
38
  export declare function checkConnection(client?: ApolloClient<any>): Promise<boolean>;
39
39
  declare const _default: {
40
- createClient: typeof createClient;
40
+ createApolloClient: typeof createApolloClient;
41
41
  getClient: typeof getClient;
42
42
  getJwtSecret: () => Uint8Array;
43
43
  checkConnection: typeof checkConnection;
@@ -12,10 +12,9 @@ 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.createApolloClient = createApolloClient;
17
16
  exports.getClient = getClient;
18
- exports.useClient = useClient;
17
+ exports.useCreateApolloClient = useCreateApolloClient;
19
18
  exports.checkConnection = checkConnection;
20
19
  const client_1 = require("@apollo/client");
21
20
  const context_1 = require("@apollo/client/link/context");
@@ -25,39 +24,11 @@ const graphql_ws_1 = require("graphql-ws");
25
24
  const cross_fetch_1 = __importDefault(require("cross-fetch"));
26
25
  const debug_1 = __importDefault(require("./debug"));
27
26
  const react_1 = require("react");
27
+ const jwt_1 = require("./jwt");
28
28
  // Create a debug logger for this module
29
29
  const debug = (0, debug_1.default)('apollo');
30
30
  // Determine if running on client
31
31
  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;
58
- }
59
- };
60
- exports.getJwtSecret = getJwtSecret;
61
32
  /**
62
33
  * Create Apollo Client
63
34
  *
@@ -67,7 +38,7 @@ exports.getJwtSecret = getJwtSecret;
67
38
  * @param {string} options.secret - Admin secret for Hasura
68
39
  * @returns {ApolloClient} Apollo Client
69
40
  */
70
- function createClient(options = {}) {
41
+ function createApolloClient(options = {}) {
71
42
  // Default values
72
43
  const { url = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL, ws = false, token = undefined, secret = process.env.HASURA_ADMIN_SECRET } = options;
73
44
  if (!url) {
@@ -140,7 +111,7 @@ function createClient(options = {}) {
140
111
  }, wsLink, httpLink);
141
112
  }
142
113
  // Create Apollo Client
143
- return new client_1.ApolloClient({
114
+ const apolloClient = new client_1.ApolloClient({
144
115
  link: splitLink,
145
116
  cache: new client_1.InMemoryCache(),
146
117
  defaultOptions: {
@@ -157,6 +128,10 @@ function createClient(options = {}) {
157
128
  },
158
129
  }
159
130
  });
131
+ apolloClient.Provider = function Provider({ children }) {
132
+ return <client_1.ApolloProvider client={apolloClient}>{children}</client_1.ApolloProvider>;
133
+ };
134
+ return apolloClient;
160
135
  }
161
136
  // Default client instance
162
137
  let clientInstance = null;
@@ -167,7 +142,7 @@ let clientInstance = null;
167
142
  */
168
143
  function getClient(options = {}) {
169
144
  if (!clientInstance) {
170
- clientInstance = createClient(options);
145
+ clientInstance = createApolloClient(options);
171
146
  }
172
147
  return clientInstance;
173
148
  }
@@ -175,8 +150,8 @@ function getClient(options = {}) {
175
150
  * React hook to get Apollo client instance
176
151
  * @returns Apollo client instance
177
152
  */
178
- function useClient(options) {
179
- return (0, react_1.useMemo)(() => createClient(options), [options]);
153
+ function useCreateApolloClient(options) {
154
+ return (0, react_1.useMemo)(() => createApolloClient(options), [options]);
180
155
  }
181
156
  const CHECK_CONNECTION = (0, client_1.gql) `
182
157
  query CheckConnection {
@@ -199,8 +174,8 @@ function checkConnection() {
199
174
  });
200
175
  }
201
176
  exports.default = {
202
- createClient,
177
+ createApolloClient,
203
178
  getClient,
204
- getJwtSecret: exports.getJwtSecret,
179
+ getJwtSecret: jwt_1.getJwtSecret,
205
180
  checkConnection
206
181
  };
@@ -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,82 @@
1
+ import { ApolloClient, ApolloError, FetchResult, Observable, OperationVariables, useQuery as useApolloQuery, useSubscription as useApolloSubscription } from '@apollo/client';
2
+ import { GenerateOptions, GenerateResult } from './generator';
3
+ /**
4
+ * Represents the result structure from Apollo hooks, including potential errors.
5
+ */
6
+ export interface HookResult<TData = any> {
7
+ loading: boolean;
8
+ data?: TData;
9
+ error?: ApolloError;
10
+ [key: string]: any;
11
+ generatedQuery?: GenerateResult['query'];
12
+ generatedVariables?: GenerateResult['variables'];
13
+ }
14
+ export declare class Client {
15
+ private apolloClient;
16
+ private generate;
17
+ constructor(apolloClient: ApolloClient<any>);
18
+ /**
19
+ * Executes a GraphQL query (select operation).
20
+ * @param options - Options for generating the query.
21
+ * @returns Promise resolving with the query result data.
22
+ * @throws ApolloError if the query fails or returns GraphQL errors.
23
+ */
24
+ select<TData = any>(options: Omit<GenerateOptions, 'operation'>): Promise<TData>;
25
+ /**
26
+ * Executes a GraphQL insert mutation.
27
+ * @param options - Options for generating the mutation.
28
+ * @returns Promise resolving with the mutation result data.
29
+ * @throws ApolloError if the mutation fails or returns GraphQL errors.
30
+ */
31
+ insert<TData = any>(options: Omit<GenerateOptions, 'operation'>): Promise<TData>;
32
+ /**
33
+ * Executes a GraphQL update mutation.
34
+ * @param options - Options for generating the mutation.
35
+ * @returns Promise resolving with the mutation result data.
36
+ * @throws ApolloError if the mutation fails or returns GraphQL errors.
37
+ */
38
+ update<TData = any>(options: Omit<GenerateOptions, 'operation'>): Promise<TData>;
39
+ /**
40
+ * Executes a GraphQL delete mutation.
41
+ * @param options - Options for generating the mutation.
42
+ * @returns Promise resolving with the mutation result data.
43
+ * @throws ApolloError if the mutation fails or returns GraphQL errors.
44
+ */
45
+ delete<TData = any>(options: Omit<GenerateOptions, 'operation'>): Promise<TData>;
46
+ /**
47
+ * Initiates a GraphQL subscription.
48
+ * @param options - Options for generating the subscription.
49
+ * @returns An Observable for the subscription results.
50
+ */
51
+ subscribe<TData = any, TVariables extends OperationVariables = OperationVariables>(options: Omit<GenerateOptions, 'operation'>): Observable<FetchResult<TData>>;
52
+ }
53
+ /**
54
+ * Hook to get the Apollo Client instance.
55
+ * Prefers the explicitly provided client, falls back to context, throws if none found.
56
+ * @param providedClient - An optional ApolloClient instance.
57
+ * @returns The ApolloClient instance.
58
+ * @throws Error if no client is found.
59
+ */
60
+ export declare function useClient(providedClient?: ApolloClient<any> | null): ApolloClient<any>;
61
+ /**
62
+ * Hook to perform a GraphQL query using the generator.
63
+ * @template TData - The expected data type.
64
+ * @param options - Options for the generator (operation is automatically set to 'query').
65
+ * @param providedClient - Optional ApolloClient instance to use instead of context.
66
+ * @param hookOptions - Optional additional options passed directly to Apollo's useQuery hook.
67
+ * @returns An object containing loading state, data, error, and the generated query/variables.
68
+ */
69
+ export declare function useQuery<TData = any>(options: Omit<GenerateOptions, 'operation'>, providedClient?: ApolloClient<any> | null, hookOptions?: Omit<Parameters<typeof useApolloQuery>[1], 'variables' | 'client' | 'query'>): HookResult<TData>;
70
+ /** Alias for useQuery */
71
+ export declare const useSelect: typeof useQuery;
72
+ /**
73
+ * Hook to perform a GraphQL subscription using the generator.
74
+ * @template TData - The expected data type.
75
+ * @param options - Options for the generator (operation is automatically set to 'subscription').
76
+ * @param providedClient - Optional ApolloClient instance to use instead of context.
77
+ * @param hookOptions - Optional additional options passed directly to Apollo's useSubscription hook.
78
+ * @returns An object containing loading state, data, error, and the generated query/variables.
79
+ */
80
+ export declare function useSubscription<TData = any>(options: Omit<GenerateOptions, 'operation'>, providedClient?: ApolloClient<any> | null, hookOptions?: Omit<Parameters<typeof useApolloSubscription>[1], 'variables' | 'client' | 'query'>): HookResult<TData>;
81
+ /** Alias for useSubscription */
82
+ export declare const useSubscribe: typeof useSubscription;