@arela/uploader 0.0.9 → 0.1.0
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/README.md +83 -0
- package/package.json +2 -3
- package/src/index.js +603 -127
- package/upload.log +0 -158
package/README.md
CHANGED
|
@@ -1 +1,84 @@
|
|
|
1
1
|
# arela-uploader
|
|
2
|
+
|
|
3
|
+
CLI tool to upload files and directories to Supabase Storage with automatic file renaming and sanitization.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📁 Upload entire directories or individual files
|
|
8
|
+
- 🔄 Automatic file renaming to handle problematic characters
|
|
9
|
+
- 📝 Comprehensive logging (local and remote)
|
|
10
|
+
- ⚡ Retry mechanism for failed uploads
|
|
11
|
+
- 🎯 Skip duplicate files automatically
|
|
12
|
+
- 📊 Progress bars and detailed summaries
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g @arela/uploader
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Basic Upload
|
|
23
|
+
```bash
|
|
24
|
+
arela -p "my-folder"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Upload with File Renaming
|
|
28
|
+
For files with accents, special characters, or problematic names:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Preview what files would be renamed (dry run)
|
|
32
|
+
arela --rename-files --dry-run
|
|
33
|
+
|
|
34
|
+
# Actually rename and upload files
|
|
35
|
+
arela --rename-files -p "documents"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Options
|
|
39
|
+
|
|
40
|
+
- `-p, --prefix <prefix>`: Prefix path in bucket (default: "")
|
|
41
|
+
- `-r, --rename-files`: Rename files with problematic characters before uploading
|
|
42
|
+
- `--dry-run`: Show what files would be renamed without actually renaming them
|
|
43
|
+
- `-h, --help`: Display help information
|
|
44
|
+
- `-v, --version`: Display version number
|
|
45
|
+
|
|
46
|
+
## Environment Variables
|
|
47
|
+
|
|
48
|
+
Create a `.env` file in your project root:
|
|
49
|
+
|
|
50
|
+
```env
|
|
51
|
+
SUPABASE_URL=your_supabase_url
|
|
52
|
+
SUPABASE_KEY=your_supabase_anon_key
|
|
53
|
+
SUPABASE_BUCKET=your_bucket_name
|
|
54
|
+
UPLOAD_BASE_PATH=/path/to/your/files
|
|
55
|
+
UPLOAD_SOURCES=folder1|folder2|file.pdf
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## File Renaming
|
|
59
|
+
|
|
60
|
+
The tool automatically handles problematic characters by:
|
|
61
|
+
|
|
62
|
+
- Removing accents (á → a, ñ → n, etc.)
|
|
63
|
+
- Replacing special characters with safe alternatives
|
|
64
|
+
- Converting spaces to dashes
|
|
65
|
+
- Removing or replacing symbols like `{}[]~^`|"<>?*:`
|
|
66
|
+
- Handling Korean characters and other Unicode symbols
|
|
67
|
+
|
|
68
|
+
### Examples
|
|
69
|
+
|
|
70
|
+
| Original | Renamed |
|
|
71
|
+
|----------|---------|
|
|
72
|
+
| `Facturas Importación.pdf` | `Facturas-Importacion.pdf` |
|
|
73
|
+
| `File{with}brackets.pdf` | `File-with-brackets.pdf` |
|
|
74
|
+
| `Document ^& symbols.pdf` | `Document-and-symbols.pdf` |
|
|
75
|
+
| `CI & PL-20221212(멕시코용).xls` | `CI-and-PL-20221212.xls` |
|
|
76
|
+
|
|
77
|
+
## Logging
|
|
78
|
+
|
|
79
|
+
The tool maintains logs both locally (`upload.log`) and remotely in your Supabase database. Logs include:
|
|
80
|
+
|
|
81
|
+
- Upload status (success/error/skipped)
|
|
82
|
+
- File paths and sanitization changes
|
|
83
|
+
- Error messages and timestamps
|
|
84
|
+
- Rename operations
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arela/uploader",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "CLI to upload files/directories to Arela",
|
|
5
5
|
"bin": {
|
|
6
6
|
"arela": "./src/index.js"
|
|
@@ -33,8 +33,7 @@
|
|
|
33
33
|
"commander": "^13.1.0",
|
|
34
34
|
"dotenv": "^16.5.0",
|
|
35
35
|
"globby": "^14.1.0",
|
|
36
|
-
"mime-types": "^3.0.1"
|
|
37
|
-
"ora": "^8.2.0"
|
|
36
|
+
"mime-types": "^3.0.1"
|
|
38
37
|
},
|
|
39
38
|
"devDependencies": {
|
|
40
39
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
package/src/index.js
CHANGED
|
@@ -7,7 +7,6 @@ import fs from 'fs';
|
|
|
7
7
|
import { globby } from 'globby';
|
|
8
8
|
import mime from 'mime-types';
|
|
9
9
|
import { createRequire } from 'module';
|
|
10
|
-
import ora from 'ora';
|
|
11
10
|
import path from 'path';
|
|
12
11
|
|
|
13
12
|
const require = createRequire(import.meta.url);
|
|
@@ -27,14 +26,236 @@ const sources = process.env.UPLOAD_SOURCES?.split('|')
|
|
|
27
26
|
|
|
28
27
|
const supabase = createClient(supabaseUrl, supabaseKey);
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
// Pre-compiled regex patterns for better performance
|
|
30
|
+
const SANITIZATION_PATTERNS = [
|
|
31
|
+
// Character replacements (grouped for efficiency)
|
|
32
|
+
[/[áàâäãåāăą]/gi, 'a'],
|
|
33
|
+
[/[éèêëēĕėę]/gi, 'e'],
|
|
34
|
+
[/[íìîïīĭį]/gi, 'i'],
|
|
35
|
+
[/[óòôöõōŏő]/gi, 'o'],
|
|
36
|
+
[/[úùûüūŭů]/gi, 'u'],
|
|
37
|
+
[/[ñň]/gi, 'n'],
|
|
38
|
+
[/[ç]/gi, 'c'],
|
|
39
|
+
[/[ý]/gi, 'y'],
|
|
40
|
+
// Korean characters (compiled once)
|
|
41
|
+
[/[멕]/g, 'meok'],
|
|
42
|
+
[/[시]/g, 'si'],
|
|
43
|
+
[/[코]/g, 'ko'],
|
|
44
|
+
[/[용]/g, 'yong'],
|
|
45
|
+
[/[가-힣]/g, 'kr'],
|
|
46
|
+
// Unicode diacritics (after normalize)
|
|
47
|
+
[/[\u0300-\u036f]/g, ''],
|
|
48
|
+
// Problematic symbols
|
|
49
|
+
[/[\\?%*:|"<>[\]~`^]/g, '-'],
|
|
50
|
+
[/[{}]/g, '-'],
|
|
51
|
+
[/[&]/g, 'and'],
|
|
52
|
+
[/[()]/g, ''], // Remove parentheses
|
|
53
|
+
// Cleanup patterns
|
|
54
|
+
[/\s+/g, '-'], // Replace spaces with dashes
|
|
55
|
+
[/-+/g, '-'], // Replace multiple dashes with single dash
|
|
56
|
+
[/^-+|-+$/g, ''], // Remove leading/trailing dashes
|
|
57
|
+
[/^\.+/, ''], // Remove leading dots
|
|
58
|
+
[/[^\w.-]/g, ''], // Remove any remaining non-alphanumeric chars
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
// Cache for sanitized filenames to avoid repeated processing
|
|
62
|
+
const sanitizationCache = new Map();
|
|
63
|
+
|
|
64
|
+
// Enhanced sanitization function with caching and pre-compiled regex
|
|
65
|
+
const sanitizeFileName = (fileName) => {
|
|
66
|
+
// Check cache first
|
|
67
|
+
if (sanitizationCache.has(fileName)) {
|
|
68
|
+
return sanitizationCache.get(fileName);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get file extension
|
|
72
|
+
const ext = path.extname(fileName);
|
|
73
|
+
const nameWithoutExt = path.basename(fileName, ext);
|
|
74
|
+
|
|
75
|
+
// Fast path for already clean filenames
|
|
76
|
+
if (/^[a-zA-Z0-9._-]+$/.test(nameWithoutExt)) {
|
|
77
|
+
const result = fileName;
|
|
78
|
+
sanitizationCache.set(fileName, result);
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Normalize unicode first (more efficient to do once)
|
|
83
|
+
let sanitized = nameWithoutExt.normalize('NFD');
|
|
84
|
+
|
|
85
|
+
// Apply all sanitization patterns
|
|
86
|
+
for (const [pattern, replacement] of SANITIZATION_PATTERNS) {
|
|
87
|
+
sanitized = sanitized.replace(pattern, replacement);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Ensure the filename is not empty
|
|
91
|
+
if (!sanitized) {
|
|
92
|
+
sanitized = 'unnamed_file';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const result = sanitized + ext;
|
|
96
|
+
|
|
97
|
+
// Cache the result for future use
|
|
98
|
+
sanitizationCache.set(fileName, result);
|
|
99
|
+
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// Pre-compiled regex patterns for path sanitization
|
|
104
|
+
const PATH_SANITIZATION_PATTERNS = [
|
|
105
|
+
[/[\\?%*:|"<>[\]~]/g, '-'],
|
|
106
|
+
[/ +/g, ' '],
|
|
107
|
+
[/^\.+/, ''],
|
|
108
|
+
[/\/+/g, '/'],
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
// Cache for sanitized paths
|
|
112
|
+
const pathSanitizationCache = new Map();
|
|
113
|
+
|
|
114
|
+
// Batch logging system for performance
|
|
115
|
+
class LogBatcher {
|
|
116
|
+
constructor(batchSize = 50, flushInterval = 5000) {
|
|
117
|
+
this.batch = [];
|
|
118
|
+
this.batchSize = batchSize;
|
|
119
|
+
this.flushInterval = flushInterval;
|
|
120
|
+
this.lastFlush = Date.now();
|
|
121
|
+
this.flushTimer = null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
add(logEntry) {
|
|
125
|
+
this.batch.push({
|
|
126
|
+
filename: path.basename(logEntry.file),
|
|
127
|
+
path: logEntry.uploadPath,
|
|
128
|
+
status: logEntry.status,
|
|
129
|
+
message: logEntry.message,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Auto-flush if batch is full or enough time has passed
|
|
133
|
+
if (
|
|
134
|
+
this.batch.length >= this.batchSize ||
|
|
135
|
+
Date.now() - this.lastFlush > this.flushInterval
|
|
136
|
+
) {
|
|
137
|
+
this.flush();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async flush() {
|
|
142
|
+
if (this.batch.length === 0) return;
|
|
143
|
+
|
|
144
|
+
const logsToSend = [...this.batch];
|
|
145
|
+
this.batch = [];
|
|
146
|
+
this.lastFlush = Date.now();
|
|
147
|
+
|
|
148
|
+
// Clear any pending timer
|
|
149
|
+
if (this.flushTimer) {
|
|
150
|
+
clearTimeout(this.flushTimer);
|
|
151
|
+
this.flushTimer = null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const { error } = await supabase.from('upload_logs').insert(logsToSend);
|
|
156
|
+
if (error) {
|
|
157
|
+
console.error(
|
|
158
|
+
`⚠️ Error saving batch of ${logsToSend.length} logs to Supabase: ${error.message}`,
|
|
159
|
+
);
|
|
160
|
+
// Re-add failed logs to batch for retry (optional)
|
|
161
|
+
this.batch.unshift(...logsToSend);
|
|
162
|
+
} else {
|
|
163
|
+
// Only show verbose output if requested
|
|
164
|
+
if (process.env.LOG_BATCH_VERBOSE === 'true') {
|
|
165
|
+
console.log(`📊 Flushed ${logsToSend.length} logs to Supabase`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.error(`⚠️ Error during batch flush: ${err.message}`);
|
|
170
|
+
// Re-add failed logs to batch for retry (optional)
|
|
171
|
+
this.batch.unshift(...logsToSend);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Schedule auto-flush if not already scheduled
|
|
176
|
+
scheduleFlush() {
|
|
177
|
+
if (!this.flushTimer && this.batch.length > 0) {
|
|
178
|
+
this.flushTimer = setTimeout(() => {
|
|
179
|
+
this.flush();
|
|
180
|
+
}, this.flushInterval);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Force flush all pending logs (called at end of process)
|
|
185
|
+
async forceFlush() {
|
|
186
|
+
if (this.flushTimer) {
|
|
187
|
+
clearTimeout(this.flushTimer);
|
|
188
|
+
this.flushTimer = null;
|
|
189
|
+
}
|
|
190
|
+
await this.flush();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Global log batcher instance
|
|
195
|
+
const logBatcher = new LogBatcher();
|
|
196
|
+
|
|
197
|
+
// Function to manage cache size (prevent memory issues in long sessions)
|
|
198
|
+
const manageCaches = () => {
|
|
199
|
+
const MAX_CACHE_SIZE = 1000;
|
|
200
|
+
|
|
201
|
+
if (sanitizationCache.size > MAX_CACHE_SIZE) {
|
|
202
|
+
// Keep only the most recent 500 entries
|
|
203
|
+
const entries = Array.from(sanitizationCache.entries());
|
|
204
|
+
sanitizationCache.clear();
|
|
205
|
+
entries.slice(-500).forEach(([key, value]) => {
|
|
206
|
+
sanitizationCache.set(key, value);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (pathSanitizationCache.size > MAX_CACHE_SIZE) {
|
|
211
|
+
const entries = Array.from(pathSanitizationCache.entries());
|
|
212
|
+
pathSanitizationCache.clear();
|
|
213
|
+
entries.slice(-500).forEach(([key, value]) => {
|
|
214
|
+
pathSanitizationCache.set(key, value);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const sanitizePath = (inputPath) => {
|
|
220
|
+
// Check cache first
|
|
221
|
+
if (pathSanitizationCache.has(inputPath)) {
|
|
222
|
+
return pathSanitizationCache.get(inputPath);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Fast path for already clean paths
|
|
226
|
+
if (!/[\\?%*:|"<>[\]~]|^ +|^\.+|\/\/+/.test(inputPath)) {
|
|
227
|
+
pathSanitizationCache.set(inputPath, inputPath);
|
|
228
|
+
return inputPath;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let sanitized = inputPath;
|
|
232
|
+
|
|
233
|
+
// Apply path sanitization patterns
|
|
234
|
+
for (const [pattern, replacement] of PATH_SANITIZATION_PATTERNS) {
|
|
235
|
+
sanitized = sanitized.replace(pattern, replacement);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Cache the result
|
|
239
|
+
pathSanitizationCache.set(inputPath, sanitized);
|
|
240
|
+
|
|
241
|
+
return sanitized;
|
|
242
|
+
};
|
|
36
243
|
|
|
37
244
|
const sendLogToSupabase = async ({ file, uploadPath, status, message }) => {
|
|
245
|
+
// Add to batch instead of sending immediately
|
|
246
|
+
logBatcher.add({ file, uploadPath, status, message });
|
|
247
|
+
|
|
248
|
+
// Schedule auto-flush if needed
|
|
249
|
+
logBatcher.scheduleFlush();
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// Enhanced version for immediate sending (used for critical errors)
|
|
253
|
+
const sendLogToSupabaseImmediate = async ({
|
|
254
|
+
file,
|
|
255
|
+
uploadPath,
|
|
256
|
+
status,
|
|
257
|
+
message,
|
|
258
|
+
}) => {
|
|
38
259
|
const { error } = await supabase.from('upload_logs').insert([
|
|
39
260
|
{
|
|
40
261
|
filename: path.basename(file),
|
|
@@ -45,7 +266,9 @@ const sendLogToSupabase = async ({ file, uploadPath, status, message }) => {
|
|
|
45
266
|
]);
|
|
46
267
|
|
|
47
268
|
if (error) {
|
|
48
|
-
console.error(
|
|
269
|
+
console.error(
|
|
270
|
+
`⚠️ Error saving immediate log to Supabase: ${error.message}`,
|
|
271
|
+
);
|
|
49
272
|
}
|
|
50
273
|
};
|
|
51
274
|
|
|
@@ -55,7 +278,7 @@ const checkCredentials = async () => {
|
|
|
55
278
|
'⚠️ Missing Supabase credentials. Please set SUPABASE_URL, SUPABASE_KEY, and SUPABASE_BUCKET in your environment variables.',
|
|
56
279
|
);
|
|
57
280
|
writeLog('⚠️ Missing Supabase credentials.');
|
|
58
|
-
await
|
|
281
|
+
await sendLogToSupabaseImmediate({
|
|
59
282
|
file: 'Error',
|
|
60
283
|
uploadPath: 'Error',
|
|
61
284
|
status: 'error',
|
|
@@ -69,7 +292,7 @@ const checkCredentials = async () => {
|
|
|
69
292
|
if (error) {
|
|
70
293
|
console.error('⚠️ Error connecting to Supabase:', error.message);
|
|
71
294
|
writeLog(`⚠️ Error connecting to Supabase: ${error.message}`);
|
|
72
|
-
await
|
|
295
|
+
await sendLogToSupabaseImmediate({
|
|
73
296
|
file: 'Error',
|
|
74
297
|
uploadPath: 'Error',
|
|
75
298
|
status: 'error',
|
|
@@ -80,7 +303,7 @@ const checkCredentials = async () => {
|
|
|
80
303
|
} catch (err) {
|
|
81
304
|
console.error('⚠️ Error:', err.message);
|
|
82
305
|
writeLog(`⚠️ Error: ${err.message}`);
|
|
83
|
-
await
|
|
306
|
+
await sendLogToSupabaseImmediate({
|
|
84
307
|
file: 'Error',
|
|
85
308
|
uploadPath: 'Error',
|
|
86
309
|
status: 'error',
|
|
@@ -101,7 +324,7 @@ const fileExistsInBucket = async (pathInBucket) => {
|
|
|
101
324
|
if (error) {
|
|
102
325
|
console.error(`⚠️ Could not verify duplicate: ${error.message}`);
|
|
103
326
|
writeLog(`⚠️ Could not verify duplicate: ${error.message}`);
|
|
104
|
-
await
|
|
327
|
+
await sendLogToSupabaseImmediate({
|
|
105
328
|
file: 'Error',
|
|
106
329
|
uploadPath: 'Error',
|
|
107
330
|
status: 'error',
|
|
@@ -189,23 +412,326 @@ const getProcessedPaths = async () => {
|
|
|
189
412
|
|
|
190
413
|
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
191
414
|
|
|
192
|
-
const uploadWithRetry = async (uploadFn, maxRetries =
|
|
415
|
+
const uploadWithRetry = async (uploadFn, maxRetries = 5, delayMs = 2000) => {
|
|
193
416
|
let attempt = 0;
|
|
417
|
+
let lastError;
|
|
418
|
+
|
|
194
419
|
while (attempt < maxRetries) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
420
|
+
try {
|
|
421
|
+
const result = await uploadFn();
|
|
422
|
+
if (!result.error) return result;
|
|
423
|
+
lastError = result.error;
|
|
424
|
+
attempt++;
|
|
425
|
+
|
|
426
|
+
// Exponential backoff with jitter
|
|
427
|
+
if (attempt < maxRetries) {
|
|
428
|
+
const backoffDelay =
|
|
429
|
+
delayMs * Math.pow(2, attempt - 1) + Math.random() * 1000;
|
|
430
|
+
console.log(
|
|
431
|
+
`Retry ${attempt}/${maxRetries} after ${Math.round(backoffDelay)}ms...`,
|
|
432
|
+
);
|
|
433
|
+
await delay(backoffDelay);
|
|
434
|
+
}
|
|
435
|
+
} catch (error) {
|
|
436
|
+
lastError = error;
|
|
437
|
+
attempt++;
|
|
438
|
+
|
|
439
|
+
if (attempt < maxRetries) {
|
|
440
|
+
const backoffDelay =
|
|
441
|
+
delayMs * Math.pow(2, attempt - 1) + Math.random() * 1000;
|
|
442
|
+
console.log(
|
|
443
|
+
`Retry ${attempt}/${maxRetries} after ${Math.round(backoffDelay)}ms due to exception...`,
|
|
444
|
+
);
|
|
445
|
+
await delay(backoffDelay);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
199
448
|
}
|
|
200
|
-
|
|
449
|
+
|
|
450
|
+
return {
|
|
451
|
+
error: new Error(
|
|
452
|
+
`Max retries exceeded. Last error: ${lastError?.message || 'Unknown error'}`,
|
|
453
|
+
),
|
|
454
|
+
};
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
// Function to process a single file
|
|
458
|
+
const processFile = async (
|
|
459
|
+
file,
|
|
460
|
+
options,
|
|
461
|
+
basePath,
|
|
462
|
+
folder,
|
|
463
|
+
sourcePath,
|
|
464
|
+
processedPaths,
|
|
465
|
+
) => {
|
|
466
|
+
let currentFile = file;
|
|
467
|
+
let result = {
|
|
468
|
+
success: false,
|
|
469
|
+
skipped: false,
|
|
470
|
+
error: null,
|
|
471
|
+
message: '',
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
// Check if we need to rename the file
|
|
476
|
+
if (options.renameFiles) {
|
|
477
|
+
const originalName = path.basename(file);
|
|
478
|
+
const sanitizedName = sanitizeFileName(originalName);
|
|
479
|
+
|
|
480
|
+
if (originalName !== sanitizedName) {
|
|
481
|
+
const newFilePath = path.join(path.dirname(file), sanitizedName);
|
|
482
|
+
|
|
483
|
+
if (options.dryRun) {
|
|
484
|
+
result.message = `Would rename: ${originalName} → ${sanitizedName}`;
|
|
485
|
+
result.skipped = true;
|
|
486
|
+
return result;
|
|
487
|
+
} else {
|
|
488
|
+
try {
|
|
489
|
+
fs.renameSync(file, newFilePath);
|
|
490
|
+
currentFile = newFilePath;
|
|
491
|
+
writeLog(`RENAMED: ${originalName} → ${sanitizedName}`);
|
|
492
|
+
await sendLogToSupabase({
|
|
493
|
+
file: originalName,
|
|
494
|
+
uploadPath: sanitizedName,
|
|
495
|
+
status: 'renamed',
|
|
496
|
+
message: `Renamed from ${originalName}`,
|
|
497
|
+
});
|
|
498
|
+
} catch (renameError) {
|
|
499
|
+
result.error = `Failed to rename ${originalName}: ${renameError.message}`;
|
|
500
|
+
writeLog(`RENAME_ERROR: ${originalName} | ${renameError.message}`);
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const content = fs.readFileSync(currentFile);
|
|
508
|
+
const relativePathRaw = path
|
|
509
|
+
.relative(basePath, currentFile)
|
|
510
|
+
.replace(/^[\\/]+/, '')
|
|
511
|
+
.replace(/\\/g, '/');
|
|
512
|
+
|
|
513
|
+
// Always sanitize the filename for upload path
|
|
514
|
+
const pathParts = relativePathRaw.split('/');
|
|
515
|
+
const originalFileName = pathParts[pathParts.length - 1];
|
|
516
|
+
const sanitizedFileName = sanitizeFileName(originalFileName);
|
|
517
|
+
pathParts[pathParts.length - 1] = sanitizedFileName;
|
|
518
|
+
const sanitizedRelativePath = pathParts.join('/');
|
|
519
|
+
|
|
520
|
+
const uploadPathRaw = options.prefix
|
|
521
|
+
? path.posix.join(options.prefix, sanitizedRelativePath)
|
|
522
|
+
: sanitizedRelativePath;
|
|
523
|
+
const uploadPath = sanitizePath(uploadPathRaw);
|
|
524
|
+
|
|
525
|
+
if (
|
|
526
|
+
uploadPath !== uploadPathRaw ||
|
|
527
|
+
originalFileName !== sanitizedFileName
|
|
528
|
+
) {
|
|
529
|
+
writeLog(`SANITIZED: ${relativePathRaw} → ${uploadPath}`);
|
|
530
|
+
await sendLogToSupabase({
|
|
531
|
+
file: currentFile,
|
|
532
|
+
uploadPath: relativePathRaw,
|
|
533
|
+
status: 'sanitized',
|
|
534
|
+
message: `Sanitized to ${uploadPath} (Arela Version: ${version})`,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (processedPaths.has(uploadPath)) {
|
|
539
|
+
result.skipped = true;
|
|
540
|
+
result.message = `Already processed (log): ${currentFile}`;
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const contentType = mime.lookup(currentFile) || 'application/octet-stream';
|
|
545
|
+
|
|
546
|
+
const exists = await fileExistsInBucket(uploadPath);
|
|
547
|
+
|
|
548
|
+
if (exists) {
|
|
549
|
+
result.skipped = true;
|
|
550
|
+
result.message = `Skipped (already exists): ${currentFile}`;
|
|
551
|
+
writeLog(`SKIPPED: ${currentFile} -> ${uploadPath}`);
|
|
552
|
+
await sendLogToSupabase({
|
|
553
|
+
file: currentFile,
|
|
554
|
+
uploadPath,
|
|
555
|
+
status: 'skipped',
|
|
556
|
+
message: 'Already exists in bucket',
|
|
557
|
+
});
|
|
558
|
+
return result;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const { error } = await uploadWithRetry(() =>
|
|
562
|
+
supabase.storage.from(bucket).upload(uploadPath, content, {
|
|
563
|
+
upsert: true,
|
|
564
|
+
contentType,
|
|
565
|
+
metadata: {
|
|
566
|
+
originalName: path.basename(currentFile),
|
|
567
|
+
sanitizedName: path.basename(uploadPath),
|
|
568
|
+
clientPath: path.posix.join(
|
|
569
|
+
basePath,
|
|
570
|
+
folder,
|
|
571
|
+
path.relative(sourcePath, currentFile).replace(/\\/g, '/'),
|
|
572
|
+
),
|
|
573
|
+
arelaVersion: version,
|
|
574
|
+
},
|
|
575
|
+
}),
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
if (error) {
|
|
579
|
+
result.error = error.message || JSON.stringify(error);
|
|
580
|
+
writeLog(`ERROR: ${currentFile} -> ${uploadPath} | ${result.error}`);
|
|
581
|
+
await sendLogToSupabase({
|
|
582
|
+
file: currentFile,
|
|
583
|
+
uploadPath,
|
|
584
|
+
status: 'error',
|
|
585
|
+
message: result.error,
|
|
586
|
+
});
|
|
587
|
+
} else {
|
|
588
|
+
result.success = true;
|
|
589
|
+
result.message = `Uploaded ${currentFile} -> ${uploadPath}`;
|
|
590
|
+
writeLog(`SUCCESS: ${currentFile} -> ${uploadPath}`);
|
|
591
|
+
await sendLogToSupabase({
|
|
592
|
+
file: currentFile,
|
|
593
|
+
uploadPath,
|
|
594
|
+
status: 'success',
|
|
595
|
+
message: 'Uploaded successfully',
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
} catch (err) {
|
|
599
|
+
result.error = err.message || JSON.stringify(err);
|
|
600
|
+
writeLog(`ERROR: ${currentFile} | ${result.error}`);
|
|
601
|
+
await sendLogToSupabase({
|
|
602
|
+
file: currentFile,
|
|
603
|
+
uploadPath: currentFile,
|
|
604
|
+
status: 'error',
|
|
605
|
+
message: result.error,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return result;
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// Function to process files in parallel batches
|
|
613
|
+
const processFilesInBatches = async (
|
|
614
|
+
files,
|
|
615
|
+
batchSize,
|
|
616
|
+
options,
|
|
617
|
+
basePath,
|
|
618
|
+
folder,
|
|
619
|
+
sourcePath,
|
|
620
|
+
processedPaths,
|
|
621
|
+
) => {
|
|
622
|
+
let successCount = 0;
|
|
623
|
+
let failureCount = 0;
|
|
624
|
+
let skippedCount = 0;
|
|
625
|
+
|
|
626
|
+
const progressBar = new cliProgress.SingleBar({
|
|
627
|
+
format:
|
|
628
|
+
'📂 Processing [{bar}] {percentage}% | {value}/{total} files | Success: {successCount} | Errors: {failureCount} | Skipped: {skippedCount}',
|
|
629
|
+
barCompleteChar: '█',
|
|
630
|
+
barIncompleteChar: '░',
|
|
631
|
+
hideCursor: true,
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
progressBar.start(files.length, 0, {
|
|
635
|
+
successCount: 0,
|
|
636
|
+
failureCount: 0,
|
|
637
|
+
skippedCount: 0,
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
for (let i = 0; i < files.length; i += batchSize) {
|
|
641
|
+
const batch = files.slice(i, i + batchSize);
|
|
642
|
+
|
|
643
|
+
// Process batch in parallel
|
|
644
|
+
const batchResults = await Promise.all(
|
|
645
|
+
batch.map((file) =>
|
|
646
|
+
processFile(
|
|
647
|
+
file,
|
|
648
|
+
options,
|
|
649
|
+
basePath,
|
|
650
|
+
folder,
|
|
651
|
+
sourcePath,
|
|
652
|
+
processedPaths,
|
|
653
|
+
),
|
|
654
|
+
),
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
// Update counters and progress
|
|
658
|
+
for (const result of batchResults) {
|
|
659
|
+
if (result.success) {
|
|
660
|
+
successCount++;
|
|
661
|
+
} else if (result.skipped) {
|
|
662
|
+
skippedCount++;
|
|
663
|
+
} else if (result.error) {
|
|
664
|
+
failureCount++;
|
|
665
|
+
console.error(`❌ ${result.error}`);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
if (result.message && !result.error) {
|
|
669
|
+
console.log(`✅ ${result.message}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
progressBar.update(i + batch.length, {
|
|
674
|
+
successCount,
|
|
675
|
+
failureCount,
|
|
676
|
+
skippedCount,
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// Manage cache size periodically (every 100 files processed)
|
|
680
|
+
if ((i + batch.length) % 100 === 0) {
|
|
681
|
+
manageCaches();
|
|
682
|
+
// Also flush logs every 100 files to maintain responsiveness
|
|
683
|
+
await logBatcher.flush();
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// Small delay between batches to prevent overwhelming the server
|
|
687
|
+
if (i + batchSize < files.length) {
|
|
688
|
+
await delay(100);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
progressBar.stop();
|
|
693
|
+
|
|
694
|
+
return {
|
|
695
|
+
successCount,
|
|
696
|
+
failureCount,
|
|
697
|
+
skippedCount,
|
|
698
|
+
};
|
|
201
699
|
};
|
|
202
700
|
|
|
203
701
|
program
|
|
204
702
|
.name('supabase-uploader')
|
|
205
703
|
.description('CLI to upload folders from a base path to Supabase Storage')
|
|
206
|
-
.
|
|
704
|
+
.option('-v, --version', 'output the version number')
|
|
207
705
|
.option('-p, --prefix <prefix>', 'Prefix path in bucket', '')
|
|
706
|
+
.option(
|
|
707
|
+
'-r, --rename-files',
|
|
708
|
+
'Rename files with problematic characters before uploading',
|
|
709
|
+
)
|
|
710
|
+
.option(
|
|
711
|
+
'--dry-run',
|
|
712
|
+
'Show what files would be renamed without actually renaming them',
|
|
713
|
+
)
|
|
714
|
+
.option(
|
|
715
|
+
'-c, --concurrency <number>',
|
|
716
|
+
'Number of files to process concurrently (default: 3)',
|
|
717
|
+
'3',
|
|
718
|
+
)
|
|
719
|
+
.option(
|
|
720
|
+
'--show-cache-stats',
|
|
721
|
+
'Show cache statistics for performance analysis',
|
|
722
|
+
)
|
|
723
|
+
.option(
|
|
724
|
+
'--batch-size <number>',
|
|
725
|
+
'Number of logs to batch before sending to Supabase (default: 50)',
|
|
726
|
+
'50',
|
|
727
|
+
)
|
|
208
728
|
.action(async (options) => {
|
|
729
|
+
// Handle version option
|
|
730
|
+
if (options.version) {
|
|
731
|
+
console.log(version);
|
|
732
|
+
process.exit(0);
|
|
733
|
+
}
|
|
734
|
+
|
|
209
735
|
if (!basePath || !sources || sources.length === 0) {
|
|
210
736
|
console.error(
|
|
211
737
|
'⚠️ UPLOAD_BASE_PATH or UPLOAD_SOURCES not defined in environment variables.',
|
|
@@ -213,6 +739,15 @@ program
|
|
|
213
739
|
process.exit(1);
|
|
214
740
|
}
|
|
215
741
|
|
|
742
|
+
const concurrency = parseInt(options.concurrency) || 3;
|
|
743
|
+
const batchSize = parseInt(options.batchSize) || 50;
|
|
744
|
+
|
|
745
|
+
// Configure log batcher with custom batch size
|
|
746
|
+
logBatcher.batchSize = batchSize;
|
|
747
|
+
|
|
748
|
+
console.log(`🚀 Using concurrency level: ${concurrency}`);
|
|
749
|
+
console.log(`📦 Using log batch size: ${batchSize}`);
|
|
750
|
+
|
|
216
751
|
const processedPaths = await getProcessedPaths();
|
|
217
752
|
let globalSuccess = 0;
|
|
218
753
|
let globalFailure = 0;
|
|
@@ -227,122 +762,58 @@ program
|
|
|
227
762
|
? await globby([`${sourcePath}/**/*`], { onlyFiles: true })
|
|
228
763
|
: [sourcePath];
|
|
229
764
|
|
|
230
|
-
|
|
231
|
-
format: '📂 Reading [{bar}] {percentage}% | {value}/{total} files',
|
|
232
|
-
barCompleteChar: '█',
|
|
233
|
-
barIncompleteChar: '░',
|
|
234
|
-
hideCursor: true,
|
|
235
|
-
});
|
|
236
|
-
progressBar.start(files.length, 0);
|
|
237
|
-
|
|
238
|
-
let successCount = 0;
|
|
239
|
-
let failureCount = 0;
|
|
240
|
-
|
|
241
|
-
for (const file of files) {
|
|
242
|
-
progressBar.increment();
|
|
243
|
-
const content = fs.readFileSync(file);
|
|
244
|
-
const relativePathRaw = path
|
|
245
|
-
.relative(basePath, file)
|
|
246
|
-
.replace(/^[\\/]+/, '')
|
|
247
|
-
.replace(/\\/g, '/');
|
|
248
|
-
const uploadPathRaw = options.prefix
|
|
249
|
-
? path.posix.join(options.prefix, relativePathRaw)
|
|
250
|
-
: relativePathRaw;
|
|
251
|
-
const uploadPath = sanitizePath(uploadPathRaw);
|
|
252
|
-
|
|
253
|
-
if (uploadPath !== uploadPathRaw) {
|
|
254
|
-
writeLog(`SANITIZED: ${uploadPathRaw} → ${uploadPath}`);
|
|
255
|
-
await sendLogToSupabase({
|
|
256
|
-
file,
|
|
257
|
-
uploadPath: uploadPathRaw,
|
|
258
|
-
status: 'sanitized',
|
|
259
|
-
message: `Sanitized to ${uploadPath}`,
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (processedPaths.has(uploadPath)) {
|
|
264
|
-
ora().info(`⏭️ Already processed (log): ${file}`);
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
765
|
+
console.log(`📊 Found ${files.length} files to process`);
|
|
267
766
|
|
|
268
|
-
|
|
767
|
+
// Process files in parallel batches
|
|
768
|
+
const { successCount, failureCount, skippedCount } =
|
|
769
|
+
await processFilesInBatches(
|
|
770
|
+
files,
|
|
771
|
+
concurrency,
|
|
772
|
+
options,
|
|
773
|
+
basePath,
|
|
774
|
+
folder,
|
|
775
|
+
sourcePath,
|
|
776
|
+
processedPaths,
|
|
777
|
+
);
|
|
269
778
|
|
|
270
|
-
|
|
271
|
-
|
|
779
|
+
globalSuccess += successCount;
|
|
780
|
+
globalFailure += failureCount;
|
|
272
781
|
|
|
273
|
-
|
|
274
|
-
spinner.info(`⏭️ Skipped (already exists): ${file}`);
|
|
275
|
-
writeLog(`SKIPPED: ${file} -> ${uploadPath}`);
|
|
276
|
-
await sendLogToSupabase({
|
|
277
|
-
file,
|
|
278
|
-
uploadPath,
|
|
279
|
-
status: 'skipped',
|
|
280
|
-
message: 'Already exists in bucket',
|
|
281
|
-
});
|
|
282
|
-
continue;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
// await delay(5000); // TODO: Remove this delay before production
|
|
287
|
-
|
|
288
|
-
const { error } = await uploadWithRetry(() =>
|
|
289
|
-
supabase.storage.from(bucket).upload(uploadPath, content, {
|
|
290
|
-
upsert: true,
|
|
291
|
-
contentType,
|
|
292
|
-
metadata: {
|
|
293
|
-
originalName: path.basename(file),
|
|
294
|
-
clientPath: path.posix.join(
|
|
295
|
-
basePath,
|
|
296
|
-
folder,
|
|
297
|
-
path.relative(sourcePath, file).replace(/\\/g, '/'),
|
|
298
|
-
),
|
|
299
|
-
},
|
|
300
|
-
}),
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
if (error) {
|
|
304
|
-
failureCount++;
|
|
305
|
-
globalFailure++;
|
|
306
|
-
spinner.fail(
|
|
307
|
-
`❌ Failed to upload ${file}: ${JSON.stringify(error, null, 2)}`,
|
|
308
|
-
);
|
|
309
|
-
writeLog(`ERROR: ${file} -> ${uploadPath} | ${error.message}`);
|
|
310
|
-
await sendLogToSupabase({
|
|
311
|
-
file,
|
|
312
|
-
uploadPath,
|
|
313
|
-
status: 'error',
|
|
314
|
-
message: error.message,
|
|
315
|
-
});
|
|
316
|
-
} else {
|
|
317
|
-
successCount++;
|
|
318
|
-
globalSuccess++;
|
|
319
|
-
spinner.succeed(`✅ Uploaded ${file} -> ${uploadPath}`);
|
|
320
|
-
writeLog(`SUCCESS: ${file} -> ${uploadPath}`);
|
|
321
|
-
await sendLogToSupabase({
|
|
322
|
-
file,
|
|
323
|
-
uploadPath,
|
|
324
|
-
status: 'success',
|
|
325
|
-
message: 'Uploaded successfully',
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
} catch (err) {
|
|
329
|
-
spinner.fail(`❌ Error uploading ${file}: ${err.message}`);
|
|
330
|
-
writeLog(`❌ Error uploading ${file}: ${err.message}`);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
progressBar.stop();
|
|
335
|
-
|
|
336
|
-
console.log(`\n📦 Upload Summary:`);
|
|
782
|
+
console.log(`\n📦 Upload Summary for ${folder}:`);
|
|
337
783
|
console.log(` ✅ Successfully uploaded files: ${successCount}`);
|
|
338
784
|
console.log(` ❌ Files with errors: ${failureCount}`);
|
|
339
|
-
console.log(
|
|
340
|
-
` ⏭️ Files skipped (already exist): ${files.length - successCount - failureCount}`,
|
|
341
|
-
);
|
|
785
|
+
console.log(` ⏭️ Files skipped (already exist): ${skippedCount}`);
|
|
342
786
|
console.log(` 📜 Log file: ${logFilePath} \n`);
|
|
343
787
|
|
|
788
|
+
// Show cache statistics if requested
|
|
789
|
+
if (options.showCacheStats) {
|
|
790
|
+
console.log(`📊 Cache Statistics:`);
|
|
791
|
+
console.log(
|
|
792
|
+
` 🗂️ Filename sanitization cache: ${sanitizationCache.size} entries`,
|
|
793
|
+
);
|
|
794
|
+
console.log(
|
|
795
|
+
` 📁 Path sanitization cache: ${pathSanitizationCache.size} entries`,
|
|
796
|
+
);
|
|
797
|
+
console.log(
|
|
798
|
+
` 📋 Log batch pending: ${logBatcher.batch.length} entries`,
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
// Calculate cache hit rate (rough estimation)
|
|
802
|
+
const totalProcessed = successCount + failureCount + skippedCount;
|
|
803
|
+
const estimatedCacheHitRate =
|
|
804
|
+
totalProcessed > 0
|
|
805
|
+
? Math.round(
|
|
806
|
+
((totalProcessed - sanitizationCache.size) / totalProcessed) *
|
|
807
|
+
100,
|
|
808
|
+
)
|
|
809
|
+
: 0;
|
|
810
|
+
console.log(
|
|
811
|
+
` 🎯 Estimated cache hit rate: ${Math.max(0, estimatedCacheHitRate)}%\n`,
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
|
|
344
815
|
writeLog(
|
|
345
|
-
`📦 Upload Summary for folder ${folder}: Success: ${successCount}, Errors: ${failureCount}, Skipped: ${
|
|
816
|
+
`📦 Upload Summary for folder ${folder}: Success: ${successCount}, Errors: ${failureCount}, Skipped: ${skippedCount}`,
|
|
346
817
|
);
|
|
347
818
|
} catch (err) {
|
|
348
819
|
console.error(`⚠️ Error processing folder ${folder}:`, err.message);
|
|
@@ -353,9 +824,14 @@ program
|
|
|
353
824
|
status: 'error',
|
|
354
825
|
message: err.message,
|
|
355
826
|
});
|
|
827
|
+
globalFailure++;
|
|
356
828
|
}
|
|
357
829
|
}
|
|
358
830
|
|
|
831
|
+
// Force flush any remaining logs before finishing
|
|
832
|
+
console.log(`📤 Flushing remaining logs...`);
|
|
833
|
+
await logBatcher.forceFlush();
|
|
834
|
+
|
|
359
835
|
console.log(`🎯 Upload completed.`);
|
|
360
836
|
console.log(` ✅ Total uploaded: ${globalSuccess}`);
|
|
361
837
|
console.log(` ❌ Total with errors: ${globalFailure}`);
|
package/upload.log
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
[2025-05-13T19:46:47.620Z] SKIPPED: ../../Documents/2023/2003180/VU_3429_070_2003180.xml -> 2023/2003180/VU_3429_070_2003180.xml
|
|
2
|
-
[2025-05-13T19:46:47.650Z] SKIPPED: ../../Documents/2023/2003189/VU_3429_070_2003189.xml -> 2023/2003189/VU_3429_070_2003189.xml
|
|
3
|
-
[2025-05-13T19:46:47.662Z] SKIPPED: ../../Documents/2023/2003202/VU_3429_070_2003202.xml -> 2023/2003202/VU_3429_070_2003202.xml
|
|
4
|
-
[2025-05-13T19:46:47.671Z] SKIPPED: ../../Documents/2023/2002089/044321004UKC5.pdf -> 2023/2002089/044321004UKC5.pdf
|
|
5
|
-
[2025-05-13T19:46:47.682Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-60280-191230MC0-COVE.xml -> 2023/2002089/3429-07-22002089-60280-191230MC0-COVE.xml
|
|
6
|
-
[2025-05-13T19:46:47.688Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-60280-191230MC2-COVE.xml -> 2023/2002089/3429-07-22002089-60280-191230MC2-COVE.xml
|
|
7
|
-
[2025-05-13T19:46:47.695Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-60280-191230MC5-COVE.xml -> 2023/2002089/3429-07-22002089-60280-191230MC5-COVE.xml
|
|
8
|
-
[2025-05-13T19:46:47.701Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-CoveFact.pdf -> 2023/2002089/3429-07-22002089-CoveFact.pdf
|
|
9
|
-
[2025-05-13T19:46:47.708Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-FV-m3429279.006 -> 2023/2002089/3429-07-22002089-FV-m3429279.006
|
|
10
|
-
[2025-05-13T19:46:47.714Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-FV-m3429279.err -> 2023/2002089/3429-07-22002089-FV-m3429279.err
|
|
11
|
-
[2025-05-13T19:46:47.720Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-PE-A3429811.006 -> 2023/2002089/3429-07-22002089-PE-A3429811.006
|
|
12
|
-
[2025-05-13T19:46:47.726Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-PE-E3429811.006 -> 2023/2002089/3429-07-22002089-PE-E3429811.006
|
|
13
|
-
[2025-05-13T19:46:47.731Z] SKIPPED: ../../Documents/2023/2002089/3429-07-22002089-Simplif.pdf -> 2023/2002089/3429-07-22002089-Simplif.pdf
|
|
14
|
-
[2025-05-13T19:46:47.737Z] SKIPPED: ../../Documents/2023/2002089/COVE-3429-070-2002089-COVE225IIKWC1.pdf -> 2023/2002089/COVE-3429-070-2002089-COVE225IIKWC1.pdf
|
|
15
|
-
[2025-05-13T19:46:47.743Z] SKIPPED: ../../Documents/2023/2002089/COVE-3429-070-2002089-COVE225IIKWC1.xml -> 2023/2002089/COVE-3429-070-2002089-COVE225IIKWC1.xml
|
|
16
|
-
[2025-05-13T19:46:47.749Z] SKIPPED: ../../Documents/2023/2002089/COVE-3429-070-2002089-COVE225IINHI2.pdf -> 2023/2002089/COVE-3429-070-2002089-COVE225IINHI2.pdf
|
|
17
|
-
[2025-05-13T19:46:47.756Z] SKIPPED: ../../Documents/2023/2002089/COVE-3429-070-2002089-COVE225IINHI2.xml -> 2023/2002089/COVE-3429-070-2002089-COVE225IINHI2.xml
|
|
18
|
-
[2025-05-13T19:46:47.761Z] SKIPPED: ../../Documents/2023/2002089/DETALLE_COVE225IIKWC1.pdf -> 2023/2002089/DETALLE_COVE225IIKWC1.pdf
|
|
19
|
-
[2025-05-13T19:46:47.766Z] SKIPPED: ../../Documents/2023/2002089/DETALLE_COVE225IINHI2.pdf -> 2023/2002089/DETALLE_COVE225IINHI2.pdf
|
|
20
|
-
[2025-05-13T19:46:47.773Z] SKIPPED: ../../Documents/2023/2002089/EDOC_044321004UKC5.xml -> 2023/2002089/EDOC_044321004UKC5.xml
|
|
21
|
-
[2025-05-13T19:46:47.781Z] SKIPPED: ../../Documents/2023/2002089/VU_3429_070_2002089.xml -> 2023/2002089/VU_3429_070_2002089.xml
|
|
22
|
-
[2025-05-13T19:46:47.787Z] SKIPPED: ../../Documents/2023/2002089/VU_REMESA_3429_070_2002089.xml -> 2023/2002089/VU_REMESA_3429_070_2002089.xml
|
|
23
|
-
[2025-05-13T19:46:47.792Z] SKIPPED: ../../Documents/2023/2000601/04402200X9L27.pdf -> 2023/2000601/04402200X9L27.pdf
|
|
24
|
-
[2025-05-13T19:46:47.798Z] SKIPPED: ../../Documents/2023/2000601/04402200X9L27.xml -> 2023/2000601/04402200X9L27.xml
|
|
25
|
-
[2025-05-13T19:46:47.805Z] SKIPPED: ../../Documents/2023/2000601/04412000Z75A8.pdf -> 2023/2000601/04412000Z75A8.pdf
|
|
26
|
-
[2025-05-13T19:46:47.811Z] SKIPPED: ../../Documents/2023/2000601/04432000491D6.pdf -> 2023/2000601/04432000491D6.pdf
|
|
27
|
-
[2025-05-13T19:46:47.818Z] SKIPPED: ../../Documents/2023/2000601/044320004GF86.pdf -> 2023/2000601/044320004GF86.pdf
|
|
28
|
-
[2025-05-13T19:46:47.824Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-73096-COVE.xml -> 2023/2000601/3429-07-22000601-73096-COVE.xml
|
|
29
|
-
[2025-05-13T19:46:47.830Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-90972508-0001-DODA.pdf -> 2023/2000601/3429-07-22000601-90972508-0001-DODA.pdf
|
|
30
|
-
[2025-05-13T19:46:47.837Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-CoveFact.pdf -> 2023/2000601/3429-07-22000601-CoveFact.pdf
|
|
31
|
-
[2025-05-13T19:46:47.842Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-FV-m3429536.009 -> 2023/2000601/3429-07-22000601-FV-m3429536.009
|
|
32
|
-
[2025-05-13T19:46:47.847Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-FV-m3429536.err -> 2023/2000601/3429-07-22000601-FV-m3429536.err
|
|
33
|
-
[2025-05-13T19:46:47.852Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-MX-B376W_20221212_162523-RespDgs.xml -> 2023/2000601/3429-07-22000601-MX-B376W_20221212_162523-RespDgs.xml
|
|
34
|
-
[2025-05-13T19:46:47.856Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-PE-A3429518.009 -> 2023/2000601/3429-07-22000601-PE-A3429518.009
|
|
35
|
-
[2025-05-13T19:46:47.861Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-PE-E3429518.009 -> 2023/2000601/3429-07-22000601-PE-E3429518.009
|
|
36
|
-
[2025-05-13T19:46:47.866Z] SKIPPED: ../../Documents/2023/2000601/3429-07-22000601-Simplif.pdf -> 2023/2000601/3429-07-22000601-Simplif.pdf
|
|
37
|
-
[2025-05-13T19:46:47.872Z] SKIPPED: ../../Documents/2023/2000601/COVE-3429-070-2000601-COVE225GYTBB3.pdf -> 2023/2000601/COVE-3429-070-2000601-COVE225GYTBB3.pdf
|
|
38
|
-
[2025-05-13T19:46:47.878Z] SKIPPED: ../../Documents/2023/2000601/COVE-3429-070-2000601-COVE225GYTBB3.xml -> 2023/2000601/COVE-3429-070-2000601-COVE225GYTBB3.xml
|
|
39
|
-
[2025-05-13T19:46:47.883Z] SKIPPED: ../../Documents/2023/2000601/DETALLE_COVE225GYTBB3.pdf -> 2023/2000601/DETALLE_COVE225GYTBB3.pdf
|
|
40
|
-
[2025-05-13T19:46:47.889Z] SKIPPED: ../../Documents/2023/2000601/EDOC-3429-070-2000601-04402200X9L27.pdf -> 2023/2000601/EDOC-3429-070-2000601-04402200X9L27.pdf
|
|
41
|
-
[2025-05-13T19:46:47.894Z] SKIPPED: ../../Documents/2023/2000601/EDOC-3429-070-2000601-04412000Z75A8.pdf -> 2023/2000601/EDOC-3429-070-2000601-04412000Z75A8.pdf
|
|
42
|
-
[2025-05-13T19:46:47.900Z] SKIPPED: ../../Documents/2023/2000601/EDOC-3429-070-2000601-04432000491D6.pdf -> 2023/2000601/EDOC-3429-070-2000601-04432000491D6.pdf
|
|
43
|
-
[2025-05-13T19:46:47.905Z] SKIPPED: ../../Documents/2023/2000601/EDOC-3429-070-2000601-044320004GF86.pdf -> 2023/2000601/EDOC-3429-070-2000601-044320004GF86.pdf
|
|
44
|
-
[2025-05-13T19:46:47.911Z] SKIPPED: ../../Documents/2023/2000601/EDOC_04412000Z75A8.xml -> 2023/2000601/EDOC_04412000Z75A8.xml
|
|
45
|
-
[2025-05-13T19:46:47.917Z] SKIPPED: ../../Documents/2023/2000601/EDOC_04432000491D6.xml -> 2023/2000601/EDOC_04432000491D6.xml
|
|
46
|
-
[2025-05-13T19:46:47.922Z] SKIPPED: ../../Documents/2023/2000601/EDOC_044320004GF86.xml -> 2023/2000601/EDOC_044320004GF86.xml
|
|
47
|
-
[2025-05-13T19:46:47.927Z] SKIPPED: ../../Documents/2023/2000601/VU_3429_070_2000601.xml -> 2023/2000601/VU_3429_070_2000601.xml
|
|
48
|
-
[2025-05-13T19:46:47.931Z] SKIPPED: ../../Documents/2023/2000601/VU_REMESA_3429_070_2000601.xml -> 2023/2000601/VU_REMESA_3429_070_2000601.xml
|
|
49
|
-
[2025-05-13T19:46:47.932Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
50
|
-
[2025-05-13T19:46:47.934Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
51
|
-
[2025-05-13T19:46:47.939Z] SKIPPED: ../../Documents/2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf -> 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
52
|
-
[2025-05-13T19:46:47.943Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
53
|
-
[2025-05-13T19:46:47.947Z] SKIPPED: ../../Documents/2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf -> 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
54
|
-
[2025-05-13T19:46:47.952Z] SKIPPED: ../../Documents/2024/2003207/VU_3429_070_2003207.xml -> 2024/2003207/VU_3429_070_2003207.xml
|
|
55
|
-
[2025-05-13T19:46:47.955Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
56
|
-
[2025-05-13T19:46:47.960Z] SKIPPED: ../../Documents/2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf -> 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
57
|
-
[2025-05-13T19:46:47.965Z] SKIPPED: ../../Documents/2024/2003212/VU_3429_070_2003212.xml -> 2024/2003212/VU_3429_070_2003212.xml
|
|
58
|
-
[2025-05-13T19:46:47.967Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 5
|
|
59
|
-
[2025-05-13T19:46:47.981Z] SUCCESS: ../../Documents/2025/2003180/VU_3429_070_2003180.xml -> 2025/2003180/VU_3429_070_2003180.xml
|
|
60
|
-
[2025-05-13T19:46:47.992Z] SUCCESS: ../../Documents/2025/2003189/VU_3429_070_2003189.xml -> 2025/2003189/VU_3429_070_2003189.xml
|
|
61
|
-
[2025-05-13T19:46:48.003Z] SUCCESS: ../../Documents/2025/2003202/VU_3429_070_2003202.xml -> 2025/2003202/VU_3429_070_2003202.xml
|
|
62
|
-
[2025-05-13T19:46:48.027Z] SUCCESS: ../../Documents/2025/2002089/044321004UKC5.pdf -> 2025/2002089/044321004UKC5.pdf
|
|
63
|
-
[2025-05-13T19:46:48.038Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-60280-191230MC0-COVE.xml -> 2025/2002089/3429-07-22002089-60280-191230MC0-COVE.xml
|
|
64
|
-
[2025-05-13T19:46:48.060Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-60280-191230MC2-COVE.xml -> 2025/2002089/3429-07-22002089-60280-191230MC2-COVE.xml
|
|
65
|
-
[2025-05-13T19:46:48.077Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-60280-191230MC5-COVE.xml -> 2025/2002089/3429-07-22002089-60280-191230MC5-COVE.xml
|
|
66
|
-
[2025-05-13T19:46:48.096Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-CoveFact.pdf -> 2025/2002089/3429-07-22002089-CoveFact.pdf
|
|
67
|
-
[2025-05-13T19:46:48.108Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-FV-m3429279.006 -> 2025/2002089/3429-07-22002089-FV-m3429279.006
|
|
68
|
-
[2025-05-13T19:46:48.118Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-FV-m3429279.err -> 2025/2002089/3429-07-22002089-FV-m3429279.err
|
|
69
|
-
[2025-05-13T19:46:48.128Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-PE-A3429811.006 -> 2025/2002089/3429-07-22002089-PE-A3429811.006
|
|
70
|
-
[2025-05-13T19:46:48.138Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-PE-E3429811.006 -> 2025/2002089/3429-07-22002089-PE-E3429811.006
|
|
71
|
-
[2025-05-13T19:46:48.153Z] SUCCESS: ../../Documents/2025/2002089/3429-07-22002089-Simplif.pdf -> 2025/2002089/3429-07-22002089-Simplif.pdf
|
|
72
|
-
[2025-05-13T19:46:48.164Z] SUCCESS: ../../Documents/2025/2002089/COVE-3429-070-2002089-COVE225IIKWC1.pdf -> 2025/2002089/COVE-3429-070-2002089-COVE225IIKWC1.pdf
|
|
73
|
-
[2025-05-13T19:46:48.175Z] SUCCESS: ../../Documents/2025/2002089/COVE-3429-070-2002089-COVE225IIKWC1.xml -> 2025/2002089/COVE-3429-070-2002089-COVE225IIKWC1.xml
|
|
74
|
-
[2025-05-13T19:46:48.187Z] SUCCESS: ../../Documents/2025/2002089/COVE-3429-070-2002089-COVE225IINHI2.pdf -> 2025/2002089/COVE-3429-070-2002089-COVE225IINHI2.pdf
|
|
75
|
-
[2025-05-13T19:46:48.197Z] SUCCESS: ../../Documents/2025/2002089/COVE-3429-070-2002089-COVE225IINHI2.xml -> 2025/2002089/COVE-3429-070-2002089-COVE225IINHI2.xml
|
|
76
|
-
[2025-05-13T19:46:48.212Z] SUCCESS: ../../Documents/2025/2002089/DETALLE_COVE225IIKWC1.pdf -> 2025/2002089/DETALLE_COVE225IIKWC1.pdf
|
|
77
|
-
[2025-05-13T19:46:48.225Z] SUCCESS: ../../Documents/2025/2002089/DETALLE_COVE225IINHI2.pdf -> 2025/2002089/DETALLE_COVE225IINHI2.pdf
|
|
78
|
-
[2025-05-13T19:46:48.243Z] SUCCESS: ../../Documents/2025/2002089/EDOC_044321004UKC5.xml -> 2025/2002089/EDOC_044321004UKC5.xml
|
|
79
|
-
[2025-05-13T19:46:48.253Z] SUCCESS: ../../Documents/2025/2002089/VU_3429_070_2002089.xml -> 2025/2002089/VU_3429_070_2002089.xml
|
|
80
|
-
[2025-05-13T19:46:48.265Z] SUCCESS: ../../Documents/2025/2002089/VU_REMESA_3429_070_2002089.xml -> 2025/2002089/VU_REMESA_3429_070_2002089.xml
|
|
81
|
-
[2025-05-13T19:46:48.319Z] SUCCESS: ../../Documents/2025/2000601/04402200X9L27.pdf -> 2025/2000601/04402200X9L27.pdf
|
|
82
|
-
[2025-05-13T19:46:48.401Z] SUCCESS: ../../Documents/2025/2000601/04402200X9L27.xml -> 2025/2000601/04402200X9L27.xml
|
|
83
|
-
[2025-05-13T19:46:48.512Z] SUCCESS: ../../Documents/2025/2000601/04412000Z75A8.pdf -> 2025/2000601/04412000Z75A8.pdf
|
|
84
|
-
[2025-05-13T19:46:48.650Z] SUCCESS: ../../Documents/2025/2000601/04432000491D6.pdf -> 2025/2000601/04432000491D6.pdf
|
|
85
|
-
[2025-05-13T19:46:48.714Z] SUCCESS: ../../Documents/2025/2000601/044320004GF86.pdf -> 2025/2000601/044320004GF86.pdf
|
|
86
|
-
[2025-05-13T19:46:48.725Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-73096-COVE.xml -> 2025/2000601/3429-07-22000601-73096-COVE.xml
|
|
87
|
-
[2025-05-13T19:46:48.736Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-90972508-0001-DODA.pdf -> 2025/2000601/3429-07-22000601-90972508-0001-DODA.pdf
|
|
88
|
-
[2025-05-13T19:46:48.757Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-CoveFact.pdf -> 2025/2000601/3429-07-22000601-CoveFact.pdf
|
|
89
|
-
[2025-05-13T19:46:48.767Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-FV-m3429536.009 -> 2025/2000601/3429-07-22000601-FV-m3429536.009
|
|
90
|
-
[2025-05-13T19:46:48.778Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-FV-m3429536.err -> 2025/2000601/3429-07-22000601-FV-m3429536.err
|
|
91
|
-
[2025-05-13T19:46:48.787Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-MX-B376W_20221212_162523-RespDgs.xml -> 2025/2000601/3429-07-22000601-MX-B376W_20221212_162523-RespDgs.xml
|
|
92
|
-
[2025-05-13T19:46:48.800Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-PE-A3429518.009 -> 2025/2000601/3429-07-22000601-PE-A3429518.009
|
|
93
|
-
[2025-05-13T19:46:48.810Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-PE-E3429518.009 -> 2025/2000601/3429-07-22000601-PE-E3429518.009
|
|
94
|
-
[2025-05-13T19:46:48.826Z] SUCCESS: ../../Documents/2025/2000601/3429-07-22000601-Simplif.pdf -> 2025/2000601/3429-07-22000601-Simplif.pdf
|
|
95
|
-
[2025-05-13T19:46:48.838Z] SUCCESS: ../../Documents/2025/2000601/COVE-3429-070-2000601-COVE225GYTBB3.pdf -> 2025/2000601/COVE-3429-070-2000601-COVE225GYTBB3.pdf
|
|
96
|
-
[2025-05-13T19:46:48.848Z] SUCCESS: ../../Documents/2025/2000601/COVE-3429-070-2000601-COVE225GYTBB3.xml -> 2025/2000601/COVE-3429-070-2000601-COVE225GYTBB3.xml
|
|
97
|
-
[2025-05-13T19:46:48.861Z] SUCCESS: ../../Documents/2025/2000601/DETALLE_COVE225GYTBB3.pdf -> 2025/2000601/DETALLE_COVE225GYTBB3.pdf
|
|
98
|
-
[2025-05-13T19:46:48.872Z] SUCCESS: ../../Documents/2025/2000601/EDOC-3429-070-2000601-04402200X9L27.pdf -> 2025/2000601/EDOC-3429-070-2000601-04402200X9L27.pdf
|
|
99
|
-
[2025-05-13T19:46:48.884Z] SUCCESS: ../../Documents/2025/2000601/EDOC-3429-070-2000601-04412000Z75A8.pdf -> 2025/2000601/EDOC-3429-070-2000601-04412000Z75A8.pdf
|
|
100
|
-
[2025-05-13T19:46:48.895Z] SUCCESS: ../../Documents/2025/2000601/EDOC-3429-070-2000601-04432000491D6.pdf -> 2025/2000601/EDOC-3429-070-2000601-04432000491D6.pdf
|
|
101
|
-
[2025-05-13T19:46:48.906Z] SUCCESS: ../../Documents/2025/2000601/EDOC-3429-070-2000601-044320004GF86.pdf -> 2025/2000601/EDOC-3429-070-2000601-044320004GF86.pdf
|
|
102
|
-
[2025-05-13T19:46:48.935Z] SUCCESS: ../../Documents/2025/2000601/EDOC_04412000Z75A8.xml -> 2025/2000601/EDOC_04412000Z75A8.xml
|
|
103
|
-
[2025-05-13T19:46:48.976Z] SUCCESS: ../../Documents/2025/2000601/EDOC_04432000491D6.xml -> 2025/2000601/EDOC_04432000491D6.xml
|
|
104
|
-
[2025-05-13T19:46:49.010Z] SUCCESS: ../../Documents/2025/2000601/EDOC_044320004GF86.xml -> 2025/2000601/EDOC_044320004GF86.xml
|
|
105
|
-
[2025-05-13T19:46:49.025Z] SUCCESS: ../../Documents/2025/2000601/VU_3429_070_2000601.xml -> 2025/2000601/VU_3429_070_2000601.xml
|
|
106
|
-
[2025-05-13T19:46:49.036Z] SUCCESS: ../../Documents/2025/2000601/VU_REMESA_3429_070_2000601.xml -> 2025/2000601/VU_REMESA_3429_070_2000601.xml
|
|
107
|
-
[2025-05-13T19:46:49.038Z] 📦 Upload Summary for folder 2025: Success: 48, Errors: 0, Skipped: 0
|
|
108
|
-
[2025-05-13T23:23:45.703Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
109
|
-
[2025-05-13T23:23:45.708Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
110
|
-
[2025-05-13T23:23:45.727Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
111
|
-
[2025-05-13T23:23:45.733Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
112
|
-
[2025-05-13T23:23:45.737Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 5
|
|
113
|
-
[2025-05-13T23:23:45.753Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 48
|
|
114
|
-
[2025-05-13T23:25:07.223Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
115
|
-
[2025-05-13T23:25:07.225Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
116
|
-
[2025-05-13T23:25:07.243Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
117
|
-
[2025-05-13T23:25:07.247Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
118
|
-
[2025-05-13T23:25:07.251Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 5
|
|
119
|
-
[2025-05-13T23:25:07.293Z] SUCCESS: ../../Documents/2025/2003189888/VU_3429_070_2003180.xml -> 2025/2003189888/VU_3429_070_2003180.xml
|
|
120
|
-
[2025-05-13T23:25:07.295Z] 📦 Upload Summary for folder 2025: Success: 1, Errors: 0, Skipped: 48
|
|
121
|
-
[2025-05-13T23:37:57.110Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
122
|
-
[2025-05-13T23:37:57.113Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
123
|
-
[2025-05-13T23:37:57.131Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
124
|
-
[2025-05-13T23:37:57.136Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
125
|
-
[2025-05-13T23:37:57.157Z] SUCCESS: ../../Documents/2024/2003212/VU_3429_070_2003.xml -> 2024/2003212/VU_3429_070_2003.xml
|
|
126
|
-
[2025-05-13T23:37:57.160Z] 📦 Upload Summary for folder 2024: Success: 1, Errors: 0, Skipped: 5
|
|
127
|
-
[2025-05-13T23:37:57.175Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|
|
128
|
-
[2025-05-13T23:40:13.585Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
129
|
-
[2025-05-13T23:40:13.587Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
130
|
-
[2025-05-13T23:40:13.602Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
131
|
-
[2025-05-13T23:40:13.606Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
132
|
-
[2025-05-13T23:40:13.609Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 6
|
|
133
|
-
[2025-05-13T23:40:13.629Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|
|
134
|
-
[2025-05-13T23:40:57.243Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
135
|
-
[2025-05-13T23:40:57.245Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
136
|
-
[2025-05-13T23:40:57.262Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
137
|
-
[2025-05-13T23:40:57.286Z] SUCCESS: ../../Documents/2024/2003207/VU_3429_070_2003.xml -> 2024/2003207/VU_3429_070_2003.xml
|
|
138
|
-
[2025-05-13T23:40:57.289Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
139
|
-
[2025-05-13T23:40:57.292Z] 📦 Upload Summary for folder 2024: Success: 1, Errors: 0, Skipped: 6
|
|
140
|
-
[2025-05-13T23:40:57.309Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|
|
141
|
-
[2025-05-13T23:47:19.890Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
142
|
-
[2025-05-13T23:47:19.892Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
143
|
-
[2025-05-13T23:47:19.912Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
144
|
-
[2025-05-13T23:47:19.919Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
145
|
-
[2025-05-13T23:47:19.923Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 7
|
|
146
|
-
[2025-05-13T23:47:19.939Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|
|
147
|
-
[2025-05-14T00:00:31.007Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
148
|
-
[2025-05-14T00:00:31.010Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
149
|
-
[2025-05-14T00:00:31.027Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
150
|
-
[2025-05-14T00:00:31.032Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
151
|
-
[2025-05-14T00:00:31.037Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 7
|
|
152
|
-
[2025-05-14T00:00:31.054Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|
|
153
|
-
[2025-05-14T00:02:01.388Z] 📦 Upload Summary for folder 2023: Success: 0, Errors: 0, Skipped: 48
|
|
154
|
-
[2025-05-14T00:02:02.398Z] SANITIZED: 2024/4.- 3 - Prueba ~ 3429-07-22002089-CoveFact copy.pdf → 2024/4.- 3 - Prueba - 3429-07-22002089-CoveFact copy.pdf
|
|
155
|
-
[2025-05-14T00:02:03.430Z] SANITIZED: 2024/2003207/2. 3 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003207/2. 3 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
156
|
-
[2025-05-14T00:02:06.448Z] SANITIZED: 2024/2003212/2.- 5 - Prueba ~ 3429-07-22002089-CoveFact.pdf → 2024/2003212/2.- 5 - Prueba - 3429-07-22002089-CoveFact.pdf
|
|
157
|
-
[2025-05-14T00:02:08.465Z] 📦 Upload Summary for folder 2024: Success: 0, Errors: 0, Skipped: 7
|
|
158
|
-
[2025-05-14T00:02:57.621Z] 📦 Upload Summary for folder 2025: Success: 0, Errors: 0, Skipped: 49
|