google-drive-picker.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Google Drive Picker API configuration
  2. const API_KEY = import.meta.env.VITE_GOOGLE_API_KEY;
  3. const CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
  4. const SCOPE = ['https://www.googleapis.com/auth/drive.readonly'];
  5. // Validate required credentials
  6. const validateCredentials = () => {
  7. if (!API_KEY || !CLIENT_ID) {
  8. throw new Error('Google Drive API credentials not configured');
  9. }
  10. if (API_KEY === 'your-api-key' || CLIENT_ID === 'your-client-id') {
  11. throw new Error('Please configure valid Google Drive API credentials');
  12. }
  13. };
  14. let pickerApiLoaded = false;
  15. let oauthToken: string | null = null;
  16. let initialized = false;
  17. export const loadGoogleDriveApi = () => {
  18. return new Promise((resolve, reject) => {
  19. if (typeof gapi === 'undefined') {
  20. const script = document.createElement('script');
  21. script.src = 'https://apis.google.com/js/api.js';
  22. script.onload = () => {
  23. gapi.load('picker', {
  24. callback: () => {
  25. pickerApiLoaded = true;
  26. resolve(true);
  27. }
  28. });
  29. };
  30. script.onerror = reject;
  31. document.body.appendChild(script);
  32. } else {
  33. gapi.load('picker', {
  34. callback: () => {
  35. pickerApiLoaded = true;
  36. resolve(true);
  37. }
  38. });
  39. }
  40. });
  41. };
  42. export const loadGoogleAuthApi = () => {
  43. return new Promise((resolve, reject) => {
  44. if (typeof google === 'undefined') {
  45. const script = document.createElement('script');
  46. script.src = 'https://accounts.google.com/gsi/client';
  47. script.onload = resolve;
  48. script.onerror = reject;
  49. document.body.appendChild(script);
  50. } else {
  51. resolve(true);
  52. }
  53. });
  54. };
  55. export const getAuthToken = async () => {
  56. if (!oauthToken) {
  57. const tokenClient = google.accounts.oauth2.initTokenClient({
  58. client_id: CLIENT_ID,
  59. scope: SCOPE.join(' '),
  60. callback: (response: any) => {
  61. if (response.access_token) {
  62. oauthToken = response.access_token;
  63. }
  64. },
  65. });
  66. await tokenClient.requestAccessToken();
  67. }
  68. return oauthToken;
  69. };
  70. const initialize = async () => {
  71. if (!initialized) {
  72. validateCredentials();
  73. await Promise.all([loadGoogleDriveApi(), loadGoogleAuthApi()]);
  74. initialized = true;
  75. }
  76. };
  77. export const createPicker = () => {
  78. return new Promise(async (resolve, reject) => {
  79. try {
  80. await initialize();
  81. const token = await getAuthToken();
  82. if (!token) {
  83. throw new Error('Unable to get OAuth token');
  84. }
  85. const picker = new google.picker.PickerBuilder()
  86. .addView(google.picker.ViewId.DOCS)
  87. .setOAuthToken(token)
  88. .setDeveloperKey(API_KEY)
  89. .setCallback((data: any) => {
  90. if (data[google.picker.Response.ACTION] === google.picker.Action.PICKED) {
  91. const doc = data[google.picker.Response.DOCUMENTS][0];
  92. const fileId = doc[google.picker.Document.ID];
  93. const fileName = doc[google.picker.Document.NAME];
  94. const fileUrl = doc[google.picker.Document.URL];
  95. resolve({
  96. id: fileId,
  97. name: fileName,
  98. url: fileUrl
  99. });
  100. } else if (data[google.picker.Response.ACTION] === google.picker.Action.CANCEL) {
  101. resolve(null);
  102. }
  103. })
  104. .build();
  105. picker.setVisible(true);
  106. } catch (error) {
  107. reject(error);
  108. }
  109. });
  110. };