@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.
- package/dist/action-entrypoint.d.ts +10 -0
- package/dist/action-entrypoint.d.ts.map +1 -1
- package/dist/esm/index.js +55 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -16
- package/dist/setup/gcpTransport.d.ts +24 -0
- package/dist/setup/gcpTransport.d.ts.map +1 -0
- package/dist/setup/wifSetup.d.ts +2 -4
- package/dist/setup/wifSetup.d.ts.map +1 -1
- package/dist/utils/driveImageSync.d.ts +6 -0
- package/dist/utils/driveImageSync.d.ts.map +1 -1
- package/dist/utils/driveSpreadsheetBootstrap.d.ts +12 -0
- package/dist/utils/driveSpreadsheetBootstrap.d.ts.map +1 -0
- package/dist/utils/getDriveTranslations.d.ts +2 -0
- package/dist/utils/getDriveTranslations.d.ts.map +1 -1
- package/dist/utils/spreadsheetFormulas.d.ts +51 -0
- package/dist/utils/spreadsheetFormulas.d.ts.map +1 -0
- package/dist/utils/spreadsheetUpdater.d.ts +2 -0
- package/dist/utils/spreadsheetUpdater.d.ts.map +1 -1
- package/dist-cli/setup-wif.mjs +196 -134
- package/package.json +22 -21
|
@@ -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
|
|
1545
|
-
|
|
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
|
|
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/
|
|
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/
|
|
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
|
|
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
|
|
2445
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAC;
|
|
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
|
|
1636
|
-
|
|
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
|
|
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/
|
|
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/
|
|
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
|
|
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
|
|
2536
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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"}
|
package/dist/setup/wifSetup.d.ts
CHANGED
|
@@ -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
|
-
|
|
37
|
-
|
|
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":"
|
|
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;
|
|
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;
|
|
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"}
|