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.
- package/APOLLO.md +106 -80
- package/GENERATOR.md +4 -5
- package/README.md +75 -14
- package/dist/lib/apollo.d.ts +9 -9
- package/dist/lib/{apollo.js → apollo.jsx} +14 -39
- package/dist/lib/auth.d.ts +16 -0
- package/dist/lib/auth.jsx +159 -0
- package/dist/lib/client.d.ts +82 -0
- package/dist/lib/client.jsx +237 -0
- package/dist/lib/generator.d.ts +2 -7
- package/dist/lib/generator.js +394 -392
- package/dist/lib/hasura-schema.d.ts +1 -0
- package/dist/lib/hasura-schema.js +72 -0
- package/dist/lib/hasura.d.ts +16 -0
- package/dist/lib/hasura.js +102 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +4 -0
- package/dist/package.json +22 -5
- package/dist/public/hasura-schema.json +7995 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +18 -4
@@ -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;
|
package/dist/lib/index.d.ts
CHANGED
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.
|
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": "
|
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
|
}
|