@hasna/files 0.2.18 → 0.2.20

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 CHANGED
@@ -35,10 +35,13 @@ files sources sync-google-drive --dry-run
35
35
  files sources sync-google-drive
36
36
  ```
37
37
 
38
+ The production default is `s3://hasna-xyz-prod-emails/drive/<profile>/...`
39
+ using the `hasna-xyz-infra` AWS profile.
40
+
38
41
  For a custom S3 destination, pass the shared AWS profile explicitly:
39
42
 
40
43
  ```bash
41
- files sources add s3://my-files-bucket/google-drive --region us-east-1 --aws-profile hasna-xyz-infra
44
+ files sources add s3://my-files-bucket/drive --region us-west-2 --aws-profile hasna-xyz-infra
42
45
  ```
43
46
 
44
47
  To sync into local storage instead, add a local source and pass it as the
package/dist/cli/index.js CHANGED
@@ -167389,6 +167389,7 @@ var GOOGLE_FOLDER_MIME = "application/vnd.google-apps.folder";
167389
167389
  var DRIVE_API_BASE2 = "https://www.googleapis.com/drive/v3";
167390
167390
  var TOKEN_URL3 = "https://oauth2.googleapis.com/token";
167391
167391
  var REFRESH_BUFFER_MS3 = 5 * 60 * 1000;
167392
+ var RANGE_DOWNLOAD_CHUNK_BYTES = 64 * 1024 * 1024;
167392
167393
  var DEFAULT_EXPORT_FORMATS2 = {
167393
167394
  document: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
167394
167395
  spreadsheet: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -167470,6 +167471,15 @@ class ConnectorSdkGoogleDriveClient {
167470
167471
  size: downloaded.data.byteLength
167471
167472
  };
167472
167473
  }
167474
+ const size = file.size ? Number(file.size) : undefined;
167475
+ if (size && size > RANGE_DOWNLOAD_CHUNK_BYTES) {
167476
+ return {
167477
+ body: Readable4.from(downloadGoogleDriveRangeChunks(this.profile, file.id, size)),
167478
+ filename: file.name,
167479
+ mimeType: file.mimeType || "application/octet-stream",
167480
+ size
167481
+ };
167482
+ }
167473
167483
  const response = await requestGoogleDrive(this.profile, `/files/${encodeURIComponent(file.id)}`, {
167474
167484
  alt: "media",
167475
167485
  supportsAllDrives: true
@@ -167480,7 +167490,7 @@ class ConnectorSdkGoogleDriveClient {
167480
167490
  body: Readable4.fromWeb(response.body),
167481
167491
  filename: file.name,
167482
167492
  mimeType: response.headers.get("content-type")?.split(";")[0] || file.mimeType || "application/octet-stream",
167483
- size: file.size ? Number(file.size) : Number(response.headers.get("content-length") ?? 0) || undefined
167493
+ size: size ?? (Number(response.headers.get("content-length") ?? 0) || undefined)
167484
167494
  };
167485
167495
  }
167486
167496
  }
@@ -167510,7 +167520,7 @@ function getExportMimeType(googleMimeType, exportFormats) {
167510
167520
  return exportFormats.drawing ?? DEFAULT_EXPORT_FORMATS2.drawing;
167511
167521
  throw new Error(`Cannot export Google Workspace file type: ${googleMimeType}`);
167512
167522
  }
167513
- async function requestGoogleDrive(profile, path, params) {
167523
+ async function requestGoogleDrive(profile, path, params, headers = {}) {
167514
167524
  const token = await getValidAccessToken3(profile);
167515
167525
  const url = new URL(`${DRIVE_API_BASE2}${path}`);
167516
167526
  for (const [key, value] of Object.entries(params)) {
@@ -167520,7 +167530,8 @@ async function requestGoogleDrive(profile, path, params) {
167520
167530
  const response = await fetch(url, {
167521
167531
  headers: {
167522
167532
  Authorization: `Bearer ${token}`,
167523
- Accept: "application/octet-stream"
167533
+ Accept: "application/octet-stream",
167534
+ ...headers
167524
167535
  }
167525
167536
  });
167526
167537
  if (!response.ok) {
@@ -167529,6 +167540,14 @@ async function requestGoogleDrive(profile, path, params) {
167529
167540
  }
167530
167541
  return response;
167531
167542
  }
167543
+ async function* downloadGoogleDriveRangeChunks(profile, fileId, size) {
167544
+ for (let start = 0;start < size; start += RANGE_DOWNLOAD_CHUNK_BYTES) {
167545
+ const end = Math.min(start + RANGE_DOWNLOAD_CHUNK_BYTES - 1, size - 1);
167546
+ const response = await requestGoogleDrive(profile, `/files/${encodeURIComponent(fileId)}`, { alt: "media", supportsAllDrives: true }, { Range: `bytes=${start}-${end}` });
167547
+ const data = Buffer.from(await response.arrayBuffer());
167548
+ yield data;
167549
+ }
167550
+ }
167532
167551
  async function getValidAccessToken3(profile) {
167533
167552
  if (process.env.GOOGLE_ACCESS_TOKEN)
167534
167553
  return process.env.GOOGLE_ACCESS_TOKEN;
@@ -168081,12 +168100,12 @@ function shouldImport(config9, item, existing, destinationSourceId, storageType)
168081
168100
  }
168082
168101
  function buildImportedPath(config9, item, importedName) {
168083
168102
  if (config9.path_mode === "id_based") {
168084
- return posix.join("google-drive", safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
168103
+ return posix.join(safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
168085
168104
  }
168086
168105
  const storageName = appendDriveFileId(importedName, item.id);
168087
168106
  const itemPath = item.path === item.name ? storageName : posix.join(dirname5(item.path), storageName);
168088
168107
  const driveSegment = item.drive_id === "my-drive" ? "my-drive" : safePathSegment(item.drive_name || item.drive_id);
168089
- return posix.join("google-drive", safePathSegment(config9.profile), driveSegment, itemPath);
168108
+ return posix.join(safePathSegment(config9.profile), driveSegment, itemPath);
168090
168109
  }
168091
168110
  function safePathSegment(value) {
168092
168111
  return value.replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").replace(/\s+/g, " ").trim() || "unnamed";
@@ -168316,10 +168335,12 @@ sources.command("add-google-drive").description("Add a Google Drive source that
168316
168335
  process.exit(1);
168317
168336
  });
168318
168337
  });
168319
- sources.command("bootstrap-prod-files").description("Create or update the production S3 source for Google Drive/Gmail sync").option("--bucket <bucket>", "Production files bucket", "hasna-xyz-prod-files").option("--region <region>", "AWS region", "us-east-1").option("--aws-profile <profile>", "AWS shared config profile", "hasna-xyz-infra").option("--prefix <prefix>", "Optional S3 key prefix").option("-n, --name <name>", "Source name", "prod-files").option("--no-google-drive-default", "Do not set this source as the default Google Drive destination").option("--json", "Output as JSON").action((opts) => {
168338
+ sources.command("bootstrap-prod-files").description("Create or update the production S3 source for Google Drive archive sync").option("--bucket <bucket>", "Production archive bucket", "hasna-xyz-prod-emails").option("--region <region>", "AWS region", "us-west-2").option("--aws-profile <profile>", "AWS shared config profile", "hasna-xyz-infra").option("--prefix <prefix>", "S3 key prefix for Drive objects", "drive").option("-n, --name <name>", "Source name", "prod-emails-drive").option("--no-google-drive-default", "Do not set this source as the default Google Drive destination").option("--json", "Output as JSON").action((opts) => {
168320
168339
  const machine = getCurrentMachine();
168321
168340
  const config9 = { profile: opts.awsProfile };
168322
- const existing = listSources().find((source2) => source2.type === "s3" && (source2.name === opts.name || source2.bucket === opts.bucket));
168341
+ const legacyProductionNames = new Set([opts.name, "prod-files"]);
168342
+ const legacyProductionBuckets = new Set([opts.bucket, "hasna-xyz-prod-files", "hasna-prod-files"]);
168343
+ const existing = listSources().find((source2) => source2.type === "s3" && (legacyProductionNames.has(source2.name) || legacyProductionBuckets.has(source2.bucket ?? "")));
168323
168344
  const source = existing ? updateSource(existing.id, {
168324
168345
  name: opts.name,
168325
168346
  bucket: opts.bucket,
package/dist/index.js CHANGED
@@ -163979,6 +163979,7 @@ var GOOGLE_FOLDER_MIME = "application/vnd.google-apps.folder";
163979
163979
  var DRIVE_API_BASE2 = "https://www.googleapis.com/drive/v3";
163980
163980
  var TOKEN_URL3 = "https://oauth2.googleapis.com/token";
163981
163981
  var REFRESH_BUFFER_MS3 = 5 * 60 * 1000;
163982
+ var RANGE_DOWNLOAD_CHUNK_BYTES = 64 * 1024 * 1024;
163982
163983
  var DEFAULT_EXPORT_FORMATS2 = {
163983
163984
  document: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
163984
163985
  spreadsheet: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -164060,6 +164061,15 @@ class ConnectorSdkGoogleDriveClient {
164060
164061
  size: downloaded.data.byteLength
164061
164062
  };
164062
164063
  }
164064
+ const size = file.size ? Number(file.size) : undefined;
164065
+ if (size && size > RANGE_DOWNLOAD_CHUNK_BYTES) {
164066
+ return {
164067
+ body: Readable4.from(downloadGoogleDriveRangeChunks(this.profile, file.id, size)),
164068
+ filename: file.name,
164069
+ mimeType: file.mimeType || "application/octet-stream",
164070
+ size
164071
+ };
164072
+ }
164063
164073
  const response = await requestGoogleDrive(this.profile, `/files/${encodeURIComponent(file.id)}`, {
164064
164074
  alt: "media",
164065
164075
  supportsAllDrives: true
@@ -164070,7 +164080,7 @@ class ConnectorSdkGoogleDriveClient {
164070
164080
  body: Readable4.fromWeb(response.body),
164071
164081
  filename: file.name,
164072
164082
  mimeType: response.headers.get("content-type")?.split(";")[0] || file.mimeType || "application/octet-stream",
164073
- size: file.size ? Number(file.size) : Number(response.headers.get("content-length") ?? 0) || undefined
164083
+ size: size ?? (Number(response.headers.get("content-length") ?? 0) || undefined)
164074
164084
  };
164075
164085
  }
164076
164086
  }
@@ -164100,7 +164110,7 @@ function getExportMimeType(googleMimeType, exportFormats) {
164100
164110
  return exportFormats.drawing ?? DEFAULT_EXPORT_FORMATS2.drawing;
164101
164111
  throw new Error(`Cannot export Google Workspace file type: ${googleMimeType}`);
164102
164112
  }
164103
- async function requestGoogleDrive(profile, path, params) {
164113
+ async function requestGoogleDrive(profile, path, params, headers = {}) {
164104
164114
  const token = await getValidAccessToken3(profile);
164105
164115
  const url = new URL(`${DRIVE_API_BASE2}${path}`);
164106
164116
  for (const [key, value] of Object.entries(params)) {
@@ -164110,7 +164120,8 @@ async function requestGoogleDrive(profile, path, params) {
164110
164120
  const response = await fetch(url, {
164111
164121
  headers: {
164112
164122
  Authorization: `Bearer ${token}`,
164113
- Accept: "application/octet-stream"
164123
+ Accept: "application/octet-stream",
164124
+ ...headers
164114
164125
  }
164115
164126
  });
164116
164127
  if (!response.ok) {
@@ -164119,6 +164130,14 @@ async function requestGoogleDrive(profile, path, params) {
164119
164130
  }
164120
164131
  return response;
164121
164132
  }
164133
+ async function* downloadGoogleDriveRangeChunks(profile, fileId, size) {
164134
+ for (let start = 0;start < size; start += RANGE_DOWNLOAD_CHUNK_BYTES) {
164135
+ const end = Math.min(start + RANGE_DOWNLOAD_CHUNK_BYTES - 1, size - 1);
164136
+ const response = await requestGoogleDrive(profile, `/files/${encodeURIComponent(fileId)}`, { alt: "media", supportsAllDrives: true }, { Range: `bytes=${start}-${end}` });
164137
+ const data = Buffer.from(await response.arrayBuffer());
164138
+ yield data;
164139
+ }
164140
+ }
164122
164141
  async function getValidAccessToken3(profile) {
164123
164142
  if (process.env.GOOGLE_ACCESS_TOKEN)
164124
164143
  return process.env.GOOGLE_ACCESS_TOKEN;
@@ -164674,12 +164693,12 @@ function shouldImport(config9, item, existing, destinationSourceId, storageType)
164674
164693
  }
164675
164694
  function buildImportedPath(config9, item, importedName) {
164676
164695
  if (config9.path_mode === "id_based") {
164677
- return posix.join("google-drive", safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
164696
+ return posix.join(safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
164678
164697
  }
164679
164698
  const storageName = appendDriveFileId(importedName, item.id);
164680
164699
  const itemPath = item.path === item.name ? storageName : posix.join(dirname5(item.path), storageName);
164681
164700
  const driveSegment = item.drive_id === "my-drive" ? "my-drive" : safePathSegment(item.drive_name || item.drive_id);
164682
- return posix.join("google-drive", safePathSegment(config9.profile), driveSegment, itemPath);
164701
+ return posix.join(safePathSegment(config9.profile), driveSegment, itemPath);
164683
164702
  }
164684
164703
  function safePathSegment(value) {
164685
164704
  return value.replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").replace(/\s+/g, " ").trim() || "unnamed";
package/dist/mcp/index.js CHANGED
@@ -182918,6 +182918,7 @@ var GOOGLE_FOLDER_MIME = "application/vnd.google-apps.folder";
182918
182918
  var DRIVE_API_BASE2 = "https://www.googleapis.com/drive/v3";
182919
182919
  var TOKEN_URL3 = "https://oauth2.googleapis.com/token";
182920
182920
  var REFRESH_BUFFER_MS3 = 5 * 60 * 1000;
182921
+ var RANGE_DOWNLOAD_CHUNK_BYTES = 64 * 1024 * 1024;
182921
182922
  var DEFAULT_EXPORT_FORMATS2 = {
182922
182923
  document: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
182923
182924
  spreadsheet: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -182999,6 +183000,15 @@ class ConnectorSdkGoogleDriveClient {
182999
183000
  size: downloaded.data.byteLength
183000
183001
  };
183001
183002
  }
183003
+ const size = file.size ? Number(file.size) : undefined;
183004
+ if (size && size > RANGE_DOWNLOAD_CHUNK_BYTES) {
183005
+ return {
183006
+ body: Readable4.from(downloadGoogleDriveRangeChunks(this.profile, file.id, size)),
183007
+ filename: file.name,
183008
+ mimeType: file.mimeType || "application/octet-stream",
183009
+ size
183010
+ };
183011
+ }
183002
183012
  const response = await requestGoogleDrive(this.profile, `/files/${encodeURIComponent(file.id)}`, {
183003
183013
  alt: "media",
183004
183014
  supportsAllDrives: true
@@ -183009,7 +183019,7 @@ class ConnectorSdkGoogleDriveClient {
183009
183019
  body: Readable4.fromWeb(response.body),
183010
183020
  filename: file.name,
183011
183021
  mimeType: response.headers.get("content-type")?.split(";")[0] || file.mimeType || "application/octet-stream",
183012
- size: file.size ? Number(file.size) : Number(response.headers.get("content-length") ?? 0) || undefined
183022
+ size: size ?? (Number(response.headers.get("content-length") ?? 0) || undefined)
183013
183023
  };
183014
183024
  }
183015
183025
  }
@@ -183039,7 +183049,7 @@ function getExportMimeType(googleMimeType, exportFormats) {
183039
183049
  return exportFormats.drawing ?? DEFAULT_EXPORT_FORMATS2.drawing;
183040
183050
  throw new Error(`Cannot export Google Workspace file type: ${googleMimeType}`);
183041
183051
  }
183042
- async function requestGoogleDrive(profile, path, params) {
183052
+ async function requestGoogleDrive(profile, path, params, headers = {}) {
183043
183053
  const token = await getValidAccessToken3(profile);
183044
183054
  const url = new URL(`${DRIVE_API_BASE2}${path}`);
183045
183055
  for (const [key, value] of Object.entries(params)) {
@@ -183049,7 +183059,8 @@ async function requestGoogleDrive(profile, path, params) {
183049
183059
  const response = await fetch(url, {
183050
183060
  headers: {
183051
183061
  Authorization: `Bearer ${token}`,
183052
- Accept: "application/octet-stream"
183062
+ Accept: "application/octet-stream",
183063
+ ...headers
183053
183064
  }
183054
183065
  });
183055
183066
  if (!response.ok) {
@@ -183058,6 +183069,14 @@ async function requestGoogleDrive(profile, path, params) {
183058
183069
  }
183059
183070
  return response;
183060
183071
  }
183072
+ async function* downloadGoogleDriveRangeChunks(profile, fileId, size) {
183073
+ for (let start = 0;start < size; start += RANGE_DOWNLOAD_CHUNK_BYTES) {
183074
+ const end = Math.min(start + RANGE_DOWNLOAD_CHUNK_BYTES - 1, size - 1);
183075
+ const response = await requestGoogleDrive(profile, `/files/${encodeURIComponent(fileId)}`, { alt: "media", supportsAllDrives: true }, { Range: `bytes=${start}-${end}` });
183076
+ const data = Buffer.from(await response.arrayBuffer());
183077
+ yield data;
183078
+ }
183079
+ }
183061
183080
  async function getValidAccessToken3(profile) {
183062
183081
  if (process.env.GOOGLE_ACCESS_TOKEN)
183063
183082
  return process.env.GOOGLE_ACCESS_TOKEN;
@@ -183605,12 +183624,12 @@ function shouldImport(config9, item, existing, destinationSourceId, storageType)
183605
183624
  }
183606
183625
  function buildImportedPath(config9, item, importedName) {
183607
183626
  if (config9.path_mode === "id_based") {
183608
- return posix.join("google-drive", safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
183627
+ return posix.join(safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
183609
183628
  }
183610
183629
  const storageName = appendDriveFileId(importedName, item.id);
183611
183630
  const itemPath = item.path === item.name ? storageName : posix.join(dirname5(item.path), storageName);
183612
183631
  const driveSegment = item.drive_id === "my-drive" ? "my-drive" : safePathSegment(item.drive_name || item.drive_id);
183613
- return posix.join("google-drive", safePathSegment(config9.profile), driveSegment, itemPath);
183632
+ return posix.join(safePathSegment(config9.profile), driveSegment, itemPath);
183614
183633
  }
183615
183634
  function safePathSegment(value) {
183616
183635
  return value.replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").replace(/\s+/g, " ").trim() || "unnamed";
@@ -163738,6 +163738,7 @@ var GOOGLE_FOLDER_MIME = "application/vnd.google-apps.folder";
163738
163738
  var DRIVE_API_BASE2 = "https://www.googleapis.com/drive/v3";
163739
163739
  var TOKEN_URL3 = "https://oauth2.googleapis.com/token";
163740
163740
  var REFRESH_BUFFER_MS3 = 5 * 60 * 1000;
163741
+ var RANGE_DOWNLOAD_CHUNK_BYTES = 64 * 1024 * 1024;
163741
163742
  var DEFAULT_EXPORT_FORMATS2 = {
163742
163743
  document: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
163743
163744
  spreadsheet: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -163811,6 +163812,15 @@ class ConnectorSdkGoogleDriveClient {
163811
163812
  size: downloaded.data.byteLength
163812
163813
  };
163813
163814
  }
163815
+ const size = file.size ? Number(file.size) : undefined;
163816
+ if (size && size > RANGE_DOWNLOAD_CHUNK_BYTES) {
163817
+ return {
163818
+ body: Readable4.from(downloadGoogleDriveRangeChunks(this.profile, file.id, size)),
163819
+ filename: file.name,
163820
+ mimeType: file.mimeType || "application/octet-stream",
163821
+ size
163822
+ };
163823
+ }
163814
163824
  const response = await requestGoogleDrive(this.profile, `/files/${encodeURIComponent(file.id)}`, {
163815
163825
  alt: "media",
163816
163826
  supportsAllDrives: true
@@ -163821,7 +163831,7 @@ class ConnectorSdkGoogleDriveClient {
163821
163831
  body: Readable4.fromWeb(response.body),
163822
163832
  filename: file.name,
163823
163833
  mimeType: response.headers.get("content-type")?.split(";")[0] || file.mimeType || "application/octet-stream",
163824
- size: file.size ? Number(file.size) : Number(response.headers.get("content-length") ?? 0) || undefined
163834
+ size: size ?? (Number(response.headers.get("content-length") ?? 0) || undefined)
163825
163835
  };
163826
163836
  }
163827
163837
  }
@@ -163851,7 +163861,7 @@ function getExportMimeType(googleMimeType, exportFormats) {
163851
163861
  return exportFormats.drawing ?? DEFAULT_EXPORT_FORMATS2.drawing;
163852
163862
  throw new Error(`Cannot export Google Workspace file type: ${googleMimeType}`);
163853
163863
  }
163854
- async function requestGoogleDrive(profile, path, params) {
163864
+ async function requestGoogleDrive(profile, path, params, headers = {}) {
163855
163865
  const token = await getValidAccessToken3(profile);
163856
163866
  const url = new URL(`${DRIVE_API_BASE2}${path}`);
163857
163867
  for (const [key, value] of Object.entries(params)) {
@@ -163861,7 +163871,8 @@ async function requestGoogleDrive(profile, path, params) {
163861
163871
  const response = await fetch(url, {
163862
163872
  headers: {
163863
163873
  Authorization: `Bearer ${token}`,
163864
- Accept: "application/octet-stream"
163874
+ Accept: "application/octet-stream",
163875
+ ...headers
163865
163876
  }
163866
163877
  });
163867
163878
  if (!response.ok) {
@@ -163870,6 +163881,14 @@ async function requestGoogleDrive(profile, path, params) {
163870
163881
  }
163871
163882
  return response;
163872
163883
  }
163884
+ async function* downloadGoogleDriveRangeChunks(profile, fileId, size) {
163885
+ for (let start = 0;start < size; start += RANGE_DOWNLOAD_CHUNK_BYTES) {
163886
+ const end = Math.min(start + RANGE_DOWNLOAD_CHUNK_BYTES - 1, size - 1);
163887
+ const response = await requestGoogleDrive(profile, `/files/${encodeURIComponent(fileId)}`, { alt: "media", supportsAllDrives: true }, { Range: `bytes=${start}-${end}` });
163888
+ const data = Buffer.from(await response.arrayBuffer());
163889
+ yield data;
163890
+ }
163891
+ }
163873
163892
  async function getValidAccessToken3(profile) {
163874
163893
  if (process.env.GOOGLE_ACCESS_TOKEN)
163875
163894
  return process.env.GOOGLE_ACCESS_TOKEN;
@@ -164344,12 +164363,12 @@ function shouldImport(config9, item, existing, destinationSourceId, storageType)
164344
164363
  }
164345
164364
  function buildImportedPath(config9, item, importedName) {
164346
164365
  if (config9.path_mode === "id_based") {
164347
- return posix.join("google-drive", safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
164366
+ return posix.join(safePathSegment(config9.profile), safePathSegment(item.drive_id), item.id, importedName);
164348
164367
  }
164349
164368
  const storageName = appendDriveFileId(importedName, item.id);
164350
164369
  const itemPath = item.path === item.name ? storageName : posix.join(dirname5(item.path), storageName);
164351
164370
  const driveSegment = item.drive_id === "my-drive" ? "my-drive" : safePathSegment(item.drive_name || item.drive_id);
164352
- return posix.join("google-drive", safePathSegment(config9.profile), driveSegment, itemPath);
164371
+ return posix.join(safePathSegment(config9.profile), driveSegment, itemPath);
164353
164372
  }
164354
164373
  function safePathSegment(value) {
164355
164374
  return value.replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").replace(/\s+/g, " ").trim() || "unnamed";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/files",
3
- "version": "0.2.18",
3
+ "version": "0.2.20",
4
4
  "description": "Agent-first file management — index local folders and S3 buckets, sync Google Drive, tag, search, and retrieve files via CLI + MCP",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",