@el-j/google-sheet-translations 2.2.0-beta.5 → 2.2.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,12 @@
1
+ /**
2
+ * Main GitHub Action entrypoint.
3
+ *
4
+ * Reads action inputs from the runner environment, configures Google Cloud
5
+ * credentials (WIF or classic service account key), executes either
6
+ * `manageDriveTranslations` (if `drive-folder-id` is present) or `getSpreadSheetData`,
7
+ * and sets step outputs (`translations-dir`, `locales-file`, `data-json-file`).
8
+ *
9
+ * @throws {Error} If authentication or required inputs are missing or sync fails.
10
+ */
1
11
  export declare function run(): Promise<void>;
2
12
  //# sourceMappingURL=action-entrypoint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-entrypoint.d.ts","sourceRoot":"","sources":["../src/action-entrypoint.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA8GzC"}
1
+ {"version":3,"file":"action-entrypoint.d.ts","sourceRoot":"","sources":["../src/action-entrypoint.ts"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA8GzC"}
package/dist/esm/index.js CHANGED
@@ -571,6 +571,8 @@ function findLocalChanges(localData, spreadsheetData) {
571
571
 
572
572
  // src/utils/spreadsheetUpdater.ts
573
573
  import { setTimeout as delay2 } from "node:timers/promises";
574
+
575
+ // src/utils/spreadsheetFormulas.ts
574
576
  function columnIndexToLetter(index) {
575
577
  let result = "";
576
578
  let i = index;
@@ -593,6 +595,8 @@ function langCodeFormula(cellRef, sep) {
593
595
  const full = `LOWER(${cellRef})`;
594
596
  return `IF(LOWER(LEFT(${cellRef}${sep}3))="zh-"${sep}${full}${sep}${prefix})`;
595
597
  }
598
+
599
+ // src/utils/spreadsheetUpdater.ts
596
600
  async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
597
601
  console.log("Updating spreadsheet with local changes...");
598
602
  const baseDelayMs = waitSeconds * 1e3;
@@ -1541,9 +1545,12 @@ async function listFilesInFolder2(folderId, token, mimeTypeFilter) {
1541
1545
  pageSize: "1000"
1542
1546
  });
1543
1547
  if (pageToken) params.set("pageToken", pageToken);
1544
- const response = await fetch(`${DRIVE_FILES_URL2}?${params.toString()}`, {
1545
- headers: { Authorization: `Bearer ${token}` }
1546
- });
1548
+ const response = await withRetry(
1549
+ () => fetch(`${DRIVE_FILES_URL2}?${params.toString()}`, {
1550
+ headers: { Authorization: `Bearer ${token}` }
1551
+ }),
1552
+ `listDriveFiles(${folderId})`
1553
+ );
1547
1554
  if (!response.ok) {
1548
1555
  const text = await response.text();
1549
1556
  throw new Error(`Drive API error ${response.status}: ${text}`);
@@ -1554,7 +1561,7 @@ async function listFilesInFolder2(folderId, token, mimeTypeFilter) {
1554
1561
  } while (pageToken);
1555
1562
  return results;
1556
1563
  }
1557
- async function collectFiles(folderId, folderRelPath, outputPath, token, allowedMimeTypes, recursive, folderPattern, normalizeExts = true) {
1564
+ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedMimeTypes, recursive, folderPattern, normalizeExts = true, nameFilter) {
1558
1565
  console.log(`[driveImageSync] Scanning folder: ${folderId} (path: "${folderRelPath}")`);
1559
1566
  const allItems = await listFilesInFolder2(folderId, token);
1560
1567
  const entries = [];
@@ -1571,10 +1578,12 @@ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedM
1571
1578
  allowedMimeTypes,
1572
1579
  recursive,
1573
1580
  folderPattern,
1574
- normalizeExts
1581
+ normalizeExts,
1582
+ nameFilter
1575
1583
  );
1576
1584
  entries.push(...subEntries);
1577
1585
  } else if (allowedMimeTypes.includes(item.mimeType)) {
1586
+ if (nameFilter && !nameFilter.test(item.name)) continue;
1578
1587
  const localName = normalizeExts ? normalizeExtension(item.name) : item.name;
1579
1588
  const localPath = folderRelPath ? join(outputPath, folderRelPath, localName) : join(outputPath, localName);
1580
1589
  entries.push({
@@ -1590,7 +1599,10 @@ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedM
1590
1599
  }
1591
1600
  async function downloadFile(fileId, localPath, token) {
1592
1601
  const url = `${DRIVE_FILES_URL2}/${fileId}?alt=media`;
1593
- const response = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
1602
+ const response = await withRetry(
1603
+ () => fetch(url, { headers: { Authorization: `Bearer ${token}` } }),
1604
+ `downloadDriveFile(${fileId})`
1605
+ );
1594
1606
  if (!response.ok) {
1595
1607
  throw new Error(`Failed to download ${fileId}: ${response.status}`);
1596
1608
  }
@@ -1627,6 +1639,7 @@ async function syncDriveImages(options) {
1627
1639
  mimeTypes = DEFAULT_IMAGE_MIME_TYPES,
1628
1640
  recursive = true,
1629
1641
  folderPattern,
1642
+ nameFilter,
1630
1643
  credentials,
1631
1644
  cleanSync = false,
1632
1645
  concurrency = 3,
@@ -1643,7 +1656,8 @@ async function syncDriveImages(options) {
1643
1656
  mimeTypes,
1644
1657
  recursive,
1645
1658
  folderPattern,
1646
- normalizeExtensions
1659
+ normalizeExtensions,
1660
+ nameFilter
1647
1661
  );
1648
1662
  const downloaded = [];
1649
1663
  const skipped = [];
@@ -2175,7 +2189,7 @@ async function ingestDoc(docFile, options = {}) {
2175
2189
  return { action: "refreshed", entry };
2176
2190
  }
2177
2191
 
2178
- // src/utils/getDriveTranslations.ts
2192
+ // src/utils/driveSpreadsheetBootstrap.ts
2179
2193
  function sanitizeFolderName(name) {
2180
2194
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "sheet";
2181
2195
  }
@@ -2205,6 +2219,8 @@ async function moveSpreadsheetToFolder(spreadsheetId, folderId) {
2205
2219
  }
2206
2220
  });
2207
2221
  }
2222
+
2223
+ // src/utils/getDriveTranslations.ts
2208
2224
  async function manageDriveTranslations(options) {
2209
2225
  const {
2210
2226
  driveFolderId,
@@ -2401,7 +2417,7 @@ async function manageDriveTranslations(options) {
2401
2417
  return { translations, spreadsheetIds: filteredIds, imageSync, manifest, docIngestResults };
2402
2418
  }
2403
2419
 
2404
- // src/setup/wifSetup.ts
2420
+ // src/setup/gcpTransport.ts
2405
2421
  import { GoogleAuth as GoogleAuth4 } from "google-auth-library";
2406
2422
  var GcpApiError = class extends Error {
2407
2423
  constructor(message, status) {
@@ -2410,7 +2426,7 @@ var GcpApiError = class extends Error {
2410
2426
  this.name = "GcpApiError";
2411
2427
  }
2412
2428
  };
2413
- async function getAccessToken4(keyFilePath) {
2429
+ async function getGcpAccessToken(keyFilePath) {
2414
2430
  const auth = new GoogleAuth4({
2415
2431
  ...keyFilePath ? { keyFilename: keyFilePath } : {},
2416
2432
  scopes: ["https://www.googleapis.com/auth/cloud-platform"]
@@ -2441,8 +2457,26 @@ async function gcpFetch(url, token, method = "GET", body) {
2441
2457
  }
2442
2458
  return data;
2443
2459
  }
2444
- async function pollOperation(operationName, token, maxWaitMs = 6e4) {
2445
- const opUrl = operationName.startsWith("http") ? operationName : `https://iam.googleapis.com/v1/${operationName}`;
2460
+ async function waitForOperation(operationName, token, maxWaitMs = 6e4) {
2461
+ let opUrl;
2462
+ if (operationName.startsWith("http")) {
2463
+ let isGoogleHost;
2464
+ try {
2465
+ const parsedUrl = new URL(operationName);
2466
+ const hostname = (parsedUrl.hostname || "").toLowerCase();
2467
+ isGoogleHost = hostname === "iam.googleapis.com" || hostname.endsWith(".iam.googleapis.com") || hostname === "googleapis.com" || hostname.endsWith(".googleapis.com");
2468
+ } catch {
2469
+ isGoogleHost = false;
2470
+ }
2471
+ if (!isGoogleHost) {
2472
+ throw new Error(
2473
+ `Invalid operation URL: hostname must be a Google API endpoint (*.googleapis.com), got: ${operationName}`
2474
+ );
2475
+ }
2476
+ opUrl = operationName;
2477
+ } else {
2478
+ opUrl = `https://iam.googleapis.com/v1/${operationName}`;
2479
+ }
2446
2480
  const deadline = Date.now() + maxWaitMs;
2447
2481
  const maxWaitSecs = Math.round(maxWaitMs / 1e3);
2448
2482
  while (Date.now() < deadline) {
@@ -2461,6 +2495,8 @@ async function pollOperation(operationName, token, maxWaitMs = 6e4) {
2461
2495
  );
2462
2496
  }
2463
2497
  }
2498
+
2499
+ // src/setup/wifSetup.ts
2464
2500
  async function getProjectNumber(projectId, token) {
2465
2501
  const data = await gcpFetch(
2466
2502
  `https://cloudresourcemanager.googleapis.com/v1/projects/${encodeURIComponent(projectId)}`,
@@ -2481,7 +2517,7 @@ async function createOrGetWifPool(projectId, poolId, token) {
2481
2517
  }
2482
2518
  );
2483
2519
  if (!op.done) {
2484
- await pollOperation(op.name, token);
2520
+ await waitForOperation(op.name, token);
2485
2521
  } else if (op.error) {
2486
2522
  throw new Error(`Operation failed: ${op.error.message}`);
2487
2523
  }
@@ -2514,7 +2550,7 @@ async function createOrGetWifProvider(projectId, poolId, providerId, githubRepo,
2514
2550
  }
2515
2551
  );
2516
2552
  if (!op.done) {
2517
- await pollOperation(op.name, token);
2553
+ await waitForOperation(op.name, token);
2518
2554
  } else if (op.error) {
2519
2555
  throw new Error(`Operation failed: ${op.error.message}`);
2520
2556
  }
@@ -2562,7 +2598,7 @@ async function setupWIF(options) {
2562
2598
  );
2563
2599
  }
2564
2600
  log("Authenticating with Google Cloud...");
2565
- const token = await getAccessToken4(options.keyFilePath);
2601
+ const token = await getGcpAccessToken(options.keyFilePath);
2566
2602
  log("Fetching project number...");
2567
2603
  const projectNumber = await getProjectNumber(options.projectId, token);
2568
2604
  log(`Creating Workload Identity Pool "${poolId}"...`);
@@ -2588,7 +2624,7 @@ async function setupWIF(options) {
2588
2624
  return { wifProvider, projectNumber, poolId, providerId };
2589
2625
  }
2590
2626
  async function grantDrivePermissions(options) {
2591
- const token = await getAccessToken4(options.keyFilePath);
2627
+ const token = await getGcpAccessToken(options.keyFilePath);
2592
2628
  const policy = await gcpFetch(
2593
2629
  `https://cloudresourcemanager.googleapis.com/v1/projects/${encodeURIComponent(options.projectId)}:getIamPolicy`,
2594
2630
  token,
@@ -2623,6 +2659,7 @@ export {
2623
2659
  GcpApiError,
2624
2660
  buildGoogleAuth,
2625
2661
  buildManifest,
2662
+ columnIndexToLetter,
2626
2663
  convertFromDataJsonFormat,
2627
2664
  convertToDataJsonFormat,
2628
2665
  createAuthClient,
@@ -2650,6 +2687,7 @@ export {
2650
2687
  manageDriveTranslations,
2651
2688
  mergeMultipleTranslationData,
2652
2689
  mergeSheets,
2690
+ moveSpreadsheetToFolder,
2653
2691
  normalizeExtension,
2654
2692
  normalizeLocaleCode,
2655
2693
  normalizePrivateKey,
@@ -2658,6 +2696,7 @@ export {
2658
2696
  readManifest,
2659
2697
  readPublicSheet,
2660
2698
  resolveLocaleWithFallback,
2699
+ sanitizeFolderName,
2661
2700
  scanDriveFolderForDocs,
2662
2701
  scanDriveFolderForSpreadsheets,
2663
2702
  setupWIF,
package/dist/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export { createAuthClient, buildGoogleAuth, normalizePrivateKey } from './utils/
11
11
  export { convertToDataJsonFormat } from './utils/dataConverter/convertToDataJsonFormat';
12
12
  export { convertFromDataJsonFormat } from './utils/dataConverter/convertFromDataJsonFormat';
13
13
  export { findLocalChanges } from './utils/dataConverter/findLocalChanges';
14
- export { updateSpreadsheetWithLocalChanges } from './utils/spreadsheetUpdater';
14
+ export { updateSpreadsheetWithLocalChanges, columnIndexToLetter } from './utils/spreadsheetUpdater';
15
15
  export { readPublicSheet } from './utils/publicSheetReader';
16
16
  export { createSpreadsheet } from './utils/spreadsheetCreator';
17
17
  export { validateCredentials } from './utils/validateEnv';
@@ -34,7 +34,7 @@ export { syncDriveImages, normalizeExtension } from './utils/driveImageSync';
34
34
  export type { DriveImageSyncOptions, DriveImageSyncResult } from './utils/driveImageSync';
35
35
  export { walkDirectory, validateImageDirectory, DEFAULT_IMAGE_EXTENSIONS } from './utils/localImageUtils';
36
36
  export type { WalkDirectoryOptions, ImageDirectoryValidationOptions, ImageDirectoryValidationResult, } from './utils/localImageUtils';
37
- export { manageDriveTranslations } from './utils/getDriveTranslations';
37
+ export { manageDriveTranslations, sanitizeFolderName, moveSpreadsheetToFolder } from './utils/getDriveTranslations';
38
38
  export type { GoogleDriveManagerOptions, GoogleDriveManagerResult } from './utils/getDriveTranslations';
39
39
  export { buildManifest, writeManifest, readManifest } from './utils/driveProjectIndex';
40
40
  export type { DriveProjectManifest, SpreadsheetManifestEntry, BuildManifestOptions, DocManifestEntry } from './utils/driveProjectIndex';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  GcpApiError: () => GcpApiError,
36
36
  buildGoogleAuth: () => buildGoogleAuth,
37
37
  buildManifest: () => buildManifest,
38
+ columnIndexToLetter: () => columnIndexToLetter,
38
39
  convertFromDataJsonFormat: () => convertFromDataJsonFormat,
39
40
  convertToDataJsonFormat: () => convertToDataJsonFormat,
40
41
  createAuthClient: () => createAuthClient,
@@ -62,6 +63,7 @@ __export(index_exports, {
62
63
  manageDriveTranslations: () => manageDriveTranslations,
63
64
  mergeMultipleTranslationData: () => mergeMultipleTranslationData,
64
65
  mergeSheets: () => mergeSheets,
66
+ moveSpreadsheetToFolder: () => moveSpreadsheetToFolder,
65
67
  normalizeExtension: () => normalizeExtension,
66
68
  normalizeLocaleCode: () => normalizeLocaleCode,
67
69
  normalizePrivateKey: () => normalizePrivateKey,
@@ -70,6 +72,7 @@ __export(index_exports, {
70
72
  readManifest: () => readManifest,
71
73
  readPublicSheet: () => readPublicSheet,
72
74
  resolveLocaleWithFallback: () => resolveLocaleWithFallback,
75
+ sanitizeFolderName: () => sanitizeFolderName,
73
76
  scanDriveFolderForDocs: () => scanDriveFolderForDocs,
74
77
  scanDriveFolderForSpreadsheets: () => scanDriveFolderForSpreadsheets,
75
78
  setupWIF: () => setupWIF,
@@ -662,6 +665,8 @@ function findLocalChanges(localData, spreadsheetData) {
662
665
 
663
666
  // src/utils/spreadsheetUpdater.ts
664
667
  var import_promises2 = require("node:timers/promises");
668
+
669
+ // src/utils/spreadsheetFormulas.ts
665
670
  function columnIndexToLetter(index) {
666
671
  let result = "";
667
672
  let i = index;
@@ -684,6 +689,8 @@ function langCodeFormula(cellRef, sep) {
684
689
  const full = `LOWER(${cellRef})`;
685
690
  return `IF(LOWER(LEFT(${cellRef}${sep}3))="zh-"${sep}${full}${sep}${prefix})`;
686
691
  }
692
+
693
+ // src/utils/spreadsheetUpdater.ts
687
694
  async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
688
695
  console.log("Updating spreadsheet with local changes...");
689
696
  const baseDelayMs = waitSeconds * 1e3;
@@ -1632,9 +1639,12 @@ async function listFilesInFolder2(folderId, token, mimeTypeFilter) {
1632
1639
  pageSize: "1000"
1633
1640
  });
1634
1641
  if (pageToken) params.set("pageToken", pageToken);
1635
- const response = await fetch(`${DRIVE_FILES_URL2}?${params.toString()}`, {
1636
- headers: { Authorization: `Bearer ${token}` }
1637
- });
1642
+ const response = await withRetry(
1643
+ () => fetch(`${DRIVE_FILES_URL2}?${params.toString()}`, {
1644
+ headers: { Authorization: `Bearer ${token}` }
1645
+ }),
1646
+ `listDriveFiles(${folderId})`
1647
+ );
1638
1648
  if (!response.ok) {
1639
1649
  const text = await response.text();
1640
1650
  throw new Error(`Drive API error ${response.status}: ${text}`);
@@ -1645,7 +1655,7 @@ async function listFilesInFolder2(folderId, token, mimeTypeFilter) {
1645
1655
  } while (pageToken);
1646
1656
  return results;
1647
1657
  }
1648
- async function collectFiles(folderId, folderRelPath, outputPath, token, allowedMimeTypes, recursive, folderPattern, normalizeExts = true) {
1658
+ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedMimeTypes, recursive, folderPattern, normalizeExts = true, nameFilter) {
1649
1659
  console.log(`[driveImageSync] Scanning folder: ${folderId} (path: "${folderRelPath}")`);
1650
1660
  const allItems = await listFilesInFolder2(folderId, token);
1651
1661
  const entries = [];
@@ -1662,10 +1672,12 @@ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedM
1662
1672
  allowedMimeTypes,
1663
1673
  recursive,
1664
1674
  folderPattern,
1665
- normalizeExts
1675
+ normalizeExts,
1676
+ nameFilter
1666
1677
  );
1667
1678
  entries.push(...subEntries);
1668
1679
  } else if (allowedMimeTypes.includes(item.mimeType)) {
1680
+ if (nameFilter && !nameFilter.test(item.name)) continue;
1669
1681
  const localName = normalizeExts ? normalizeExtension(item.name) : item.name;
1670
1682
  const localPath = folderRelPath ? (0, import_node_path5.join)(outputPath, folderRelPath, localName) : (0, import_node_path5.join)(outputPath, localName);
1671
1683
  entries.push({
@@ -1681,7 +1693,10 @@ async function collectFiles(folderId, folderRelPath, outputPath, token, allowedM
1681
1693
  }
1682
1694
  async function downloadFile(fileId, localPath, token) {
1683
1695
  const url = `${DRIVE_FILES_URL2}/${fileId}?alt=media`;
1684
- const response = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
1696
+ const response = await withRetry(
1697
+ () => fetch(url, { headers: { Authorization: `Bearer ${token}` } }),
1698
+ `downloadDriveFile(${fileId})`
1699
+ );
1685
1700
  if (!response.ok) {
1686
1701
  throw new Error(`Failed to download ${fileId}: ${response.status}`);
1687
1702
  }
@@ -1718,6 +1733,7 @@ async function syncDriveImages(options) {
1718
1733
  mimeTypes = DEFAULT_IMAGE_MIME_TYPES,
1719
1734
  recursive = true,
1720
1735
  folderPattern,
1736
+ nameFilter,
1721
1737
  credentials,
1722
1738
  cleanSync = false,
1723
1739
  concurrency = 3,
@@ -1734,7 +1750,8 @@ async function syncDriveImages(options) {
1734
1750
  mimeTypes,
1735
1751
  recursive,
1736
1752
  folderPattern,
1737
- normalizeExtensions
1753
+ normalizeExtensions,
1754
+ nameFilter
1738
1755
  );
1739
1756
  const downloaded = [];
1740
1757
  const skipped = [];
@@ -2266,7 +2283,7 @@ async function ingestDoc(docFile, options = {}) {
2266
2283
  return { action: "refreshed", entry };
2267
2284
  }
2268
2285
 
2269
- // src/utils/getDriveTranslations.ts
2286
+ // src/utils/driveSpreadsheetBootstrap.ts
2270
2287
  function sanitizeFolderName(name) {
2271
2288
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "sheet";
2272
2289
  }
@@ -2296,6 +2313,8 @@ async function moveSpreadsheetToFolder(spreadsheetId, folderId) {
2296
2313
  }
2297
2314
  });
2298
2315
  }
2316
+
2317
+ // src/utils/getDriveTranslations.ts
2299
2318
  async function manageDriveTranslations(options) {
2300
2319
  const {
2301
2320
  driveFolderId,
@@ -2492,7 +2511,7 @@ async function manageDriveTranslations(options) {
2492
2511
  return { translations, spreadsheetIds: filteredIds, imageSync, manifest, docIngestResults };
2493
2512
  }
2494
2513
 
2495
- // src/setup/wifSetup.ts
2514
+ // src/setup/gcpTransport.ts
2496
2515
  var import_google_auth_library4 = require("google-auth-library");
2497
2516
  var GcpApiError = class extends Error {
2498
2517
  constructor(message, status) {
@@ -2501,7 +2520,7 @@ var GcpApiError = class extends Error {
2501
2520
  this.name = "GcpApiError";
2502
2521
  }
2503
2522
  };
2504
- async function getAccessToken4(keyFilePath) {
2523
+ async function getGcpAccessToken(keyFilePath) {
2505
2524
  const auth = new import_google_auth_library4.GoogleAuth({
2506
2525
  ...keyFilePath ? { keyFilename: keyFilePath } : {},
2507
2526
  scopes: ["https://www.googleapis.com/auth/cloud-platform"]
@@ -2532,8 +2551,26 @@ async function gcpFetch(url, token, method = "GET", body) {
2532
2551
  }
2533
2552
  return data;
2534
2553
  }
2535
- async function pollOperation(operationName, token, maxWaitMs = 6e4) {
2536
- const opUrl = operationName.startsWith("http") ? operationName : `https://iam.googleapis.com/v1/${operationName}`;
2554
+ async function waitForOperation(operationName, token, maxWaitMs = 6e4) {
2555
+ let opUrl;
2556
+ if (operationName.startsWith("http")) {
2557
+ let isGoogleHost;
2558
+ try {
2559
+ const parsedUrl = new URL(operationName);
2560
+ const hostname = (parsedUrl.hostname || "").toLowerCase();
2561
+ isGoogleHost = hostname === "iam.googleapis.com" || hostname.endsWith(".iam.googleapis.com") || hostname === "googleapis.com" || hostname.endsWith(".googleapis.com");
2562
+ } catch {
2563
+ isGoogleHost = false;
2564
+ }
2565
+ if (!isGoogleHost) {
2566
+ throw new Error(
2567
+ `Invalid operation URL: hostname must be a Google API endpoint (*.googleapis.com), got: ${operationName}`
2568
+ );
2569
+ }
2570
+ opUrl = operationName;
2571
+ } else {
2572
+ opUrl = `https://iam.googleapis.com/v1/${operationName}`;
2573
+ }
2537
2574
  const deadline = Date.now() + maxWaitMs;
2538
2575
  const maxWaitSecs = Math.round(maxWaitMs / 1e3);
2539
2576
  while (Date.now() < deadline) {
@@ -2552,6 +2589,8 @@ async function pollOperation(operationName, token, maxWaitMs = 6e4) {
2552
2589
  );
2553
2590
  }
2554
2591
  }
2592
+
2593
+ // src/setup/wifSetup.ts
2555
2594
  async function getProjectNumber(projectId, token) {
2556
2595
  const data = await gcpFetch(
2557
2596
  `https://cloudresourcemanager.googleapis.com/v1/projects/${encodeURIComponent(projectId)}`,
@@ -2572,7 +2611,7 @@ async function createOrGetWifPool(projectId, poolId, token) {
2572
2611
  }
2573
2612
  );
2574
2613
  if (!op.done) {
2575
- await pollOperation(op.name, token);
2614
+ await waitForOperation(op.name, token);
2576
2615
  } else if (op.error) {
2577
2616
  throw new Error(`Operation failed: ${op.error.message}`);
2578
2617
  }
@@ -2605,7 +2644,7 @@ async function createOrGetWifProvider(projectId, poolId, providerId, githubRepo,
2605
2644
  }
2606
2645
  );
2607
2646
  if (!op.done) {
2608
- await pollOperation(op.name, token);
2647
+ await waitForOperation(op.name, token);
2609
2648
  } else if (op.error) {
2610
2649
  throw new Error(`Operation failed: ${op.error.message}`);
2611
2650
  }
@@ -2653,7 +2692,7 @@ async function setupWIF(options) {
2653
2692
  );
2654
2693
  }
2655
2694
  log("Authenticating with Google Cloud...");
2656
- const token = await getAccessToken4(options.keyFilePath);
2695
+ const token = await getGcpAccessToken(options.keyFilePath);
2657
2696
  log("Fetching project number...");
2658
2697
  const projectNumber = await getProjectNumber(options.projectId, token);
2659
2698
  log(`Creating Workload Identity Pool "${poolId}"...`);
@@ -2679,7 +2718,7 @@ async function setupWIF(options) {
2679
2718
  return { wifProvider, projectNumber, poolId, providerId };
2680
2719
  }
2681
2720
  async function grantDrivePermissions(options) {
2682
- const token = await getAccessToken4(options.keyFilePath);
2721
+ const token = await getGcpAccessToken(options.keyFilePath);
2683
2722
  const policy = await gcpFetch(
2684
2723
  `https://cloudresourcemanager.googleapis.com/v1/projects/${encodeURIComponent(options.projectId)}:getIamPolicy`,
2685
2724
  token,
@@ -2715,6 +2754,7 @@ var index_default = getSpreadSheetData;
2715
2754
  GcpApiError,
2716
2755
  buildGoogleAuth,
2717
2756
  buildManifest,
2757
+ columnIndexToLetter,
2718
2758
  convertFromDataJsonFormat,
2719
2759
  convertToDataJsonFormat,
2720
2760
  createAuthClient,
@@ -2741,6 +2781,7 @@ var index_default = getSpreadSheetData;
2741
2781
  manageDriveTranslations,
2742
2782
  mergeMultipleTranslationData,
2743
2783
  mergeSheets,
2784
+ moveSpreadsheetToFolder,
2744
2785
  normalizeExtension,
2745
2786
  normalizeLocaleCode,
2746
2787
  normalizePrivateKey,
@@ -2749,6 +2790,7 @@ var index_default = getSpreadSheetData;
2749
2790
  readManifest,
2750
2791
  readPublicSheet,
2751
2792
  resolveLocaleWithFallback,
2793
+ sanitizeFolderName,
2752
2794
  scanDriveFolderForDocs,
2753
2795
  scanDriveFolderForSpreadsheets,
2754
2796
  setupWIF,
@@ -0,0 +1,24 @@
1
+ export interface GcpOperation {
2
+ name: string;
3
+ done?: boolean;
4
+ error?: {
5
+ code: number;
6
+ message: string;
7
+ };
8
+ }
9
+ export interface IamPolicy {
10
+ bindings?: Array<{
11
+ role: string;
12
+ members: string[];
13
+ }>;
14
+ etag?: string;
15
+ version?: number;
16
+ }
17
+ export declare class GcpApiError extends Error {
18
+ readonly status: number;
19
+ constructor(message: string, status: number);
20
+ }
21
+ export declare function getGcpAccessToken(keyFilePath?: string): Promise<string>;
22
+ export declare function gcpFetch(url: string, token: string, method?: string, body?: unknown): Promise<unknown>;
23
+ export declare function waitForOperation(operationName: string, token: string, maxWaitMs?: number): Promise<void>;
24
+ //# sourceMappingURL=gcpTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcpTransport.d.ts","sourceRoot":"","sources":["../../src/setup/gcpTransport.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAY,SAAQ,KAAK;aAGpB,MAAM,EAAE,MAAM;gBAD9B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM;CAK/B;AAED,wBAAsB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB7E;AAED,wBAAsB,QAAQ,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,MAAM,SAAQ,EACd,IAAI,CAAC,EAAE,OAAO,GACZ,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED,wBAAsB,gBAAgB,CACrC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,SAAS,SAAS,GAChB,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
@@ -33,10 +33,8 @@ export interface GrantDrivePermissionsOptions {
33
33
  /** Path to a service account JSON key file used for bootstrapping. */
34
34
  keyFilePath?: string;
35
35
  }
36
- export declare class GcpApiError extends Error {
37
- readonly status: number;
38
- constructor(message: string, status: number);
39
- }
36
+ import { GcpApiError } from "./gcpTransport";
37
+ export { GcpApiError };
40
38
  /**
41
39
  * Configures Workload Identity Federation (WIF) on Google Cloud so that
42
40
  * GitHub Actions can authenticate without a long-lived service account key.
@@ -1 +1 @@
1
- {"version":3,"file":"wifSetup.d.ts","sourceRoot":"","sources":["../../src/setup/wifSetup.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC/B,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;sEACkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC9B,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC5C,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAkBD,qBAAa,WAAY,SAAQ,KAAK;aAGpB,MAAM,EAAE,MAAM;gBAD9B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM;CAK/B;AAqMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAyChF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
1
+ {"version":3,"file":"wifSetup.d.ts","sourceRoot":"","sources":["../../src/setup/wifSetup.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC/B,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;sEACkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC9B,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC5C,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,OAAO,EACN,WAAW,EAMX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,CAAC;AA0HvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAyChF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -15,6 +15,12 @@ export interface DriveImageSyncOptions {
15
15
  * Useful for patterns like `/^projects\//` or `/icons$/`.
16
16
  */
17
17
  folderPattern?: RegExp;
18
+ /**
19
+ * Optional regular expression to filter file names. Only files whose name
20
+ * matches this pattern will be downloaded.
21
+ * Example: `/^icon-/` or `/\.(png|svg)$/i`.
22
+ */
23
+ nameFilter?: RegExp;
18
24
  /** Google service account credentials (falls back to env vars) */
19
25
  credentials?: GoogleEnvVars;
20
26
  /** If true, delete local files that no longer exist in Drive (default: false) */
@@ -1 +1 @@
1
- {"version":3,"file":"driveImageSync.d.ts","sourceRoot":"","sources":["../../src/utils/driveImageSync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAwCD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvD;AA2JD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA4F/B"}
1
+ {"version":3,"file":"driveImageSync.d.ts","sourceRoot":"","sources":["../../src/utils/driveImageSync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAwCD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvD;AAuKD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA8F/B"}
@@ -0,0 +1,12 @@
1
+ /** Turns a spreadsheet name / ID into a safe directory segment */
2
+ export declare function sanitizeFolderName(name: string): string;
3
+ /**
4
+ * Moves a Google Spreadsheet (identified by `spreadsheetId`) into the given
5
+ * Drive folder by calling the Drive Files API with the `drive.file` scope.
6
+ *
7
+ * The service-account must have been granted edit access to the target folder.
8
+ * Uses the same credential detection order as `createAuthClient` (WIF first,
9
+ * then `GOOGLE_CLIENT_EMAIL` + `GOOGLE_PRIVATE_KEY`).
10
+ */
11
+ export declare function moveSpreadsheetToFolder(spreadsheetId: string, folderId: string): Promise<void>;
12
+ //# sourceMappingURL=driveSpreadsheetBootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driveSpreadsheetBootstrap.d.ts","sourceRoot":"","sources":["../../src/utils/driveSpreadsheetBootstrap.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -132,6 +132,8 @@ export interface GoogleDriveManagerResult {
132
132
  action: 'created' | 'refreshed' | 'skipped';
133
133
  }>;
134
134
  }
135
+ import { sanitizeFolderName, moveSpreadsheetToFolder } from './driveSpreadsheetBootstrap';
136
+ export { sanitizeFolderName, moveSpreadsheetToFolder };
135
137
  /**
136
138
  * Top-level "headless CMS bridge" function.
137
139
  *
@@ -1 +1 @@
1
- {"version":3,"file":"getDriveTranslations.d.ts","sourceRoot":"","sources":["../../src/utils/getDriveTranslations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAM9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEpF,OAAO,KAAK,EAAoB,oBAAoB,EAA4B,MAAM,qBAAqB,CAAC;AAI5G,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAElD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAE7C,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI1C;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,eAAe,CAAC;IAC9B,kDAAkD;IAClD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;CAC5F;AA2DD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAuPnC"}
1
+ {"version":3,"file":"getDriveTranslations.d.ts","sourceRoot":"","sources":["../../src/utils/getDriveTranslations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAM9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEpF,OAAO,KAAK,EAAoB,oBAAoB,EAA4B,MAAM,qBAAqB,CAAC;AAI5G,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAElD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAE7C,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI1C;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,eAAe,CAAC;IAC9B,kDAAkD;IAClD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;CAC5F;AAED,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAuPnC"}