@xuda.io/drive_module 1.1.1497 → 1.1.1499

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 CHANGED
@@ -4,6 +4,7 @@ import { rimraf } from 'rimraf';
4
4
  import fse from 'fs-extra';
5
5
  import unzipper from 'unzipper';
6
6
  import fs from 'fs';
7
+ import os from 'os';
7
8
  import tesseract from 'node-tesseract-ocr';
8
9
  import countryLanguage from 'country-language';
9
10
  import url from 'url';
@@ -219,7 +220,6 @@ export const get_drive_files = async (req) => {
219
220
  } else if (app_obj?.app_build_id) {
220
221
  ts = '?ts=' + app_obj?.app_build_id;
221
222
  }
222
- debugger;
223
223
  try {
224
224
  files.sizeInBytes += doc.size;
225
225
  files.children.push({
@@ -900,7 +900,6 @@ export const rename_drive_file = async (req, job_id, headers) => {
900
900
 
901
901
  export const rename_drive_folder = async (req) => {
902
902
  try {
903
- debugger;
904
903
  const { drive_type, app_id, curr_path, new_path, uid } = req;
905
904
  validate_drive_type(drive_type);
906
905
 
@@ -3765,6 +3764,106 @@ export const read_user_drive_folder = async (req) => {
3765
3764
  }
3766
3765
  };
3767
3766
 
3767
+ // fetch_drive_file_to_tmp: copy ONE drive file's bytes onto this box as a temp
3768
+ // file so a server-side document generator can open it, edit it and save the
3769
+ // result back as a new drive file. This is what lets the office plugins (pptx,
3770
+ // docx, xlsx) modify a deck/document the user already has instead of only
3771
+ // creating new ones: user + workspace files live in object storage, so there is
3772
+ // otherwise no path on disk to hand to a parser.
3773
+ //
3774
+ // The file is resolved by drive doc id (drv_...) or by its drive path
3775
+ // (/Folder/name.ext). The caller owns the temp file and must unlink it.
3776
+ //
3777
+ // req: { uid, app_id?, drive_type: 'user'|'workspace'|'studio', file }
3778
+ // -> { tmp_path, originalname, file_path, doc_id, size, mime, drive_type }
3779
+ export const fetch_drive_file_to_tmp = async (req) => {
3780
+ try {
3781
+ const { uid, app_id, drive_type = 'user' } = req || {};
3782
+ const file_ref = String(req?.file || req?.file_id || req?.file_path || '').trim();
3783
+
3784
+ if (!uid) return { code: -1, data: 'uid required' };
3785
+ if (!file_ref) return { code: -1, data: 'file required' };
3786
+ validate_drive_type(drive_type);
3787
+
3788
+ const write_tmp = async (buffer, name) => {
3789
+ const tmp_path = path.join(os.tmpdir(), `xuda_drive_${await _common.xuda_get_uuid('tmp')}${path.extname(name) || ''}`);
3790
+ await fs.promises.writeFile(tmp_path, buffer);
3791
+ return tmp_path;
3792
+ };
3793
+
3794
+ // studio drive is plain files on this box, addressed by their relative path.
3795
+ if (drive_type === 'studio') {
3796
+ const ref = await _common.get_project_app_id(app_id, true);
3797
+ const rel = file_ref.replace(/^\/+/, '');
3798
+ const full = path.join(_conf.studio_drive_path, ref, rel);
3799
+ // Contain the read inside the app's own studio folder.
3800
+ const root = path.join(_conf.studio_drive_path, ref);
3801
+ if (!path.resolve(full).startsWith(path.resolve(root) + path.sep)) {
3802
+ return { code: -1, data: 'file_path unauthorized' };
3803
+ }
3804
+ if (!(await fs_module.file_exists(full))) return { code: -1, data: `file not found: ${file_ref}` };
3805
+ const buffer = await fs.promises.readFile(full);
3806
+ const originalname = path.basename(full);
3807
+ return {
3808
+ code: 1,
3809
+ data: {
3810
+ tmp_path: await write_tmp(buffer, originalname),
3811
+ originalname,
3812
+ file_path: path.posix.join('/', path.dirname(rel) === '.' ? '' : path.dirname(rel)),
3813
+ doc_id: rel,
3814
+ size: buffer.length,
3815
+ mime: _drive_content_type_for(originalname),
3816
+ drive_type,
3817
+ },
3818
+ };
3819
+ }
3820
+
3821
+ const project_id = drive_type === 'user' ? await get_account_default_project_id(uid) : await _common.get_project_app_id(app_id);
3822
+
3823
+ // Either the doc id itself, or a /folder/name.ext path within the drive.
3824
+ const by_id = /^drv_/.test(file_ref);
3825
+ const selector = { docType: `${drive_type}_drive`, type: 'file', stat: 3 };
3826
+ if (by_id) {
3827
+ selector._id = file_ref;
3828
+ } else {
3829
+ const with_slash = file_ref.startsWith('/') ? file_ref : `/${file_ref}`;
3830
+ const dir = path.posix.dirname(with_slash);
3831
+ selector.file_path = dir === '.' ? '/' : dir;
3832
+ selector.originalname = path.posix.basename(with_slash);
3833
+ }
3834
+
3835
+ const find_ret = await db_module.find_app_couch_query(project_id, { selector, limit: 1 });
3836
+ const doc = find_ret?.docs?.[0];
3837
+ if (!doc) return { code: -1, data: `file not found: ${file_ref}` };
3838
+
3839
+ const region = _pick_file_region(doc);
3840
+ const b = (region && doc.bucket?.[region]) || {};
3841
+ const Bucket = b.Bucket || b.bucket || (region && _conf.storage_bucket?.[region]?.name);
3842
+ const Key = b.Key || b.key;
3843
+ const s3 = region ? _drive_s3_for(region) : null;
3844
+ if (!s3 || !Bucket || !Key) return { code: -1, data: 'file bytes unavailable' };
3845
+
3846
+ const obj = await s3.send(new GetObjectCommand({ Bucket, Key }));
3847
+ const buffer = await _stream_to_buffer(obj.Body);
3848
+ const originalname = doc.originalname || path.basename(Key);
3849
+
3850
+ return {
3851
+ code: 1,
3852
+ data: {
3853
+ tmp_path: await write_tmp(buffer, originalname),
3854
+ originalname,
3855
+ file_path: doc.file_path || '/',
3856
+ doc_id: doc._id,
3857
+ size: buffer.length,
3858
+ mime: doc.mime || _drive_content_type_for(originalname),
3859
+ drive_type,
3860
+ },
3861
+ };
3862
+ } catch (err) {
3863
+ return { code: -400, data: err.message };
3864
+ }
3865
+ };
3866
+
3768
3867
  // put_site_files — snapshot a set of static-site files into ONE region's
3769
3868
  // Spaces bucket under sites/{site_id}/{version}/{path}, public-read. Each
3770
3869
  // deploy writes a fresh immutable version directory, so older versions stay
package/index_ms.mjs CHANGED
@@ -197,6 +197,10 @@ export const read_user_drive_folder = async function (...args) {
197
197
  return await broker.send_to_queue("read_user_drive_folder", ...args);
198
198
  };
199
199
 
200
+ export const fetch_drive_file_to_tmp = async function (...args) {
201
+ return await broker.send_to_queue("fetch_drive_file_to_tmp", ...args);
202
+ };
203
+
200
204
  export const put_site_files = async function (...args) {
201
205
  return await broker.send_to_queue("put_site_files", ...args);
202
206
  };
package/index_msa.mjs CHANGED
@@ -197,6 +197,10 @@ export const read_user_drive_folder = function (...args) {
197
197
  broker.send_to_queue_async("read_user_drive_folder", ...args);
198
198
  };
199
199
 
200
+ export const fetch_drive_file_to_tmp = function (...args) {
201
+ broker.send_to_queue_async("fetch_drive_file_to_tmp", ...args);
202
+ };
203
+
200
204
  export const put_site_files = function (...args) {
201
205
  broker.send_to_queue_async("put_site_files", ...args);
202
206
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/drive_module",
3
- "version": "1.1.1497",
3
+ "version": "1.1.1499",
4
4
  "description": "Xuda Drive Server Module",
5
5
  "main": "index.mjs",
6
6
  "dependencies": {