nextjs-hasura-auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/APOLLO.md ADDED
@@ -0,0 +1,148 @@
1
+ # Apollo Client Setup (`APOLLO.md`)
2
+
3
+ This document describes the configured Apollo Client instance used in this project (`lib/apolloClient.ts` or similar) for interacting with the Hasura GraphQL API.
4
+
5
+ ## Purpose
6
+
7
+ The Apollo Client setup provides a unified interface for sending GraphQL queries, mutations, and subscriptions to Hasura, automatically handling authentication based on the user's session.
8
+
9
+ ## Key Features
10
+
11
+ * **Split Link:** Intelligently routes GraphQL operations:
12
+ * **HTTP Requests (Queries/Mutations):** Sent via a secure Next.js API route (`/api/graphql-proxy` or equivalent). This proxy uses the user's session JWT to make authenticated requests to Hasura using the `HASURA_ADMIN_SECRET`, keeping the admin secret safe.
13
+ * **WebSocket Connections (Subscriptions):** Establishes a direct WebSocket connection to the Hasura endpoint (`NEXT_PUBLIC_HASURA_WS_ENDPOINT`).
14
+ * **Automatic Authentication:**
15
+ * **HTTP:** The proxy handles injecting appropriate `X-Hasura-*` headers based on the user's session JWT.
16
+ * **WS:** The WebSocket link automatically includes the user's session JWT in the `connectionParams` for Hasura to authenticate the connection.
17
+ * **Server-Side Rendering (SSR) / Static Site Generation (SSG) Compatibility:** The client can be initialized and used server-side for pre-fetching data.
18
+ * **Client-Side Usage:** Seamless integration with Apollo Client's React hooks (`useQuery`, `useMutation`, `useSubscription`).
19
+
20
+ ## Usage
21
+
22
+ ### Client-Side (React Components)
23
+
24
+ 1. **Wrap your application (or relevant layout) with `ApolloProvider`:**
25
+ This is typically done in your root layout file (`app/layout.tsx` or `pages/_app.tsx`). You'll need a way to get the initialized Apollo Client instance.
26
+
27
+ ```typescript
28
+ // Example in app/layout.tsx (simplified)
29
+ 'use client' // ApolloProvider likely requires client-side context
30
+
31
+ import { ApolloProvider } from '@apollo/client';
32
+ import { getClient } from '../lib/apolloClient'; // Adjust path as needed
33
+ import { SessionProvider } from 'next-auth/react'; // Needed for hooks to get session token
34
+
35
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
36
+ // Create Apollo Client using the token from the session if it exists
37
+ const client = useClient(useMemo(() => ({
38
+ token: session?.accessToken, // Pass Hasura token from session
39
+ ws: true // Enable WebSocket support
40
+ }), [session]));
41
+
42
+ return (
43
+ <html lang="en">
44
+ <body>
45
+ {/* SessionProvider needed for auth state access */}
46
+ <SessionProvider>
47
+ <ApolloProvider client={client}>
48
+ {children}
49
+ </ApolloProvider>
50
+ </SessionProvider>
51
+ </body>
52
+ </html>
53
+ );
54
+ }
55
+ ```
56
+
57
+ 2. **Use Apollo Hooks in Components:**
58
+ Import and use hooks like `useQuery`, `useMutation`, or `useSubscription` directly in your components. Combine with the `Generator` for dynamic queries (see [`GENERATOR.md`](GENERATOR.md)).
59
+
60
+ ```typescript
61
+ import { useQuery } from '@apollo/client';
62
+ import { Generator, GenerateOptions } from 'nextjs-hasura-auth'; // Assuming Generator is exported
63
+ // import schema from '...'; // Load schema
64
+
65
+ // const generate = Generator(schema);
66
+
67
+ function UserProfile({ userId }) {
68
+ // Example using Generator (assuming you have generate function)
69
+ // const { query, variables } = generate({
70
+ // operation: 'query',
71
+ // table: 'users',
72
+ // pk_columns: { id: userId },
73
+ // returning: ['id', 'name', 'email']
74
+ // });
75
+
76
+ // Or use a manually written query
77
+ const GET_USER = gql`
78
+ query GetUser($userId: uuid!) {
79
+ users_by_pk(id: $userId) {
80
+ id
81
+ name
82
+ email
83
+ }
84
+ }
85
+ `;
86
+ const { loading, error, data } = useQuery(GET_USER, {
87
+ variables: { userId }
88
+ });
89
+
90
+ if (loading) return <p>Loading...</p>;
91
+ if (error) return <p>Error: {error.message}</p>;
92
+
93
+ return (
94
+ <div>
95
+ <h1>{data.users_by_pk.name}</h1>
96
+ <p>{data.users_by_pk.email}</p>
97
+ </div>
98
+ );
99
+ }
100
+ ```
101
+
102
+ ### Server-Side (SSR/SSG/Server Components)
103
+
104
+ 1. **Get Client Instance:** Obtain the Apollo Client instance, potentially re-initializing it for server-side scope if necessary.
105
+ 2. **Fetch Data:** Use `client.query(...)` or `client.mutate(...)` directly.
106
+
107
+ ```typescript
108
+ // Example in a Server Component or getStaticProps/getServerSideProps
109
+ import { getClient } from '../lib/apolloClient'; // Adjust path
110
+ // import { Generator } from 'nextjs-hasura-auth';
111
+ // import schema from '...';
112
+ // const generate = Generator(schema);
113
+
114
+ async function getUserData(userId) {
115
+ const client = getClient(); // Get client instance
116
+
117
+ // const { query, variables } = generate({ ... });
118
+ const GET_USER = gql`...`; // Your query
119
+
120
+ try {
121
+ const { data } = await client.query({
122
+ query: GET_USER, // Use generated or manual query
123
+ variables: { userId },
124
+ // Ensure proper fetch policy for server-side needs
125
+ fetchPolicy: 'network-only',
126
+ });
127
+ return data.users_by_pk;
128
+ } catch (error) {
129
+ console.error('Error fetching user data:', error);
130
+ return null;
131
+ }
132
+ }
133
+ ```
134
+
135
+ ## Configuration (`lib/apolloClient.ts`)
136
+
137
+ The core logic resides in `lib/apolloClient.ts` (or a similar file). It typically involves:
138
+
139
+ 1. **Creating an `HttpLink`:** Points to the Next.js GraphQL proxy (e.g., `/api/graphql-proxy`).
140
+ 2. **Creating a `WebSocketLink`:**
141
+ * Uses the `graphql-ws` library.
142
+ * Connects to `NEXT_PUBLIC_HASURA_WS_ENDPOINT`.
143
+ * Configures `connectionParams` to dynamically fetch the session JWT (e.g., using `getSession()` from `next-auth/react` or a similar mechanism) and include it as `{ headers: { Authorization: Bearer <token> } }`.
144
+ 3. **Using `split`:** Combines the HTTP and WebSocket links, directing operations based on their type (queries/mutations vs. subscriptions).
145
+ 4. **Creating the `ApolloClient` instance:** Initializes the client with the combined link and a cache (e.g., `InMemoryCache`).
146
+ 5. **Handling Singleton Pattern:** Often uses a singleton pattern to avoid creating multiple client instances, especially on the server.
147
+
148
+ *(Refer to the actual `lib/apolloClient.ts` file for the precise implementation details.)*