nextjs-hasura-auth 0.1.0 → 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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
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
+ // lib/hasura-schema.ts
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const dotenv_1 = __importDefault(require("dotenv"));
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const path_1 = __importDefault(require("path"));
20
+ const graphql_1 = require("graphql"); // Use standard introspection query function
21
+ // Загружаем переменные окружения из корневого .env
22
+ dotenv_1.default.config({ path: path_1.default.resolve(__dirname, '../.env') });
23
+ const HASURA_GRAPHQL_URL = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL;
24
+ const HASURA_ADMIN_SECRET = process.env.HASURA_ADMIN_SECRET;
25
+ const OUTPUT_PATH = path_1.default.resolve(__dirname, '../public/hasura-schema.json');
26
+ if (!HASURA_GRAPHQL_URL) {
27
+ console.error('❌ Ошибка: NEXT_PUBLIC_HASURA_GRAPHQL_URL не определен в .env');
28
+ process.exit(1);
29
+ }
30
+ function fetchSchema() {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ var _a;
33
+ console.log(`🚀 Запрос схемы интроспекции с ${HASURA_GRAPHQL_URL}...`);
34
+ try {
35
+ const headers = {
36
+ 'Content-Type': 'application/json',
37
+ };
38
+ if (HASURA_ADMIN_SECRET) {
39
+ headers['X-Hasura-Admin-Secret'] = HASURA_ADMIN_SECRET;
40
+ console.log('🔑 Используется Hasura Admin Secret.');
41
+ }
42
+ else {
43
+ console.warn('⚠️ HASURA_ADMIN_SECRET не найден. Запрос схемы без админ-прав (может быть неполным).');
44
+ }
45
+ const response = yield axios_1.default.post(HASURA_GRAPHQL_URL, // Add non-null assertion here
46
+ {
47
+ query: (0, graphql_1.getIntrospectionQuery)(), // Use the function to get the query string
48
+ }, { headers });
49
+ if (response.data.errors) {
50
+ throw new Error(`Ошибка GraphQL при запросе схемы: ${JSON.stringify(response.data.errors)}`);
51
+ }
52
+ if (!response.data || !response.data.data || !response.data.data.__schema) {
53
+ throw new Error('Некорректный ответ от сервера Hasura. Отсутствует data.__schema.');
54
+ }
55
+ // Структурируем схему для совместимости с генератором (опционально, можно просто сохранить __schema)
56
+ // Пока оставим простую структуру, аналогичную schema.js, но только с __schema
57
+ // const structuredSchema = {
58
+ // __schema: response.data.data.__schema
59
+ // };
60
+ // Для начала сохраним полный результат интроспекции, codegen его поймет
61
+ const introspectionResult = response.data;
62
+ console.log(`💾 Сохранение схемы в ${OUTPUT_PATH}...`);
63
+ fs_1.default.writeFileSync(OUTPUT_PATH, JSON.stringify(introspectionResult, null, 2)); // Сохраняем весь результат
64
+ console.log(`✅ Схема успешно получена и сохранена в ${OUTPUT_PATH}`);
65
+ }
66
+ catch (error) {
67
+ console.error('❌ Ошибка при получении или сохранении схемы:', ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || error.message || error);
68
+ process.exit(1);
69
+ }
70
+ });
71
+ }
72
+ fetchSchema();
@@ -0,0 +1,16 @@
1
+ import { AxiosInstance } from 'axios';
2
+ interface HasuraOptions {
3
+ url: string;
4
+ secret: string;
5
+ }
6
+ export declare class Hasura {
7
+ private readonly clientInstance;
8
+ constructor(options: HasuraOptions);
9
+ get client(): AxiosInstance;
10
+ sql(sql: string, source?: string, cascade?: boolean): Promise<any>;
11
+ v1(request: {
12
+ type: string;
13
+ args: object;
14
+ }): Promise<any>;
15
+ }
16
+ export {};
@@ -0,0 +1,102 @@
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.Hasura = void 0;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const debug_1 = __importDefault(require("./debug")); // Assuming debug is in lib and alias @ points to root/src
18
+ const debug = (0, debug_1.default)('hasura');
19
+ class Hasura {
20
+ constructor(options) {
21
+ const { url, secret } = options;
22
+ if (!url || !secret) {
23
+ const errorMessage = '❌ Hasura URL or Admin Secret is missing. Check NEXT_PUBLIC_HASURA_GRAPHQL_ENDPOINT and HASURA_ADMIN_SECRET environment variables.';
24
+ debug(errorMessage);
25
+ throw new Error(errorMessage);
26
+ }
27
+ this.clientInstance = axios_1.default.create({
28
+ baseURL: url.replace('/v1/graphql', ''), // Ensure base URL is correct
29
+ headers: {
30
+ 'Content-Type': 'application/json',
31
+ 'X-Hasura-Admin-Secret': secret,
32
+ },
33
+ });
34
+ debug('✅ Hasura client initialized successfully.');
35
+ }
36
+ get client() {
37
+ return this.clientInstance;
38
+ }
39
+ sql(sql_1) {
40
+ return __awaiter(this, arguments, void 0, function* (sql, source = 'default', cascade = false) {
41
+ var _a, _b, _c;
42
+ debug('🔧 Executing SQL via /v2/query...');
43
+ try {
44
+ const response = yield this.clientInstance.post('/v2/query', {
45
+ type: 'run_sql',
46
+ args: {
47
+ source,
48
+ sql,
49
+ cascade,
50
+ },
51
+ });
52
+ debug('✅ SQL executed successfully.');
53
+ return response.data;
54
+ }
55
+ catch (error) {
56
+ const errorMessage = `❌ Error executing SQL: ${((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || error.message}`;
57
+ debug(errorMessage, ((_c = error.response) === null || _c === void 0 ? void 0 : _c.data) || error);
58
+ throw new Error(errorMessage); // Re-throw after logging
59
+ }
60
+ });
61
+ }
62
+ v1(request) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ var _a, _b, _c, _d, _e, _f, _g, _h;
65
+ debug(`🚀 Sending request to /v1/metadata: ${request.type}`);
66
+ try {
67
+ const response = yield this.clientInstance.post('/v1/metadata', request);
68
+ debug(`✅ /v1/metadata request successful for type: ${request.type}`);
69
+ return response.data;
70
+ }
71
+ catch (error) {
72
+ // Log specific Hasura errors if available, otherwise log the general error
73
+ const hasuraError = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || ((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.message) || error.message;
74
+ const errorCode = (_f = (_e = error.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.code;
75
+ const requestType = request.type; // Get the type of the request
76
+ // Don't throw an error for common "already exists/tracked/not found/defined" issues
77
+ const ignorableErrors = [
78
+ 'already exists',
79
+ 'already tracked',
80
+ 'not found',
81
+ 'already defined', // for permissions creation
82
+ ];
83
+ let isIgnorable = typeof hasuraError === 'string' && ignorableErrors.some(phrase => hasuraError.includes(phrase));
84
+ // Specifically ignore 'permission-denied' ONLY for drop/untrack operations, as it likely means "not found" in this context
85
+ if (!isIgnorable && errorCode === 'permission-denied' && (requestType.startsWith('pg_drop_') || requestType.startsWith('pg_untrack_'))) {
86
+ debug(`📝 Note: Ignoring 'permission-denied' for ${requestType}, likely means target object was not found.`);
87
+ isIgnorable = true;
88
+ }
89
+ if (isIgnorable) {
90
+ debug(`📝 Note: Non-critical issue for ${requestType} - ${hasuraError} ${errorCode ? `(Code: ${errorCode})` : ''}`);
91
+ return ((_g = error.response) === null || _g === void 0 ? void 0 : _g.data) || { info: hasuraError }; // Return info instead of throwing
92
+ }
93
+ else {
94
+ const errorMessage = `❌ Error in /v1/metadata for type ${requestType}: ${hasuraError} ${errorCode ? `(Code: ${errorCode})` : ''}`;
95
+ debug(errorMessage, ((_h = error.response) === null || _h === void 0 ? void 0 : _h.data) || error);
96
+ throw new Error(errorMessage); // Re-throw critical errors
97
+ }
98
+ }
99
+ });
100
+ }
101
+ }
102
+ exports.Hasura = Hasura;
@@ -1,3 +1,7 @@
1
1
  export * from './utils';
2
2
  export * from './apollo';
3
3
  export * from './generator';
4
+ export * from './hasura';
5
+ export * from './auth';
6
+ export * from './client';
7
+ export * from './jwt';
package/dist/lib/index.js CHANGED
@@ -18,3 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  __exportStar(require("./utils"), exports);
19
19
  __exportStar(require("./apollo"), exports);
20
20
  __exportStar(require("./generator"), exports);
21
+ __exportStar(require("./hasura"), exports);
22
+ __exportStar(require("./auth"), exports);
23
+ __exportStar(require("./client"), exports);
24
+ __exportStar(require("./jwt"), exports);
package/dist/package.json CHANGED
@@ -1,22 +1,29 @@
1
1
  {
2
2
  "name": "nextjs-hasura-auth",
3
3
  "shortName": "nha",
4
- "version": "0.1.0",
5
- "private": true,
4
+ "version": "0.1.1",
6
5
  "engines": {
7
6
  "node": "22.14"
8
7
  },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/ivansglazunov/nextjs-hasura-auth.git"
11
+ },
9
12
  "scripts": {
10
13
  "dev": "next dev --turbopack",
11
- "build": "next build && npm run build:lib",
12
- "build:lib": "tsc -p tsconfig.lib.json",
14
+ "build": "npm run build:lib && next build",
15
+ "build:lib": "rm -rf dist && tsc -p tsconfig.lib.json",
13
16
  "build:next": "next build --turbopack",
14
17
  "start": "next start --turbopack",
15
18
  "lint": "next lint --turbopack",
16
19
  "test": "jest",
17
20
  "test:build": "jest build.test.ts",
18
21
  "postinstall": "npm run ws -- -y",
19
- "ws": "npx --yes next-ws-cli@latest patch"
22
+ "ws": "npx --yes next-ws-cli@latest patch",
23
+ "nha:migrate": "tsx ./migrations/nha/up.ts",
24
+ "nha:unmigrate": "tsx ./migrations/nha/down.ts",
25
+ "hasura:schema": "tsx ./lib/hasura-schema.ts",
26
+ "codegen": "graphql-codegen --config codegen.ts"
20
27
  },
21
28
  "main": "dist/lib/index.js",
22
29
  "types": "dist/lib/index.d.ts",
@@ -85,7 +92,9 @@
85
92
  "sonner": "^2.0.3",
86
93
  "tailwind-merge": "^3.2.0",
87
94
  "tw-animate-css": "^1.2.5",
95
+ "uuid": "^11.1.0",
88
96
  "vaul": "^1.1.2",
97
+ "zerobounce": "^0.3.0",
89
98
  "zod": "^3.24.3"
90
99
  },
91
100
  "devDependencies": {
@@ -93,7 +102,12 @@
93
102
  "@babel/preset-env": "^7.26.9",
94
103
  "@babel/preset-react": "^7.26.3",
95
104
  "@babel/preset-typescript": "^7.27.0",
105
+ "@deep-foundation/hasura": "^0.0.68",
106
+ "@graphql-codegen/cli": "^5.0.5",
107
+ "@graphql-codegen/typescript": "^4.1.6",
96
108
  "@jest/globals": "^29.7.0",
109
+ "@swc/core": "^1.11.21",
110
+ "@swc/jest": "^0.2.37",
97
111
  "@tailwindcss/postcss": "^4",
98
112
  "@testing-library/jest-dom": "^6.4.0",
99
113
  "@testing-library/react": "^15.0.0",
@@ -106,8 +120,11 @@
106
120
  "babel-jest": "^29.7.0",
107
121
  "jest": "^29.7.0",
108
122
  "jest-environment-jsdom": "^29.7.0",
123
+ "prettier": "^3.5.3",
109
124
  "tailwindcss": "^4",
110
125
  "ts-jest": "^29.1.2",
126
+ "ts-node": "^10.9.2",
127
+ "tsx": "^4.19.3",
111
128
  "typescript": "^5"
112
129
  }
113
130
  }