n8n-nodes-binary-to-url 0.0.1 → 0.0.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.
@@ -1,206 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SupabaseStorage = void 0;
4
- const supabase_js_1 = require("@supabase/supabase-js");
5
- const stream_1 = require("stream");
6
- class SupabaseStorage {
7
- constructor(config) {
8
- this.client = (0, supabase_js_1.createClient)(config.projectUrl, config.apiKey);
9
- this.bucket = config.bucket;
10
- }
11
- async uploadStream(stream, contentType, metadata) {
12
- const fileKey = this.generateFileKey(contentType);
13
- try {
14
- // Supabase SDK doesn't support streaming uploads directly
15
- // We need to buffer the stream, but add a warning about memory usage
16
- // For large files, consider using S3 instead which supports true streaming
17
- const buffer = await this.streamToBuffer(stream);
18
- // Warn if file is large (> 10MB)
19
- if (buffer.length > 10 * 1024 * 1024) {
20
- console.warn(`Large file (${(buffer.length / 1024 / 1024).toFixed(2)}MB) being uploaded to Supabase. Consider using S3 for better streaming support.`);
21
- }
22
- const { error } = await this.client.storage.from(this.bucket).upload(fileKey, buffer, {
23
- contentType,
24
- upsert: false,
25
- cacheControl: '86400',
26
- metadata,
27
- });
28
- if (error) {
29
- if (error.message.includes('Bucket not found')) {
30
- throw new Error(`Supabase bucket "${this.bucket}" does not exist or is not accessible`);
31
- }
32
- if (error.message.includes('Permission denied')) {
33
- throw new Error(`Access denied to Supabase bucket "${this.bucket}". Check your API key and bucket permissions`);
34
- }
35
- throw new Error(`Supabase upload failed: ${error.message}`);
36
- }
37
- return {
38
- fileKey,
39
- contentType,
40
- };
41
- }
42
- catch (error) {
43
- if (error instanceof Error) {
44
- throw error;
45
- }
46
- throw new Error(`Supabase upload failed: ${String(error)}`);
47
- }
48
- }
49
- async downloadStream(fileKey) {
50
- try {
51
- // Use signed URL for true streaming download
52
- const { data: signedUrlData, error: signedUrlError } = await this.client.storage
53
- .from(this.bucket)
54
- .createSignedUrl(fileKey, 60); // 60 seconds validity
55
- if (signedUrlError || !signedUrlData) {
56
- throw new Error(`Failed to create signed URL: ${signedUrlError?.message || 'Unknown error'}`);
57
- }
58
- // Fetch the file using the signed URL to get proper streaming support
59
- const response = await fetch(signedUrlData.signedUrl);
60
- if (!response.ok) {
61
- throw new Error(`Failed to download file: ${response.statusText}`);
62
- }
63
- if (!response.body) {
64
- throw new Error(`Response body is empty`);
65
- }
66
- // Convert Web Stream to Node Stream
67
- const nodeStream = stream_1.Readable.fromWeb(response.body);
68
- const contentType = response.headers.get('content-type') || this.getContentTypeFromKey(fileKey);
69
- return {
70
- stream: nodeStream,
71
- contentType,
72
- };
73
- }
74
- catch (error) {
75
- // Fallback to the old method if signed URL fails
76
- try {
77
- const { data, error } = await this.client.storage.from(this.bucket).download(fileKey);
78
- if (error) {
79
- if (error.message.includes('Object not found') || error.message.includes('Not Found')) {
80
- throw new Error(`File not found: ${fileKey}`);
81
- }
82
- if (error.message.includes('Permission denied')) {
83
- throw new Error(`Access denied to Supabase bucket "${this.bucket}". Check your API key and bucket permissions`);
84
- }
85
- throw new Error(`Supabase download failed: ${error.message}`);
86
- }
87
- if (!data) {
88
- throw new Error(`File not found: ${fileKey}`);
89
- }
90
- const buffer = await data.arrayBuffer();
91
- const stream = stream_1.Readable.from(Buffer.from(buffer));
92
- const contentType = this.getContentTypeFromKey(fileKey);
93
- return {
94
- stream,
95
- contentType,
96
- };
97
- }
98
- catch (fallbackError) {
99
- if (fallbackError instanceof Error) {
100
- throw fallbackError;
101
- }
102
- throw new Error(`Supabase download failed: ${String(fallbackError)}`);
103
- }
104
- }
105
- }
106
- async deleteFile(fileKey) {
107
- try {
108
- const { error } = await this.client.storage.from(this.bucket).remove([fileKey]);
109
- if (error) {
110
- if (error.message.includes('Object not found')) {
111
- return;
112
- }
113
- if (error.message.includes('Permission denied')) {
114
- throw new Error(`Access denied to Supabase bucket "${this.bucket}". Check your API key and bucket permissions`);
115
- }
116
- throw new Error(`Supabase delete failed: ${error.message}`);
117
- }
118
- }
119
- catch (error) {
120
- if (error instanceof Error) {
121
- throw error;
122
- }
123
- throw new Error(`Supabase delete failed: ${String(error)}`);
124
- }
125
- }
126
- async streamToBuffer(stream) {
127
- const chunks = [];
128
- for await (const chunk of stream) {
129
- chunks.push(chunk);
130
- }
131
- return Buffer.concat(chunks);
132
- }
133
- generateFileKey(contentType) {
134
- const ext = this.getExtensionFromMimeType(contentType);
135
- const timestamp = Date.now();
136
- const random = Math.random().toString(36).substring(2, 15);
137
- return `${timestamp}-${random}${ext}`;
138
- }
139
- getExtensionFromMimeType(mimeType) {
140
- const mimeToExt = {
141
- 'image/jpeg': '.jpg',
142
- 'image/png': '.png',
143
- 'image/gif': '.gif',
144
- 'image/webp': '.webp',
145
- 'image/svg+xml': '.svg',
146
- 'image/bmp': '.bmp',
147
- 'image/tiff': '.tiff',
148
- 'image/avif': '.avif',
149
- 'video/mp4': '.mp4',
150
- 'video/webm': '.webm',
151
- 'video/quicktime': '.mov',
152
- 'video/x-msvideo': '.avi',
153
- 'video/x-matroska': '.mkv',
154
- 'application/pdf': '.pdf',
155
- 'application/zip': '.zip',
156
- 'application/x-rar-compressed': '.rar',
157
- 'application/x-7z-compressed': '.7z',
158
- 'audio/mpeg': '.mp3',
159
- 'audio/wav': '.wav',
160
- 'audio/ogg': '.ogg',
161
- 'audio/flac': '.flac',
162
- 'text/plain': '.txt',
163
- 'text/csv': '.csv',
164
- 'application/json': '.json',
165
- 'application/xml': '.xml',
166
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
167
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
168
- };
169
- return mimeToExt[mimeType] || '.bin';
170
- }
171
- getContentTypeFromKey(fileKey) {
172
- const ext = fileKey.split('.').pop()?.toLowerCase() || 'bin';
173
- const extToMime = {
174
- jpg: 'image/jpeg',
175
- jpeg: 'image/jpeg',
176
- png: 'image/png',
177
- gif: 'image/gif',
178
- webp: 'image/webp',
179
- svg: 'image/svg+xml',
180
- bmp: 'image/bmp',
181
- tiff: 'image/tiff',
182
- avif: 'image/avif',
183
- mp4: 'video/mp4',
184
- webm: 'video/webm',
185
- mov: 'video/quicktime',
186
- avi: 'video/x-msvideo',
187
- mkv: 'video/x-matroska',
188
- pdf: 'application/pdf',
189
- zip: 'application/zip',
190
- rar: 'application/x-rar-compressed',
191
- '7z': 'application/x-7z-compressed',
192
- mp3: 'audio/mpeg',
193
- wav: 'audio/wav',
194
- ogg: 'audio/ogg',
195
- flac: 'audio/flac',
196
- txt: 'text/plain',
197
- csv: 'text/csv',
198
- json: 'application/json',
199
- xml: 'application/xml',
200
- xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
201
- docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
202
- };
203
- return extToMime[ext] || 'application/octet-stream';
204
- }
205
- }
206
- exports.SupabaseStorage = SupabaseStorage;