@xuda.io/drive_module 1.1.1231 → 1.1.1232
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/index.mjs +68 -70
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -8,13 +8,16 @@ import fs from 'fs';
|
|
|
8
8
|
import tesseract from 'node-tesseract-ocr';
|
|
9
9
|
import countryLanguage from 'country-language';
|
|
10
10
|
import url from 'url';
|
|
11
|
-
import AWS from 'aws-sdk';
|
|
12
11
|
import { convertPDF } from 'pdf2image';
|
|
13
12
|
import mammoth from 'mammoth';
|
|
14
13
|
import xlsx from 'node-xlsx';
|
|
15
14
|
import sizeOf from 'image-size';
|
|
16
15
|
import { getPackageManifest } from 'query-registry';
|
|
17
16
|
|
|
17
|
+
// AWS SDK v3 Imports
|
|
18
|
+
import { S3Client, GetObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
|
|
19
|
+
import { Upload } from '@aws-sdk/lib-storage';
|
|
20
|
+
|
|
18
21
|
console.log('Drive Module loaded...');
|
|
19
22
|
|
|
20
23
|
// Initialize require for dynamic paths
|
|
@@ -37,6 +40,23 @@ const get_studio_path = (raw_path, ref, file_name) => {
|
|
|
37
40
|
return raw_path.replaceAll(path.join(_conf.studio_drive_path, ref), '').replaceAll('/' + file_name, '') || '/';
|
|
38
41
|
};
|
|
39
42
|
|
|
43
|
+
// Helper to get S3 Client
|
|
44
|
+
const getS3Client = (region) => {
|
|
45
|
+
const endpoint = _conf.storage_bucket[region || process.env.XUDA_HOSTNAME].endpoint;
|
|
46
|
+
// AWS SDK v3 requires protocol in endpoint, v2 didn't always strict check
|
|
47
|
+
const formattedEndpoint = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;
|
|
48
|
+
|
|
49
|
+
return new S3Client({
|
|
50
|
+
endpoint: formattedEndpoint,
|
|
51
|
+
region: _conf.storage_bucket[region || process.env.XUDA_HOSTNAME].region,
|
|
52
|
+
credentials: {
|
|
53
|
+
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
54
|
+
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
55
|
+
},
|
|
56
|
+
forcePathStyle: false, // DigitalOcean Spaces supports virtual-hosted style
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
40
60
|
export const get_drive_files = async (req) => {
|
|
41
61
|
try {
|
|
42
62
|
const { from = 0, to = 99999, drive_type, app_id, uid, type, date, search_string, sort_by = 'name', sort_dir = 'desc' } = req;
|
|
@@ -280,7 +300,6 @@ export const get_drive_files = async (req) => {
|
|
|
280
300
|
|
|
281
301
|
const options = {
|
|
282
302
|
stat: true,
|
|
283
|
-
|
|
284
303
|
symbolicLinks: false,
|
|
285
304
|
size: true,
|
|
286
305
|
hash: false,
|
|
@@ -322,7 +341,6 @@ export const get_drive_files = async (req) => {
|
|
|
322
341
|
if (ret.code > -1) {
|
|
323
342
|
if (val.type === 'file') {
|
|
324
343
|
val.cy_data = ret.data;
|
|
325
|
-
|
|
326
344
|
val.access_link = await rep(internal_path, drive_type);
|
|
327
345
|
}
|
|
328
346
|
if (val.type === 'directory') {
|
|
@@ -332,14 +350,12 @@ export const get_drive_files = async (req) => {
|
|
|
332
350
|
|
|
333
351
|
delete ret.data._id;
|
|
334
352
|
delete ret.data._rev;
|
|
335
|
-
|
|
336
353
|
delete ret.data.docType;
|
|
337
354
|
delete ret.data.stat;
|
|
338
355
|
} else {
|
|
339
356
|
if (val.type === 'directory') {
|
|
340
357
|
val.sizeInBytes = await get_folder_size(internal_path, drive_type, app_id_master);
|
|
341
358
|
}
|
|
342
|
-
// supports file uploaded directly to the server
|
|
343
359
|
val.access_link = await rep(val.path, 'studio');
|
|
344
360
|
}
|
|
345
361
|
val.date_created = new Date(val.stat.birthtime).valueOf();
|
|
@@ -1448,17 +1464,19 @@ export const get_drive_size = async (req) => {
|
|
|
1448
1464
|
};
|
|
1449
1465
|
|
|
1450
1466
|
const upload_file_to_spaces = async (tempPath, ref, drive_type, file_name) => {
|
|
1451
|
-
const spacesEndpoint = new
|
|
1452
|
-
|
|
1453
|
-
endpoint: spacesEndpoint,
|
|
1454
|
-
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1455
|
-
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1467
|
+
const spacesEndpoint = new S3Client({
|
|
1468
|
+
endpoint: _conf.storage_bucket[process.env.XUDA_HOSTNAME].endpoint,
|
|
1456
1469
|
region: _conf.storage_bucket[process.env.XUDA_HOSTNAME].region,
|
|
1470
|
+
credentials: {
|
|
1471
|
+
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1472
|
+
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1473
|
+
},
|
|
1474
|
+
forcePathStyle: false,
|
|
1457
1475
|
});
|
|
1458
1476
|
|
|
1459
|
-
const fileContent = fs.
|
|
1477
|
+
const fileContent = fs.createReadStream(tempPath);
|
|
1460
1478
|
|
|
1461
|
-
const
|
|
1479
|
+
const uploadParams = {
|
|
1462
1480
|
Bucket: `${process.env.XUDA_HOSTNAME}/${drive_type}`,
|
|
1463
1481
|
Key: path.join(ref, _utils.UUID() + '_' + file_name),
|
|
1464
1482
|
Body: fileContent,
|
|
@@ -1466,8 +1484,12 @@ const upload_file_to_spaces = async (tempPath, ref, drive_type, file_name) => {
|
|
|
1466
1484
|
};
|
|
1467
1485
|
|
|
1468
1486
|
try {
|
|
1469
|
-
const
|
|
1487
|
+
const upload = new Upload({
|
|
1488
|
+
client: spacesEndpoint,
|
|
1489
|
+
params: uploadParams,
|
|
1490
|
+
});
|
|
1470
1491
|
|
|
1492
|
+
const data = await upload.done();
|
|
1471
1493
|
return data;
|
|
1472
1494
|
} catch (err) {
|
|
1473
1495
|
console.error('Error', err);
|
|
@@ -1475,38 +1497,45 @@ const upload_file_to_spaces = async (tempPath, ref, drive_type, file_name) => {
|
|
|
1475
1497
|
};
|
|
1476
1498
|
|
|
1477
1499
|
export const copy_file_to_another_bucket = async (source_region, target_region, file_name) => {
|
|
1478
|
-
const
|
|
1479
|
-
|
|
1480
|
-
endpoint: sourceEndpoint,
|
|
1481
|
-
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1482
|
-
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1500
|
+
const sourceS3 = new S3Client({
|
|
1501
|
+
endpoint: _conf.storage_bucket[source_region].endpoint,
|
|
1483
1502
|
region: _conf.storage_bucket[source_region].region,
|
|
1503
|
+
credentials: {
|
|
1504
|
+
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1505
|
+
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1506
|
+
},
|
|
1507
|
+
forcePathStyle: false,
|
|
1484
1508
|
});
|
|
1485
1509
|
|
|
1486
|
-
const
|
|
1487
|
-
|
|
1488
|
-
endpoint: targetEndpoint,
|
|
1489
|
-
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1490
|
-
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1510
|
+
const targetS3 = new S3Client({
|
|
1511
|
+
endpoint: _conf.storage_bucket[target_region].endpoint,
|
|
1491
1512
|
region: _conf.storage_bucket[target_region].region,
|
|
1513
|
+
credentials: {
|
|
1514
|
+
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1515
|
+
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1516
|
+
},
|
|
1517
|
+
forcePathStyle: false,
|
|
1492
1518
|
});
|
|
1493
1519
|
|
|
1494
1520
|
try {
|
|
1495
|
-
const { Body } = await sourceS3
|
|
1496
|
-
|
|
1521
|
+
const { Body } = await sourceS3.send(
|
|
1522
|
+
new GetObjectCommand({
|
|
1497
1523
|
Bucket: source_region,
|
|
1498
1524
|
Key: file_name,
|
|
1499
|
-
})
|
|
1500
|
-
|
|
1525
|
+
}),
|
|
1526
|
+
);
|
|
1501
1527
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1528
|
+
const upload = new Upload({
|
|
1529
|
+
client: targetS3,
|
|
1530
|
+
params: {
|
|
1504
1531
|
Bucket: target_region,
|
|
1505
1532
|
Key: file_name,
|
|
1506
1533
|
Body,
|
|
1507
1534
|
ACL: 'public-read',
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1535
|
+
},
|
|
1536
|
+
});
|
|
1537
|
+
|
|
1538
|
+
const ret = await upload.done();
|
|
1510
1539
|
|
|
1511
1540
|
ret.Location = `${_conf.storage_bucket[target_region].endpoint}/${target_region}/${file_name}`;
|
|
1512
1541
|
ret.key = file_name;
|
|
@@ -1582,17 +1611,19 @@ const get_file_info = async (file_path) => {
|
|
|
1582
1611
|
};
|
|
1583
1612
|
|
|
1584
1613
|
export const delete_file_from_bucket = async (bucket) => {
|
|
1585
|
-
const
|
|
1586
|
-
|
|
1587
|
-
endpoint: spacesEndpoint,
|
|
1588
|
-
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1589
|
-
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1614
|
+
const s3 = new S3Client({
|
|
1615
|
+
endpoint: _conf.storage_bucket[process.env.XUDA_HOSTNAME].endpoint,
|
|
1590
1616
|
region: _conf.storage_bucket[process.env.XUDA_HOSTNAME].region,
|
|
1617
|
+
credentials: {
|
|
1618
|
+
accessKeyId: _conf.digitalocean.spaces_access_key,
|
|
1619
|
+
secretAccessKey: _conf.digitalocean.spaces_secret_key,
|
|
1620
|
+
},
|
|
1621
|
+
forcePathStyle: false,
|
|
1591
1622
|
});
|
|
1592
1623
|
|
|
1593
1624
|
try {
|
|
1594
1625
|
for await (let [key, val] of Object.entries(bucket)) {
|
|
1595
|
-
|
|
1626
|
+
await s3.send(new DeleteObjectCommand({ Bucket: key, Key: val.key }));
|
|
1596
1627
|
}
|
|
1597
1628
|
} catch (err) {
|
|
1598
1629
|
console.error('Error', err);
|
|
@@ -1959,39 +1990,6 @@ export const update_drive_addons = async (req, job_id) => {
|
|
|
1959
1990
|
return save_ret;
|
|
1960
1991
|
};
|
|
1961
1992
|
|
|
1962
|
-
// Meta-programming to export functions dynamically
|
|
1963
|
-
const methods = [
|
|
1964
|
-
'get_drive_files',
|
|
1965
|
-
'get_drive_file_info',
|
|
1966
|
-
'delete_drive_files',
|
|
1967
|
-
'extract_drive_file',
|
|
1968
|
-
'upload_drive_file',
|
|
1969
|
-
'update_drive_file',
|
|
1970
|
-
'create_drive_folder',
|
|
1971
|
-
'rename_drive_file',
|
|
1972
|
-
'rename_drive_folder',
|
|
1973
|
-
'update_drive_file_sharing_mode',
|
|
1974
|
-
'delete_file_bulk',
|
|
1975
|
-
'check_drive_file',
|
|
1976
|
-
'update_drive_file_tags',
|
|
1977
|
-
'update_drive_addons',
|
|
1978
|
-
];
|
|
1979
|
-
|
|
1980
|
-
const exportedFunctions = {};
|
|
1981
|
-
|
|
1982
|
-
methods.forEach((method) => {
|
|
1983
|
-
['workspace', 'studio', 'user'].forEach((type) => {
|
|
1984
|
-
const funcName = method + '_' + type;
|
|
1985
|
-
// Dynamically creating named exports isn't straightforward in ESM like CJS.
|
|
1986
|
-
// We attach them to an object and export them individually if needed or export the object.
|
|
1987
|
-
// For true ESM named exports, we must declare them statically.
|
|
1988
|
-
// Since the dynamic generation is a pattern here, we'll export them explicitly if known,
|
|
1989
|
-
// or export an object containing them.
|
|
1990
|
-
// However, the request implies converting the file content.
|
|
1991
|
-
// I will map the dynamic exports to explicit named exports below for clarity and ESM compliance.
|
|
1992
|
-
});
|
|
1993
|
-
});
|
|
1994
|
-
|
|
1995
1993
|
// Explicitly exporting dynamic functions for ESM compatibility
|
|
1996
1994
|
export const get_drive_files_workspace = async (req, job_id, headers, file_obj) => {
|
|
1997
1995
|
req.drive_type = 'workspace';
|