squarefi-bff-api-module 1.29.0 → 1.29.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/dist/api/types/types.d.ts +9 -1
- package/dist/hooks/useFileUpload.d.ts +34 -0
- package/dist/hooks/useFileUpload.js +98 -0
- package/dist/hooks/useUserFiles.d.ts +49 -0
- package/dist/hooks/useUserFiles.js +118 -0
- package/dist/utils/fileStorage.d.ts +111 -0
- package/dist/utils/fileStorage.js +342 -0
- package/package.json +1 -1
- package/src/api/types/types.ts +9 -1
|
@@ -1677,7 +1677,7 @@ export declare namespace API {
|
|
|
1677
1677
|
walletAddress: string;
|
|
1678
1678
|
}
|
|
1679
1679
|
namespace DepositInstruction {
|
|
1680
|
-
type InstructionType = 'ACH' | 'FEDWIRE' | 'SWIFT';
|
|
1680
|
+
type InstructionType = 'ACH' | 'FEDWIRE' | 'SWIFT' | 'SEPA_CT';
|
|
1681
1681
|
interface Address {
|
|
1682
1682
|
city: string;
|
|
1683
1683
|
state: string;
|
|
@@ -1697,6 +1697,7 @@ export declare namespace API {
|
|
|
1697
1697
|
account_holder_name?: string;
|
|
1698
1698
|
account_routing_number?: string;
|
|
1699
1699
|
swift_bic?: string;
|
|
1700
|
+
iban?: string;
|
|
1700
1701
|
}
|
|
1701
1702
|
interface ACH extends Common {
|
|
1702
1703
|
instruction_type: 'ACH';
|
|
@@ -1714,6 +1715,13 @@ export declare namespace API {
|
|
|
1714
1715
|
institution_address: Address;
|
|
1715
1716
|
account_holder_address: Address;
|
|
1716
1717
|
}
|
|
1718
|
+
interface SEPA extends Common {
|
|
1719
|
+
instruction_type: 'SEPA_CT';
|
|
1720
|
+
iban: string;
|
|
1721
|
+
swift_bic: string;
|
|
1722
|
+
institution_address: Address;
|
|
1723
|
+
account_holder_address: Address;
|
|
1724
|
+
}
|
|
1717
1725
|
type DepositInstruction = ACH | FEDWIRE | SWIFT | Common;
|
|
1718
1726
|
}
|
|
1719
1727
|
interface OrderType {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { UploadFileResult } from '../utils/fileStorage';
|
|
2
|
+
interface UseFileUploadOptions {
|
|
3
|
+
userId: string;
|
|
4
|
+
bucket?: string;
|
|
5
|
+
authToken?: string;
|
|
6
|
+
onSuccess?: (result: UploadFileResult) => void;
|
|
7
|
+
onError?: (error: string) => void;
|
|
8
|
+
}
|
|
9
|
+
interface UseFileUploadReturn {
|
|
10
|
+
upload: (file: File, fileName?: string) => Promise<UploadFileResult>;
|
|
11
|
+
uploading: boolean;
|
|
12
|
+
progress: number;
|
|
13
|
+
error: string | null;
|
|
14
|
+
result: UploadFileResult | null;
|
|
15
|
+
reset: () => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* React хук для загрузки файлов в Supabase Storage
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { upload, uploading, error, result } = useFileUpload({
|
|
23
|
+
* userId: 'user-123',
|
|
24
|
+
* onSuccess: (result) => console.log('Загружено:', result.path),
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
28
|
+
* const file = e.target.files?.[0];
|
|
29
|
+
* if (file) await upload(file);
|
|
30
|
+
* };
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const useFileUpload: (options: UseFileUploadOptions) => UseFileUploadReturn;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.useFileUpload = void 0;
|
|
13
|
+
const react_1 = require("react");
|
|
14
|
+
const fileStorage_1 = require("../utils/fileStorage");
|
|
15
|
+
/**
|
|
16
|
+
* React хук для загрузки файлов в Supabase Storage
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { upload, uploading, error, result } = useFileUpload({
|
|
21
|
+
* userId: 'user-123',
|
|
22
|
+
* onSuccess: (result) => console.log('Загружено:', result.path),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
26
|
+
* const file = e.target.files?.[0];
|
|
27
|
+
* if (file) await upload(file);
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
const useFileUpload = (options) => {
|
|
32
|
+
const { userId, bucket, authToken, onSuccess, onError } = options;
|
|
33
|
+
const [uploading, setUploading] = (0, react_1.useState)(false);
|
|
34
|
+
const [progress, setProgress] = (0, react_1.useState)(0);
|
|
35
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
36
|
+
const [result, setResult] = (0, react_1.useState)(null);
|
|
37
|
+
const upload = (0, react_1.useCallback)((file, customFileName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
setUploading(true);
|
|
39
|
+
setProgress(0);
|
|
40
|
+
setError(null);
|
|
41
|
+
setResult(null);
|
|
42
|
+
try {
|
|
43
|
+
// Симулируем прогресс (Supabase не предоставляет реальный progress)
|
|
44
|
+
const progressInterval = setInterval(() => {
|
|
45
|
+
setProgress((prev) => Math.min(prev + 10, 90));
|
|
46
|
+
}, 100);
|
|
47
|
+
const uploadOptions = {
|
|
48
|
+
file,
|
|
49
|
+
fileName: customFileName || `${Date.now()}-${file.name}`,
|
|
50
|
+
userId,
|
|
51
|
+
bucket,
|
|
52
|
+
contentType: file.type,
|
|
53
|
+
authToken,
|
|
54
|
+
};
|
|
55
|
+
const uploadResult = yield (0, fileStorage_1.uploadFile)(uploadOptions);
|
|
56
|
+
clearInterval(progressInterval);
|
|
57
|
+
setProgress(100);
|
|
58
|
+
setResult(uploadResult);
|
|
59
|
+
if (uploadResult.success) {
|
|
60
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(uploadResult);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const errorMsg = uploadResult.error || 'Ошибка загрузки файла';
|
|
64
|
+
setError(errorMsg);
|
|
65
|
+
onError === null || onError === void 0 ? void 0 : onError(errorMsg);
|
|
66
|
+
}
|
|
67
|
+
return uploadResult;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const errorMsg = err instanceof Error ? err.message : 'Непредвиденная ошибка';
|
|
71
|
+
setError(errorMsg);
|
|
72
|
+
onError === null || onError === void 0 ? void 0 : onError(errorMsg);
|
|
73
|
+
setProgress(0);
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: errorMsg,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
setUploading(false);
|
|
81
|
+
}
|
|
82
|
+
}), [userId, bucket, authToken, onSuccess, onError]);
|
|
83
|
+
const reset = (0, react_1.useCallback)(() => {
|
|
84
|
+
setUploading(false);
|
|
85
|
+
setProgress(0);
|
|
86
|
+
setError(null);
|
|
87
|
+
setResult(null);
|
|
88
|
+
}, []);
|
|
89
|
+
return {
|
|
90
|
+
upload,
|
|
91
|
+
uploading,
|
|
92
|
+
progress,
|
|
93
|
+
error,
|
|
94
|
+
result,
|
|
95
|
+
reset,
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
exports.useFileUpload = useFileUpload;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
interface FileItem {
|
|
2
|
+
name: string;
|
|
3
|
+
id: string;
|
|
4
|
+
created_at: string;
|
|
5
|
+
updated_at: string;
|
|
6
|
+
signedUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
interface UseUserFilesOptions {
|
|
9
|
+
userId: string;
|
|
10
|
+
bucket?: string;
|
|
11
|
+
autoLoad?: boolean;
|
|
12
|
+
autoGenerateUrls?: boolean;
|
|
13
|
+
urlExpiresIn?: number;
|
|
14
|
+
authToken?: string;
|
|
15
|
+
}
|
|
16
|
+
interface UseUserFilesReturn {
|
|
17
|
+
files: FileItem[];
|
|
18
|
+
loading: boolean;
|
|
19
|
+
error: string | null;
|
|
20
|
+
reload: () => Promise<void>;
|
|
21
|
+
deleteOne: (fileName: string) => Promise<boolean>;
|
|
22
|
+
deleteMultiple: (fileNames: string[]) => Promise<boolean>;
|
|
23
|
+
getFileUrl: (fileName: string) => Promise<string | null>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* React хук для работы со списком файлов пользователя
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* const { files, loading, deleteOne, getFileUrl } = useUserFiles({
|
|
31
|
+
* userId: 'user-123',
|
|
32
|
+
* autoLoad: true,
|
|
33
|
+
* autoGenerateUrls: true,
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* return (
|
|
37
|
+
* <ul>
|
|
38
|
+
* {files.map(file => (
|
|
39
|
+
* <li key={file.id}>
|
|
40
|
+
* <a href={file.signedUrl} target="_blank">{file.name}</a>
|
|
41
|
+
* <button onClick={() => deleteOne(file.name)}>Удалить</button>
|
|
42
|
+
* </li>
|
|
43
|
+
* ))}
|
|
44
|
+
* </ul>
|
|
45
|
+
* );
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare const useUserFiles: (options: UseUserFilesOptions) => UseUserFilesReturn;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.useUserFiles = void 0;
|
|
13
|
+
const react_1 = require("react");
|
|
14
|
+
const fileStorage_1 = require("../utils/fileStorage");
|
|
15
|
+
/**
|
|
16
|
+
* React хук для работы со списком файлов пользователя
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { files, loading, deleteOne, getFileUrl } = useUserFiles({
|
|
21
|
+
* userId: 'user-123',
|
|
22
|
+
* autoLoad: true,
|
|
23
|
+
* autoGenerateUrls: true,
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <ul>
|
|
28
|
+
* {files.map(file => (
|
|
29
|
+
* <li key={file.id}>
|
|
30
|
+
* <a href={file.signedUrl} target="_blank">{file.name}</a>
|
|
31
|
+
* <button onClick={() => deleteOne(file.name)}>Удалить</button>
|
|
32
|
+
* </li>
|
|
33
|
+
* ))}
|
|
34
|
+
* </ul>
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
const useUserFiles = (options) => {
|
|
39
|
+
const { userId, bucket, autoLoad = true, autoGenerateUrls = false, urlExpiresIn = 3600, authToken, } = options;
|
|
40
|
+
const [files, setFiles] = (0, react_1.useState)([]);
|
|
41
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
42
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
43
|
+
const reload = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
setLoading(true);
|
|
45
|
+
setError(null);
|
|
46
|
+
try {
|
|
47
|
+
const userFiles = yield (0, fileStorage_1.listUserFiles)(userId, bucket, authToken);
|
|
48
|
+
let filesWithUrls = userFiles.map((file) => ({
|
|
49
|
+
name: file.name,
|
|
50
|
+
id: file.id,
|
|
51
|
+
created_at: file.created_at,
|
|
52
|
+
updated_at: file.updated_at,
|
|
53
|
+
}));
|
|
54
|
+
// Генерируем signed URLs если нужно
|
|
55
|
+
if (autoGenerateUrls) {
|
|
56
|
+
const filesWithSignedUrls = yield Promise.all(filesWithUrls.map((file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
+
const signedUrl = yield (0, fileStorage_1.getSignedUrl)({
|
|
58
|
+
path: `${userId}/${file.name}`,
|
|
59
|
+
bucket,
|
|
60
|
+
expiresIn: urlExpiresIn,
|
|
61
|
+
authToken,
|
|
62
|
+
});
|
|
63
|
+
return Object.assign(Object.assign({}, file), { signedUrl: signedUrl || undefined });
|
|
64
|
+
})));
|
|
65
|
+
filesWithUrls = filesWithSignedUrls;
|
|
66
|
+
}
|
|
67
|
+
setFiles(filesWithUrls);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const errorMsg = err instanceof Error ? err.message : 'Ошибка загрузки файлов';
|
|
71
|
+
setError(errorMsg);
|
|
72
|
+
console.error('Error loading files:', err);
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
setLoading(false);
|
|
76
|
+
}
|
|
77
|
+
}), [userId, bucket, autoGenerateUrls, urlExpiresIn, authToken]);
|
|
78
|
+
const deleteOne = (0, react_1.useCallback)((fileName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
+
const filePath = `${userId}/${fileName}`;
|
|
80
|
+
const success = yield (0, fileStorage_1.deleteFile)(filePath, bucket, authToken);
|
|
81
|
+
if (success) {
|
|
82
|
+
setFiles((prev) => prev.filter((file) => file.name !== fileName));
|
|
83
|
+
}
|
|
84
|
+
return success;
|
|
85
|
+
}), [userId, bucket, authToken]);
|
|
86
|
+
const deleteMultiple = (0, react_1.useCallback)((fileNames) => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
|
+
const filePaths = fileNames.map((name) => `${userId}/${name}`);
|
|
88
|
+
const success = yield (0, fileStorage_1.deleteFiles)(filePaths, bucket, authToken);
|
|
89
|
+
if (success) {
|
|
90
|
+
setFiles((prev) => prev.filter((file) => !fileNames.includes(file.name)));
|
|
91
|
+
}
|
|
92
|
+
return success;
|
|
93
|
+
}), [userId, bucket, authToken]);
|
|
94
|
+
const getFileUrl = (0, react_1.useCallback)((fileName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
|
+
const filePath = `${userId}/${fileName}`;
|
|
96
|
+
return yield (0, fileStorage_1.getSignedUrl)({
|
|
97
|
+
path: filePath,
|
|
98
|
+
bucket,
|
|
99
|
+
expiresIn: urlExpiresIn,
|
|
100
|
+
authToken,
|
|
101
|
+
});
|
|
102
|
+
}), [userId, bucket, urlExpiresIn, authToken]);
|
|
103
|
+
(0, react_1.useEffect)(() => {
|
|
104
|
+
if (autoLoad) {
|
|
105
|
+
reload();
|
|
106
|
+
}
|
|
107
|
+
}, [autoLoad, reload]);
|
|
108
|
+
return {
|
|
109
|
+
files,
|
|
110
|
+
loading,
|
|
111
|
+
error,
|
|
112
|
+
reload,
|
|
113
|
+
deleteOne,
|
|
114
|
+
deleteMultiple,
|
|
115
|
+
getFileUrl,
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
exports.useUserFiles = useUserFiles;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Типы для работы с файловым хранилищем
|
|
3
|
+
*/
|
|
4
|
+
export interface UploadFileOptions {
|
|
5
|
+
file: File | Blob;
|
|
6
|
+
fileName: string;
|
|
7
|
+
bucket?: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
contentType?: string;
|
|
10
|
+
cacheControl?: string;
|
|
11
|
+
upsert?: boolean;
|
|
12
|
+
authToken?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface UploadFileResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
publicUrl?: string;
|
|
17
|
+
signedUrl?: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface GetFileUrlOptions {
|
|
22
|
+
path: string;
|
|
23
|
+
bucket?: string;
|
|
24
|
+
expiresIn?: number;
|
|
25
|
+
authToken?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Названия бакетов по умолчанию
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_BUCKET = "user-files";
|
|
31
|
+
export declare const DOCUMENTS_BUCKET = "documents";
|
|
32
|
+
export declare const IMAGES_BUCKET = "images";
|
|
33
|
+
/**
|
|
34
|
+
* Загружает файл в Supabase Storage
|
|
35
|
+
* Файл сохраняется по пути: {userId}/{fileName}
|
|
36
|
+
*
|
|
37
|
+
* @param options - параметры загрузки файла
|
|
38
|
+
* @returns результат загрузки с ссылкой на файл
|
|
39
|
+
*/
|
|
40
|
+
export declare const uploadFile: (options: UploadFileOptions) => Promise<UploadFileResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Получает подписанный URL для доступа к файлу
|
|
43
|
+
*
|
|
44
|
+
* @param options - параметры получения URL
|
|
45
|
+
* @returns подписанный URL или null при ошибке
|
|
46
|
+
*/
|
|
47
|
+
export declare const getSignedUrl: (options: GetFileUrlOptions) => Promise<string | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Получает публичный URL для файла
|
|
50
|
+
*
|
|
51
|
+
* Для ПРИВАТНЫХ бакетов:
|
|
52
|
+
* - URL постоянный (не истекает)
|
|
53
|
+
* - Требует Authorization header с service role key для доступа
|
|
54
|
+
* - Используется на backend для суперадмина
|
|
55
|
+
*
|
|
56
|
+
* Для ПУБЛИЧНЫХ бакетов:
|
|
57
|
+
* - URL доступен всем без аутентификации
|
|
58
|
+
*
|
|
59
|
+
* @example Backend usage for private buckets:
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const url = getPublicUrl(filePath, bucket);
|
|
62
|
+
*
|
|
63
|
+
* // Access with service role key:
|
|
64
|
+
* fetch(url, {
|
|
65
|
+
* headers: {
|
|
66
|
+
* 'Authorization': `Bearer ${SUPABASE_SERVICE_ROLE_KEY}`
|
|
67
|
+
* }
|
|
68
|
+
* })
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @param path - путь к файлу
|
|
72
|
+
* @param bucket - название бакета
|
|
73
|
+
* @returns постоянный URL
|
|
74
|
+
*/
|
|
75
|
+
export declare const getPublicUrl: (path: string, bucket?: string) => string | null;
|
|
76
|
+
/**
|
|
77
|
+
* Удаляет файл из хранилища
|
|
78
|
+
*
|
|
79
|
+
* @param path - путь к файлу
|
|
80
|
+
* @param bucket - название бакета
|
|
81
|
+
* @param authToken - JWT token для авторизации
|
|
82
|
+
* @returns true при успешном удалении
|
|
83
|
+
*/
|
|
84
|
+
export declare const deleteFile: (path: string, bucket?: string, authToken?: string) => Promise<boolean>;
|
|
85
|
+
/**
|
|
86
|
+
* Удаляет несколько файлов из хранилища
|
|
87
|
+
*
|
|
88
|
+
* @param paths - массив путей к файлам
|
|
89
|
+
* @param bucket - название бакета
|
|
90
|
+
* @param authToken - JWT token для авторизации
|
|
91
|
+
* @returns true при успешном удалении всех файлов
|
|
92
|
+
*/
|
|
93
|
+
export declare const deleteFiles: (paths: string[], bucket?: string, authToken?: string) => Promise<boolean>;
|
|
94
|
+
/**
|
|
95
|
+
* Получает список файлов пользователя
|
|
96
|
+
*
|
|
97
|
+
* @param userId - ID пользователя
|
|
98
|
+
* @param bucket - название бакета
|
|
99
|
+
* @param authToken - JWT token для авторизации
|
|
100
|
+
* @returns список файлов или пустой массив при ошибке
|
|
101
|
+
*/
|
|
102
|
+
export declare const listUserFiles: (userId: string, bucket?: string, authToken?: string) => Promise<import("@supabase/storage-js").FileObject[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Скачивает файл из хранилища
|
|
105
|
+
*
|
|
106
|
+
* @param path - путь к файлу
|
|
107
|
+
* @param bucket - название бакета
|
|
108
|
+
* @param authToken - JWT token для авторизации
|
|
109
|
+
* @returns Blob файла или null при ошибке
|
|
110
|
+
*/
|
|
111
|
+
export declare const downloadFile: (path: string, bucket?: string, authToken?: string) => Promise<Blob | null>;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.downloadFile = exports.listUserFiles = exports.deleteFiles = exports.deleteFile = exports.getPublicUrl = exports.getSignedUrl = exports.uploadFile = exports.IMAGES_BUCKET = exports.DOCUMENTS_BUCKET = exports.DEFAULT_BUCKET = void 0;
|
|
46
|
+
const supabase_1 = require("./supabase");
|
|
47
|
+
/**
|
|
48
|
+
* Названия бакетов по умолчанию
|
|
49
|
+
*/
|
|
50
|
+
exports.DEFAULT_BUCKET = 'user-files';
|
|
51
|
+
exports.DOCUMENTS_BUCKET = 'documents';
|
|
52
|
+
exports.IMAGES_BUCKET = 'images';
|
|
53
|
+
/**
|
|
54
|
+
* Загружает файл в Supabase Storage
|
|
55
|
+
* Файл сохраняется по пути: {userId}/{fileName}
|
|
56
|
+
*
|
|
57
|
+
* @param options - параметры загрузки файла
|
|
58
|
+
* @returns результат загрузки с ссылкой на файл
|
|
59
|
+
*/
|
|
60
|
+
const uploadFile = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
const { file, fileName, bucket = exports.DEFAULT_BUCKET, userId, contentType, cacheControl = '3600', upsert = false, authToken, } = options;
|
|
62
|
+
if (!supabase_1.supabaseClient) {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Supabase client is not initialized',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
// Если передан authToken, создаем клиент с токеном
|
|
70
|
+
let client = supabase_1.supabaseClient;
|
|
71
|
+
if (authToken) {
|
|
72
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
73
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
74
|
+
global: {
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${authToken}`,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Путь к файлу: userId/fileName
|
|
82
|
+
const filePath = `${userId}/${fileName}`;
|
|
83
|
+
const { data, error } = yield client.storage.from(bucket).upload(filePath, file, {
|
|
84
|
+
contentType,
|
|
85
|
+
cacheControl,
|
|
86
|
+
upsert,
|
|
87
|
+
});
|
|
88
|
+
if (error) {
|
|
89
|
+
console.error('Error uploading file:', error);
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
error: error.message,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Получаем публичный URL
|
|
96
|
+
const { data: urlData } = client.storage.from(bucket).getPublicUrl(data.path);
|
|
97
|
+
// Получаем подписанный URL (действителен 1 час по умолчанию)
|
|
98
|
+
const { data: signedUrlData, error: signedUrlError } = yield client.storage
|
|
99
|
+
.from(bucket)
|
|
100
|
+
.createSignedUrl(data.path, 3600);
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
publicUrl: urlData.publicUrl,
|
|
104
|
+
signedUrl: signedUrlError ? undefined : signedUrlData.signedUrl,
|
|
105
|
+
path: data.path,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('Unexpected error uploading file:', error);
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
exports.uploadFile = uploadFile;
|
|
117
|
+
/**
|
|
118
|
+
* Получает подписанный URL для доступа к файлу
|
|
119
|
+
*
|
|
120
|
+
* @param options - параметры получения URL
|
|
121
|
+
* @returns подписанный URL или null при ошибке
|
|
122
|
+
*/
|
|
123
|
+
const getSignedUrl = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
|
+
const { path, bucket = exports.DEFAULT_BUCKET, expiresIn = 3600, authToken } = options;
|
|
125
|
+
if (!supabase_1.supabaseClient) {
|
|
126
|
+
console.error('Supabase client is not initialized');
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
// Если передан authToken, создаем клиент с токеном
|
|
131
|
+
let client = supabase_1.supabaseClient;
|
|
132
|
+
if (authToken) {
|
|
133
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
134
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
135
|
+
global: {
|
|
136
|
+
headers: {
|
|
137
|
+
Authorization: `Bearer ${authToken}`,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const { data, error } = yield client.storage.from(bucket).createSignedUrl(path, expiresIn);
|
|
143
|
+
if (error) {
|
|
144
|
+
console.error('Error creating signed URL:', error);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return data.signedUrl;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error('Unexpected error creating signed URL:', error);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
exports.getSignedUrl = getSignedUrl;
|
|
155
|
+
/**
|
|
156
|
+
* Получает публичный URL для файла
|
|
157
|
+
*
|
|
158
|
+
* Для ПРИВАТНЫХ бакетов:
|
|
159
|
+
* - URL постоянный (не истекает)
|
|
160
|
+
* - Требует Authorization header с service role key для доступа
|
|
161
|
+
* - Используется на backend для суперадмина
|
|
162
|
+
*
|
|
163
|
+
* Для ПУБЛИЧНЫХ бакетов:
|
|
164
|
+
* - URL доступен всем без аутентификации
|
|
165
|
+
*
|
|
166
|
+
* @example Backend usage for private buckets:
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const url = getPublicUrl(filePath, bucket);
|
|
169
|
+
*
|
|
170
|
+
* // Access with service role key:
|
|
171
|
+
* fetch(url, {
|
|
172
|
+
* headers: {
|
|
173
|
+
* 'Authorization': `Bearer ${SUPABASE_SERVICE_ROLE_KEY}`
|
|
174
|
+
* }
|
|
175
|
+
* })
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @param path - путь к файлу
|
|
179
|
+
* @param bucket - название бакета
|
|
180
|
+
* @returns постоянный URL
|
|
181
|
+
*/
|
|
182
|
+
const getPublicUrl = (path, bucket = exports.DEFAULT_BUCKET) => {
|
|
183
|
+
if (!supabase_1.supabaseClient) {
|
|
184
|
+
console.error('Supabase client is not initialized');
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const { data } = supabase_1.supabaseClient.storage.from(bucket).getPublicUrl(path);
|
|
188
|
+
return data.publicUrl;
|
|
189
|
+
};
|
|
190
|
+
exports.getPublicUrl = getPublicUrl;
|
|
191
|
+
/**
|
|
192
|
+
* Удаляет файл из хранилища
|
|
193
|
+
*
|
|
194
|
+
* @param path - путь к файлу
|
|
195
|
+
* @param bucket - название бакета
|
|
196
|
+
* @param authToken - JWT token для авторизации
|
|
197
|
+
* @returns true при успешном удалении
|
|
198
|
+
*/
|
|
199
|
+
const deleteFile = (path_1, ...args_1) => __awaiter(void 0, [path_1, ...args_1], void 0, function* (path, bucket = exports.DEFAULT_BUCKET, authToken) {
|
|
200
|
+
if (!supabase_1.supabaseClient) {
|
|
201
|
+
console.error('Supabase client is not initialized');
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
let client = supabase_1.supabaseClient;
|
|
206
|
+
if (authToken) {
|
|
207
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
208
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
209
|
+
global: {
|
|
210
|
+
headers: {
|
|
211
|
+
Authorization: `Bearer ${authToken}`,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const { error } = yield client.storage.from(bucket).remove([path]);
|
|
217
|
+
if (error) {
|
|
218
|
+
console.error('Error deleting file:', error);
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error('Unexpected error deleting file:', error);
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
exports.deleteFile = deleteFile;
|
|
229
|
+
/**
|
|
230
|
+
* Удаляет несколько файлов из хранилища
|
|
231
|
+
*
|
|
232
|
+
* @param paths - массив путей к файлам
|
|
233
|
+
* @param bucket - название бакета
|
|
234
|
+
* @param authToken - JWT token для авторизации
|
|
235
|
+
* @returns true при успешном удалении всех файлов
|
|
236
|
+
*/
|
|
237
|
+
const deleteFiles = (paths_1, ...args_1) => __awaiter(void 0, [paths_1, ...args_1], void 0, function* (paths, bucket = exports.DEFAULT_BUCKET, authToken) {
|
|
238
|
+
if (!supabase_1.supabaseClient) {
|
|
239
|
+
console.error('Supabase client is not initialized');
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
let client = supabase_1.supabaseClient;
|
|
244
|
+
if (authToken) {
|
|
245
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
246
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
247
|
+
global: {
|
|
248
|
+
headers: {
|
|
249
|
+
Authorization: `Bearer ${authToken}`,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
const { error } = yield client.storage.from(bucket).remove(paths);
|
|
255
|
+
if (error) {
|
|
256
|
+
console.error('Error deleting files:', error);
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error('Unexpected error deleting files:', error);
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
exports.deleteFiles = deleteFiles;
|
|
267
|
+
/**
|
|
268
|
+
* Получает список файлов пользователя
|
|
269
|
+
*
|
|
270
|
+
* @param userId - ID пользователя
|
|
271
|
+
* @param bucket - название бакета
|
|
272
|
+
* @param authToken - JWT token для авторизации
|
|
273
|
+
* @returns список файлов или пустой массив при ошибке
|
|
274
|
+
*/
|
|
275
|
+
const listUserFiles = (userId_1, ...args_1) => __awaiter(void 0, [userId_1, ...args_1], void 0, function* (userId, bucket = exports.DEFAULT_BUCKET, authToken) {
|
|
276
|
+
if (!supabase_1.supabaseClient) {
|
|
277
|
+
console.error('Supabase client is not initialized');
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
let client = supabase_1.supabaseClient;
|
|
282
|
+
if (authToken) {
|
|
283
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
284
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
285
|
+
global: {
|
|
286
|
+
headers: {
|
|
287
|
+
Authorization: `Bearer ${authToken}`,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const { data, error } = yield client.storage.from(bucket).list(userId);
|
|
293
|
+
if (error) {
|
|
294
|
+
console.error('Error listing files:', error);
|
|
295
|
+
return [];
|
|
296
|
+
}
|
|
297
|
+
return data || [];
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.error('Unexpected error listing files:', error);
|
|
301
|
+
return [];
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
exports.listUserFiles = listUserFiles;
|
|
305
|
+
/**
|
|
306
|
+
* Скачивает файл из хранилища
|
|
307
|
+
*
|
|
308
|
+
* @param path - путь к файлу
|
|
309
|
+
* @param bucket - название бакета
|
|
310
|
+
* @param authToken - JWT token для авторизации
|
|
311
|
+
* @returns Blob файла или null при ошибке
|
|
312
|
+
*/
|
|
313
|
+
const downloadFile = (path_1, ...args_1) => __awaiter(void 0, [path_1, ...args_1], void 0, function* (path, bucket = exports.DEFAULT_BUCKET, authToken) {
|
|
314
|
+
if (!supabase_1.supabaseClient) {
|
|
315
|
+
console.error('Supabase client is not initialized');
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
let client = supabase_1.supabaseClient;
|
|
320
|
+
if (authToken) {
|
|
321
|
+
const { createClient } = yield Promise.resolve().then(() => __importStar(require('@supabase/supabase-js')));
|
|
322
|
+
client = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLIC_KEY, {
|
|
323
|
+
global: {
|
|
324
|
+
headers: {
|
|
325
|
+
Authorization: `Bearer ${authToken}`,
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
const { data, error } = yield client.storage.from(bucket).download(path);
|
|
331
|
+
if (error) {
|
|
332
|
+
console.error('Error downloading file:', error);
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
return data;
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error('Unexpected error downloading file:', error);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
exports.downloadFile = downloadFile;
|
package/package.json
CHANGED
package/src/api/types/types.ts
CHANGED
|
@@ -2163,7 +2163,7 @@ export namespace API {
|
|
|
2163
2163
|
}
|
|
2164
2164
|
|
|
2165
2165
|
export namespace DepositInstruction {
|
|
2166
|
-
export type InstructionType = 'ACH' | 'FEDWIRE' | 'SWIFT';
|
|
2166
|
+
export type InstructionType = 'ACH' | 'FEDWIRE' | 'SWIFT' | 'SEPA_CT';
|
|
2167
2167
|
|
|
2168
2168
|
export interface Address {
|
|
2169
2169
|
city: string;
|
|
@@ -2185,6 +2185,7 @@ export namespace API {
|
|
|
2185
2185
|
account_holder_name?: string;
|
|
2186
2186
|
account_routing_number?: string;
|
|
2187
2187
|
swift_bic?: string;
|
|
2188
|
+
iban?: string;
|
|
2188
2189
|
}
|
|
2189
2190
|
export interface ACH extends Common {
|
|
2190
2191
|
instruction_type: 'ACH';
|
|
@@ -2203,6 +2204,13 @@ export namespace API {
|
|
|
2203
2204
|
institution_address: Address;
|
|
2204
2205
|
account_holder_address: Address;
|
|
2205
2206
|
}
|
|
2207
|
+
export interface SEPA extends Common {
|
|
2208
|
+
instruction_type: 'SEPA_CT';
|
|
2209
|
+
iban: string;
|
|
2210
|
+
swift_bic: string;
|
|
2211
|
+
institution_address: Address;
|
|
2212
|
+
account_holder_address: Address;
|
|
2213
|
+
}
|
|
2206
2214
|
|
|
2207
2215
|
export type DepositInstruction = ACH | FEDWIRE | SWIFT | Common;
|
|
2208
2216
|
}
|