Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

googleSheets.ts 3.2 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  1. import logger from './logger';
  2. import type { CsvRow } from './types';
  3. async function checkGoogleSheetAccess(url: string) {
  4. try {
  5. const response = await fetch(url);
  6. if (response.ok) {
  7. return { public: true, status: response.status };
  8. } else {
  9. return { public: false, status: response.status };
  10. }
  11. } catch (error) {
  12. logger.error('Error checking sheet access:', error);
  13. return { public: false };
  14. }
  15. }
  16. export async function fetchCsvFromGoogleSheet(url: string): Promise<CsvRow[]> {
  17. const { public: isPublic } = await checkGoogleSheetAccess(url);
  18. logger.debug(`Google Sheets URL: ${url}, isPublic: ${isPublic}`);
  19. if (isPublic) {
  20. return fetchCsvFromGoogleSheetUnauthenticated(url);
  21. }
  22. return fetchCsvFromGoogleSheetAuthenticated(url);
  23. }
  24. export async function fetchCsvFromGoogleSheetUnauthenticated(url: string): Promise<CsvRow[]> {
  25. const { parse: parseCsv } = await import('csv-parse/sync');
  26. const { fetchWithProxy } = await import('./fetch');
  27. const csvUrl = url.replace(/\/edit.*$/, '/export?format=csv');
  28. const response = await fetchWithProxy(csvUrl);
  29. if (response.status !== 200) {
  30. throw new Error(`Failed to fetch CSV from Google Sheets URL: ${url}`);
  31. }
  32. const csvData = await response.text();
  33. return parseCsv(csvData, { columns: true });
  34. }
  35. export async function fetchCsvFromGoogleSheetAuthenticated(url: string): Promise<CsvRow[]> {
  36. const { google } = await import('googleapis');
  37. const auth = new google.auth.GoogleAuth({
  38. scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
  39. });
  40. const sheets = google.sheets('v4');
  41. const match = url.match(/\/d\/([^/]+)/);
  42. if (!match) {
  43. throw new Error(`Invalid Google Sheets URL: ${url}`);
  44. }
  45. const spreadsheetId = match[1];
  46. const range = 'A1:ZZZ';
  47. const response = await sheets.spreadsheets.values.get({ spreadsheetId, range, auth });
  48. const rows = response.data.values;
  49. if (!rows?.length) {
  50. throw new Error(`No data found in Google Sheets URL: ${url}`);
  51. }
  52. // Assuming the first row contains headers
  53. const headers = rows[0];
  54. const dataRows = rows.slice(1);
  55. return dataRows.map((row) => {
  56. const csvRow: CsvRow = {};
  57. headers.forEach((header, index) => {
  58. csvRow[header] = row[index];
  59. });
  60. return csvRow;
  61. });
  62. }
  63. export async function writeCsvToGoogleSheet(rows: CsvRow[], url: string): Promise<void> {
  64. const { google } = await import('googleapis');
  65. const auth = new google.auth.GoogleAuth({
  66. scopes: ['https://www.googleapis.com/auth/spreadsheets'],
  67. });
  68. const sheets = google.sheets('v4');
  69. const match = url.match(/\/d\/([^/]+)/);
  70. if (!match) {
  71. throw new Error(`Invalid Google Sheets URL: ${url}`);
  72. }
  73. const spreadsheetId = match[1];
  74. const range = 'A1:ZZZ';
  75. // Extract headers from the first row
  76. const headers = Object.keys(rows[0]);
  77. // Convert rows to a 2D array
  78. const values = [headers, ...rows.map((row) => headers.map((header) => row[header]))];
  79. // Write data to the sheet
  80. logger.debug(`Writing CSV to Google Sheets URL: ${url} with ${values.length} rows`);
  81. await sheets.spreadsheets.values.update({
  82. spreadsheetId,
  83. range,
  84. valueInputOption: 'USER_ENTERED',
  85. auth,
  86. requestBody: {
  87. values,
  88. },
  89. });
  90. }
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...