nextjs-hasura-auth 0.1.2 → 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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nextjs-hasura-auth",
3
3
  "shortName": "nha",
4
- "version": "0.1.2",
4
+ "version": "0.1.3",
5
5
  "engines": {
6
6
  "node": "22.14"
7
7
  },
@@ -20,10 +20,11 @@
20
20
  "test:build": "jest build.test.ts",
21
21
  "postinstall": "npm run ws -- -y",
22
22
  "ws": "npx --yes next-ws-cli@latest patch",
23
- "nha:migrate": "tsx ./migrations/nha/up.ts",
23
+ "nha:migrate": "tsx ./migrations/nha/up.ts; npm run hasura:schema; npm run hasura:types",
24
24
  "nha:unmigrate": "tsx ./migrations/nha/down.ts",
25
25
  "hasura:schema": "tsx ./lib/hasura-schema.ts",
26
- "codegen": "graphql-codegen --config codegen.ts"
26
+ "hasura:types": "graphql-codegen --config codegen.ts",
27
+ "publish": "npm run hasura:schema; npm run hasura:types; npm run build; npm publish"
27
28
  },
28
29
  "main": "dist/lib/index.js",
29
30
  "types": "dist/lib/index.d.ts",
@@ -64,7 +65,9 @@
64
65
  "@radix-ui/react-toggle": "^1.1.3",
65
66
  "@radix-ui/react-toggle-group": "^1.1.3",
66
67
  "@radix-ui/react-tooltip": "^1.2.0",
68
+ "@types/bcrypt": "^5.0.2",
67
69
  "@types/debug": "^4.1.12",
70
+ "bcrypt": "^5.1.1",
68
71
  "class-variance-authority": "^0.7.1",
69
72
  "clsx": "^2.1.1",
70
73
  "cmdk": "^1.1.1",
@@ -89,12 +92,13 @@
89
92
  "react-hook-form": "^7.55.0",
90
93
  "react-resizable-panels": "^2.1.7",
91
94
  "recharts": "^2.15.3",
95
+ "resend": "^4.3.0",
92
96
  "sonner": "^2.0.3",
93
97
  "tailwind-merge": "^3.2.0",
98
+ "ts-essentials": "^10.0.4",
94
99
  "tw-animate-css": "^1.2.5",
95
100
  "uuid": "^11.1.0",
96
101
  "vaul": "^1.1.2",
97
- "zerobounce": "^0.3.0",
98
102
  "zod": "^3.24.3"
99
103
  },
100
104
  "devDependencies": {
@@ -1,181 +0,0 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.createApolloClient = createApolloClient;
16
- exports.getClient = getClient;
17
- exports.useCreateApolloClient = useCreateApolloClient;
18
- exports.checkConnection = checkConnection;
19
- const client_1 = require("@apollo/client");
20
- const context_1 = require("@apollo/client/link/context");
21
- const utilities_1 = require("@apollo/client/utilities");
22
- const subscriptions_1 = require("@apollo/client/link/subscriptions");
23
- const graphql_ws_1 = require("graphql-ws");
24
- const cross_fetch_1 = __importDefault(require("cross-fetch"));
25
- const debug_1 = __importDefault(require("./debug"));
26
- const react_1 = require("react");
27
- const jwt_1 = require("./jwt");
28
- // Create a debug logger for this module
29
- const debug = (0, debug_1.default)('apollo');
30
- // Determine if running on client
31
- const isClient = typeof window !== 'undefined';
32
- /**
33
- * Create Apollo Client
34
- *
35
- * @param {Object} options - Options for creating the client
36
- * @param {boolean} options.ws - Use WebSocket connection
37
- * @param {string} options.token - JWT token for authorization
38
- * @param {string} options.secret - Admin secret for Hasura
39
- * @returns {ApolloClient} Apollo Client
40
- */
41
- function createApolloClient(options = {}) {
42
- // Default values
43
- const { url = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL, ws = false, token = undefined, secret = process.env.HASURA_ADMIN_SECRET } = options;
44
- if (!url) {
45
- throw new Error('❌ options.url or NEXT_PUBLIC_HASURA_GRAPHQL_URL not defined');
46
- }
47
- debug('apollo', '🔌 Creating Apollo client with endpoint:', url);
48
- // HTTP connection without authorization
49
- const publicHttpLink = new client_1.HttpLink({
50
- uri: url,
51
- fetch: cross_fetch_1.default,
52
- });
53
- // Create auth link with JWT token
54
- const authLink = token
55
- ? (0, context_1.setContext)((_, { headers }) => {
56
- return {
57
- headers: Object.assign(Object.assign({}, headers), { Authorization: `Bearer ${token}` })
58
- };
59
- })
60
- : client_1.ApolloLink.from([]);
61
- // Choose link based on token or secret availability
62
- let httpLink;
63
- if (token) {
64
- // If token provided, use it for authorization
65
- httpLink = client_1.ApolloLink.from([authLink, publicHttpLink]);
66
- }
67
- else if (secret) {
68
- // If no token but admin secret exists, use it
69
- httpLink = new client_1.HttpLink({
70
- uri: url,
71
- fetch: cross_fetch_1.default,
72
- headers: {
73
- 'x-hasura-admin-secret': secret || ''
74
- }
75
- });
76
- ;
77
- }
78
- else {
79
- // If neither token nor secret, use public access
80
- httpLink = publicHttpLink;
81
- }
82
- // Create link splitter for queries
83
- let splitLink = httpLink;
84
- // If WebSocket connection needed and we're in browser
85
- if (ws && isClient) {
86
- const wsEndpoint = url.replace('http', 'ws').replace('https', 'wss');
87
- // Configure connection parameters
88
- const connectionParams = {};
89
- if (token) {
90
- // If token provided, use it for WebSocket authorization
91
- connectionParams.headers = {
92
- Authorization: `Bearer ${token}`,
93
- };
94
- }
95
- else if (secret) {
96
- // If no token but admin secret exists, use it
97
- connectionParams.headers = {
98
- 'x-hasura-admin-secret': secret,
99
- };
100
- }
101
- // Create WebSocket client
102
- const wsLink = new subscriptions_1.GraphQLWsLink((0, graphql_ws_1.createClient)({
103
- url: wsEndpoint,
104
- connectionParams: () => connectionParams
105
- }));
106
- // Split requests: WebSocket for subscriptions, HTTP for others
107
- splitLink = (0, client_1.split)(({ query }) => {
108
- const definition = (0, utilities_1.getMainDefinition)(query);
109
- return (definition.kind === 'OperationDefinition' &&
110
- definition.operation === 'subscription');
111
- }, wsLink, httpLink);
112
- }
113
- // Create Apollo Client
114
- const apolloClient = new client_1.ApolloClient({
115
- link: splitLink,
116
- cache: new client_1.InMemoryCache(),
117
- defaultOptions: {
118
- watchQuery: {
119
- fetchPolicy: 'network-only',
120
- errorPolicy: 'all',
121
- },
122
- query: {
123
- fetchPolicy: 'network-only',
124
- errorPolicy: 'all',
125
- },
126
- mutate: {
127
- errorPolicy: 'all',
128
- },
129
- }
130
- });
131
- apolloClient.Provider = function Provider({ children }) {
132
- return <client_1.ApolloProvider client={apolloClient}>{children}</client_1.ApolloProvider>;
133
- };
134
- return apolloClient;
135
- }
136
- // Default client instance
137
- let clientInstance = null;
138
- /**
139
- * Get or create Apollo client instance
140
- * @param options Client options
141
- * @returns Apollo client instance
142
- */
143
- function getClient(options = {}) {
144
- if (!clientInstance) {
145
- clientInstance = createApolloClient(options);
146
- }
147
- return clientInstance;
148
- }
149
- /**
150
- * React hook to get Apollo client instance
151
- * @returns Apollo client instance
152
- */
153
- function useCreateApolloClient(options) {
154
- return (0, react_1.useMemo)(() => createApolloClient(options), [options]);
155
- }
156
- const CHECK_CONNECTION = (0, client_1.gql) `
157
- query CheckConnection {
158
- __schema {
159
- queryType {
160
- name
161
- }
162
- }
163
- }
164
- `;
165
- /**
166
- * Check connection to Hasura GraphQL endpoint
167
- * @returns {Promise<boolean>} True if connection is successful
168
- */
169
- function checkConnection() {
170
- return __awaiter(this, arguments, void 0, function* (client = getClient()) {
171
- var _a, _b, _c;
172
- const result = yield client.query({ query: CHECK_CONNECTION });
173
- 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);
174
- });
175
- }
176
- exports.default = {
177
- createApolloClient,
178
- getClient,
179
- getJwtSecret: jwt_1.getJwtSecret,
180
- checkConnection
181
- };
@@ -1,237 +0,0 @@
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.useSubscribe = exports.useSelect = exports.Client = void 0;
27
- exports.useClient = useClient;
28
- exports.useQuery = useQuery;
29
- exports.useSubscription = useSubscription;
30
- const client_1 = require("@apollo/client");
31
- const react_1 = require("react");
32
- const generator_1 = __importDefault(require("./generator")); // Assuming generator exports the function directly
33
- const debug_1 = __importDefault(require("./debug"));
34
- const debug = (0, debug_1.default)('nha:client');
35
- class Client {
36
- constructor(apolloClient) {
37
- if (!apolloClient) {
38
- throw new Error('❌ ApolloClient instance must be provided to the Client constructor.');
39
- }
40
- this.apolloClient = apolloClient;
41
- this.generate = generator_1.default; // Use the imported generator function
42
- debug('Client class initialized with ApolloClient instance.');
43
- }
44
- /**
45
- * Executes a GraphQL query (select operation).
46
- * @param options - Options for generating the query.
47
- * @returns Promise resolving with the query result data.
48
- * @throws ApolloError if the query fails or returns GraphQL errors.
49
- */
50
- select(options) {
51
- return __awaiter(this, void 0, void 0, function* () {
52
- debug('Executing select with options:', options);
53
- const generated = this.generate(Object.assign(Object.assign({}, options), { operation: 'query' }));
54
- try {
55
- const result = yield this.apolloClient.query({
56
- query: generated.query,
57
- variables: generated.variables,
58
- fetchPolicy: 'network-only', // Ensure fresh data for direct calls
59
- });
60
- if (result.errors) {
61
- debug('GraphQL errors during select:', result.errors);
62
- throw new client_1.ApolloError({ graphQLErrors: result.errors });
63
- }
64
- debug('Select successful, returning data:', result.data);
65
- return result.data;
66
- }
67
- catch (error) {
68
- debug('Error during select:', error);
69
- throw error; // Re-throw original error (could be ApolloError or network error)
70
- }
71
- });
72
- }
73
- /**
74
- * Executes a GraphQL insert mutation.
75
- * @param options - Options for generating the mutation.
76
- * @returns Promise resolving with the mutation result data.
77
- * @throws ApolloError if the mutation fails or returns GraphQL errors.
78
- */
79
- insert(options) {
80
- return __awaiter(this, void 0, void 0, function* () {
81
- var _a;
82
- debug('Executing insert with options:', options);
83
- const generated = this.generate(Object.assign(Object.assign({}, options), { operation: 'insert' }));
84
- try {
85
- const result = yield this.apolloClient.mutate({
86
- mutation: generated.query,
87
- variables: generated.variables,
88
- });
89
- if (result.errors) {
90
- debug('GraphQL errors during insert:', result.errors);
91
- throw new client_1.ApolloError({ graphQLErrors: result.errors });
92
- }
93
- // Check if data exists, otherwise return an empty object or handle as needed
94
- const returnData = (_a = result.data) !== null && _a !== void 0 ? _a : {};
95
- debug('Insert successful, returning data:', returnData);
96
- return returnData;
97
- }
98
- catch (error) {
99
- debug('Error during insert:', error);
100
- throw error;
101
- }
102
- });
103
- }
104
- /**
105
- * Executes a GraphQL update mutation.
106
- * @param options - Options for generating the mutation.
107
- * @returns Promise resolving with the mutation result data.
108
- * @throws ApolloError if the mutation fails or returns GraphQL errors.
109
- */
110
- update(options) {
111
- return __awaiter(this, void 0, void 0, function* () {
112
- var _a;
113
- debug('Executing update with options:', options);
114
- const generated = this.generate(Object.assign(Object.assign({}, options), { operation: 'update' }));
115
- try {
116
- const result = yield this.apolloClient.mutate({
117
- mutation: generated.query,
118
- variables: generated.variables,
119
- });
120
- if (result.errors) {
121
- debug('GraphQL errors during update:', result.errors);
122
- throw new client_1.ApolloError({ graphQLErrors: result.errors });
123
- }
124
- const returnData = (_a = result.data) !== null && _a !== void 0 ? _a : {};
125
- debug('Update successful, returning data:', returnData);
126
- return returnData;
127
- }
128
- catch (error) {
129
- debug('Error during update:', error);
130
- throw error;
131
- }
132
- });
133
- }
134
- /**
135
- * Executes a GraphQL delete mutation.
136
- * @param options - Options for generating the mutation.
137
- * @returns Promise resolving with the mutation result data.
138
- * @throws ApolloError if the mutation fails or returns GraphQL errors.
139
- */
140
- delete(options) {
141
- return __awaiter(this, void 0, void 0, function* () {
142
- var _a;
143
- debug('Executing delete with options:', options);
144
- const generated = this.generate(Object.assign(Object.assign({}, options), { operation: 'delete' }));
145
- try {
146
- const result = yield this.apolloClient.mutate({
147
- mutation: generated.query,
148
- variables: generated.variables,
149
- });
150
- if (result.errors) {
151
- debug('GraphQL errors during delete:', result.errors);
152
- throw new client_1.ApolloError({ graphQLErrors: result.errors });
153
- }
154
- const returnData = (_a = result.data) !== null && _a !== void 0 ? _a : {};
155
- debug('Delete successful, returning data:', returnData);
156
- return returnData;
157
- }
158
- catch (error) {
159
- debug('Error during delete:', error);
160
- throw error;
161
- }
162
- });
163
- }
164
- /**
165
- * Initiates a GraphQL subscription.
166
- * @param options - Options for generating the subscription.
167
- * @returns An Observable for the subscription results.
168
- */
169
- subscribe(options) {
170
- debug('Initiating subscribe with options:', options);
171
- const generated = this.generate(Object.assign(Object.assign({}, options), { operation: 'subscription' }));
172
- return this.apolloClient.subscribe({
173
- query: generated.query,
174
- variables: generated.variables,
175
- });
176
- }
177
- }
178
- exports.Client = Client;
179
- // --- React Hooks ---
180
- /**
181
- * Hook to get the Apollo Client instance.
182
- * Prefers the explicitly provided client, falls back to context, throws if none found.
183
- * @param providedClient - An optional ApolloClient instance.
184
- * @returns The ApolloClient instance.
185
- * @throws Error if no client is found.
186
- */
187
- function useClient(providedClient) {
188
- const ApolloContext = (0, client_1.getApolloContext)();
189
- const contextValue = (0, react_1.useContext)(ApolloContext);
190
- const contextClient = contextValue === null || contextValue === void 0 ? void 0 : contextValue.client;
191
- const client = providedClient !== null && providedClient !== void 0 ? providedClient : contextClient;
192
- if (!client) {
193
- throw new Error('❌ useClient: No ApolloClient instance found. Provide one directly or ensure the component is wrapped in an ApolloProvider.');
194
- }
195
- return client;
196
- }
197
- /**
198
- * Hook to perform a GraphQL query using the generator.
199
- * @template TData - The expected data type.
200
- * @param options - Options for the generator (operation is automatically set to 'query').
201
- * @param providedClient - Optional ApolloClient instance to use instead of context.
202
- * @param hookOptions - Optional additional options passed directly to Apollo's useQuery hook.
203
- * @returns An object containing loading state, data, error, and the generated query/variables.
204
- */
205
- function useQuery(options, providedClient, hookOptions) {
206
- // Memoize generator options based on a stable string representation
207
- // Important: Ensure options object structure is consistent or use a deep-stable stringify
208
- const optionsString = (0, react_1.useMemo)(() => JSON.stringify(options), [options]);
209
- const memoizedOptions = (0, react_1.useMemo)(() => JSON.parse(optionsString), [optionsString]);
210
- const client = useClient(providedClient);
211
- const generated = (0, react_1.useMemo)(() => (0, generator_1.default)(Object.assign(Object.assign({}, memoizedOptions), { operation: 'query' })), [memoizedOptions] // Depend on the memoized options object
212
- );
213
- const _a = (0, client_1.useQuery)(generated.query, Object.assign({ client: client, variables: generated.variables }, hookOptions)), { loading, error, data } = _a, rest = __rest(_a, ["loading", "error", "data"]);
214
- // Combine Apollo results with generator info
215
- return Object.assign(Object.assign({ loading, error, data }, rest), { generatedQuery: generated.query, generatedVariables: generated.variables });
216
- }
217
- /** Alias for useQuery */
218
- exports.useSelect = useQuery;
219
- /**
220
- * Hook to perform a GraphQL subscription using the generator.
221
- * @template TData - The expected data type.
222
- * @param options - Options for the generator (operation is automatically set to 'subscription').
223
- * @param providedClient - Optional ApolloClient instance to use instead of context.
224
- * @param hookOptions - Optional additional options passed directly to Apollo's useSubscription hook.
225
- * @returns An object containing loading state, data, error, and the generated query/variables.
226
- */
227
- function useSubscription(options, providedClient, hookOptions) {
228
- // Memoize generator options
229
- const optionsString = (0, react_1.useMemo)(() => JSON.stringify(options), [options]);
230
- const memoizedOptions = (0, react_1.useMemo)(() => JSON.parse(optionsString), [optionsString]);
231
- const client = useClient(providedClient);
232
- const generated = (0, react_1.useMemo)(() => (0, generator_1.default)(Object.assign(Object.assign({}, memoizedOptions), { operation: 'subscription' })), [memoizedOptions]);
233
- const _a = (0, client_1.useSubscription)(generated.query, Object.assign({ client: client, variables: generated.variables }, hookOptions)), { loading, error, data } = _a, rest = __rest(_a, ["loading", "error", "data"]);
234
- return Object.assign(Object.assign({ loading, error, data }, rest), { generatedQuery: generated.query, generatedVariables: generated.variables });
235
- }
236
- /** Alias for useSubscription */
237
- exports.useSubscribe = useSubscription;
File without changes