@cooperation/vc-storage 1.0.22 → 1.0.24

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.
@@ -30,30 +30,136 @@ export class ResumeVC {
30
30
  return unsignedCredential;
31
31
  }
32
32
  generateUnsignedCredential({ formData, issuerDid }) {
33
- const unsignedCredential = {
33
+ const unsignedResumeVC = {
34
34
  '@context': [
35
- 'https://www.w3.org/2018/credentials/v1', // Standard VC context
35
+ 'https://www.w3.org/2018/credentials/v1',
36
36
  inlineResumeContext['@context'], // Inline context
37
37
  ],
38
- id: `urn:uuid:${uuidv4()}`, // Generate a dynamic UUID
39
- type: ['VerifiableCredential'],
38
+ id: `urn:uuid:${uuidv4()}`, // Generate a unique UUID
39
+ type: ['VerifiableCredential', 'LERRSCredential'], // LER-RS compliant credential type
40
40
  issuer: issuerDid,
41
- issuanceDate: new Date().toISOString(),
41
+ issuanceDate: new Date().toISOString(), // Current date/time in ISO format
42
42
  credentialSubject: {
43
43
  type: 'Resume',
44
44
  person: {
45
45
  name: {
46
- formattedName: formData.formattedName,
46
+ formattedName: formData.name || '',
47
47
  },
48
- primaryLanguage: formData.primaryLanguage,
48
+ primaryLanguage: 'en',
49
+ contact: {
50
+ fullName: formData.contact.fullName || '',
51
+ email: formData.contact.email || '',
52
+ phone: formData.contact.phone || '',
53
+ location: {
54
+ street: formData.contact.location.street || '',
55
+ city: formData.contact.location.city || '',
56
+ state: formData.contact.location.state || '',
57
+ country: formData.contact.location.country || '',
58
+ postalCode: formData.contact.location.postalCode || '',
59
+ },
60
+ socialLinks: {
61
+ linkedin: formData.contact.socialLinks.linkedin || '',
62
+ github: formData.contact.socialLinks.github || '',
63
+ portfolio: formData.contact.socialLinks.portfolio || '',
64
+ twitter: formData.contact.socialLinks.twitter || '',
65
+ },
66
+ },
67
+ },
68
+ narrative: {
69
+ text: formData.summary || '',
49
70
  },
50
- narrative: formData.narrative,
51
- employmentHistory: formData.employmentHistory,
52
- skills: formData.skills,
53
- educationAndLearning: formData.educationAndLearning,
71
+ // Employment History
72
+ employmentHistory: formData.experience.items.map((exp) => ({
73
+ organization: {
74
+ tradeName: exp.company || '',
75
+ },
76
+ title: exp.title || '',
77
+ description: exp.description || '',
78
+ startDate: exp.startDate || '',
79
+ endDate: exp.endDate || '',
80
+ stillEmployed: exp.stillEmployed || false,
81
+ })),
82
+ // Duplicated Experience (Raw)
83
+ experience: formData.experience.items.map((exp) => ({
84
+ company: exp.company || '',
85
+ title: exp.title || '',
86
+ description: exp.description || '',
87
+ startDate: exp.startDate || '',
88
+ endDate: exp.endDate || '',
89
+ stillEmployed: exp.stillEmployed || false,
90
+ })),
91
+ // Skills
92
+ skills: formData.skills.items.map((skill) => ({
93
+ name: skill.name || '',
94
+ })),
95
+ // Education
96
+ educationAndLearning: formData.education.items.map((edu) => ({
97
+ institution: edu.institution || '',
98
+ degree: edu.degree || '',
99
+ fieldOfStudy: edu.fieldOfStudy || '',
100
+ startDate: edu.startDate || '',
101
+ endDate: edu.endDate || '',
102
+ })),
103
+ // Awards
104
+ awards: formData.awards.items.map((award) => ({
105
+ title: award.title || '',
106
+ issuer: award.issuer || '',
107
+ date: award.date || '',
108
+ description: award.description || '',
109
+ })),
110
+ // Publications
111
+ publications: formData.publications.items.map((pub) => ({
112
+ title: pub.title || '',
113
+ publisher: pub.publisher || '',
114
+ date: pub.date || '',
115
+ url: pub.url || '',
116
+ })),
117
+ // Certifications
118
+ certifications: formData.certifications.items.map((cert) => ({
119
+ name: cert.name || '',
120
+ issuer: cert.issuer || '',
121
+ date: cert.date || '',
122
+ url: cert.url || '',
123
+ })),
124
+ // Professional Affiliations
125
+ professionalAffiliations: formData.professionalAffiliations.items.map((aff) => ({
126
+ organization: aff.organization || '',
127
+ role: aff.role || '',
128
+ startDate: aff.startDate || '',
129
+ endDate: aff.endDate || '',
130
+ })),
131
+ // Volunteer Work
132
+ volunteerWork: formData.volunteerWork.items.map((vol) => ({
133
+ organization: vol.organization || '',
134
+ role: vol.role || '',
135
+ description: vol.description || '',
136
+ startDate: vol.startDate || '',
137
+ endDate: vol.endDate || '',
138
+ })),
139
+ // Hobbies and Interests
140
+ hobbiesAndInterests: formData.hobbiesAndInterests || [],
141
+ // Languages
142
+ languages: formData.languages.items.map((lang) => ({
143
+ language: lang.language || '',
144
+ proficiency: lang.proficiency || '',
145
+ })),
146
+ // Testimonials
147
+ testimonials: formData.testimonials.items.map((testi) => ({
148
+ author: testi.author || '',
149
+ text: testi.text || '',
150
+ date: testi.date || '',
151
+ })),
152
+ // Projects
153
+ projects: formData.projects.items.map((proj) => ({
154
+ name: proj.name || '',
155
+ description: proj.description || '',
156
+ url: proj.url || '',
157
+ startDate: proj.startDate || '',
158
+ endDate: proj.endDate || '',
159
+ })),
54
160
  },
55
161
  };
56
- return unsignedCredential;
162
+ return unsignedResumeVC;
57
163
  }
58
164
  generateKeyPair = async (address) => {
59
165
  // Generate the key pair using the library's method
@@ -1,4 +1,5 @@
1
1
  import { DidDocument, KeyPair, FormDataI, RecommendationFormDataI, VerifiableCredential } from '../../types/credential.js';
2
+ import { GoogleDriveStorage } from './GoogleDriveStorage.js';
2
3
  interface SignPropsI {
3
4
  data: FormDataI | RecommendationFormDataI;
4
5
  type: 'VC' | 'RECOMMENDATION';
@@ -9,7 +10,6 @@ interface SignPropsI {
9
10
  /**
10
11
  * Class representing the Credential Engine.
11
12
  * @class CredentialEngine
12
- * @param {string} accessToken - The access token for the user.
13
13
  * @classdesc Credential Engine class to create DIDs and VCs.
14
14
  * @method createDID - Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
15
15
  * @method createWalletDID - Create a new DID with user metamask address as controller.
@@ -21,7 +21,7 @@ interface SignPropsI {
21
21
  export declare class CredentialEngine {
22
22
  private storage;
23
23
  private keyPair;
24
- constructor(accessToken: string);
24
+ constructor(storage: GoogleDriveStorage);
25
25
  private getKeyPair;
26
26
  private generateKeyPair;
27
27
  private verifyCreds;
@@ -1,8 +1,4 @@
1
- interface FileContent {
2
- name: string;
3
- content: any;
4
- comments: string[];
5
- }
1
+ type FileType = 'KEYPAIRs' | 'VCs' | 'SESSIONs' | 'DIDs' | 'RECOMMENDATIONs' | 'MEDIAs';
6
2
  /**
7
3
  * @class GoogleDriveStorage
8
4
  * @description Class to interact with Google Drive API
@@ -20,6 +16,9 @@ interface FileContent {
20
16
  */
21
17
  export declare class GoogleDriveStorage {
22
18
  private accessToken;
19
+ folderCache: any;
20
+ private fileIdsCache;
21
+ private updateFileIdsJson;
23
22
  constructor(accessToken: string);
24
23
  private fetcher;
25
24
  private getFileContent;
@@ -27,12 +26,11 @@ export declare class GoogleDriveStorage {
27
26
  createFolder({ folderName, parentFolderId }: {
28
27
  folderName: string;
29
28
  parentFolderId: string;
30
- }): Promise<{
31
- id: string;
32
- name: string;
33
- mimeType: string;
34
- parents: string[];
35
- }>;
29
+ }): Promise<any>;
30
+ getMediaFolderId(): Promise<any>;
31
+ uploadBinaryFile({ file }: {
32
+ file: File;
33
+ }): Promise<any>;
36
34
  saveFile({ data, folderId }: {
37
35
  data: any;
38
36
  folderId: string;
@@ -44,19 +42,20 @@ export declare class GoogleDriveStorage {
44
42
  */
45
43
  retrieve(id: string): Promise<{
46
44
  data: any;
45
+ id: string;
47
46
  } | null>;
48
47
  /**
49
48
  * Get folder by folderId, if folderId == null you will have them all
50
49
  * @param folderId [Optional]
51
50
  * @returns
52
51
  */
53
- findFolders: (folderId?: string) => Promise<any[]>;
52
+ findFolders(folderId?: string): Promise<any[]>;
54
53
  /**
55
54
  * Get all files content for the specified type ('KEYPAIRs' | 'VCs' | 'SESSIONs' | 'DIDs' | 'RECOMMENDATIONs')
56
55
  * @param type
57
56
  * @returns
58
57
  */
59
- getAllFilesByType(type: 'KEYPAIRs' | 'VCs' | 'SESSIONs' | 'DIDs' | 'RECOMMENDATIONs' | 'MEDIAs'): Promise<FileContent[]>;
58
+ getAllFilesByType(type: FileType): Promise<any[]>;
60
59
  /**
61
60
  * Update the name of a file in Google Drive
62
61
  * @param fileId - The ID of the file to update
@@ -4,7 +4,10 @@ export declare class ResumeVC {
4
4
  issuerDid: string;
5
5
  keyPair: any;
6
6
  }): Promise<any>;
7
- private generateUnsignedCredential;
7
+ generateUnsignedCredential({ formData, issuerDid }: {
8
+ formData: any;
9
+ issuerDid: string;
10
+ }): any;
8
11
  generateKeyPair: (address?: string) => Promise<any>;
9
12
  /**
10
13
  * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
@@ -6,23 +6,97 @@ export declare const inlineResumeContext: {
6
6
  primaryLanguage: string;
7
7
  narrative: string;
8
8
  text: string;
9
+ contact: string;
10
+ email: string;
11
+ phone: string;
12
+ location: string;
13
+ street: string;
14
+ city: string;
15
+ state: string;
16
+ country: string;
17
+ postalCode: string;
18
+ socialLinks: {
19
+ '@id': string;
20
+ '@container': string;
21
+ };
22
+ linkedin: string;
23
+ github: string;
24
+ portfolio: string;
25
+ twitter: string;
26
+ experience: {
27
+ '@id': string;
28
+ '@container': string;
29
+ };
9
30
  employmentHistory: {
10
31
  '@id': string;
11
32
  '@container': string;
12
33
  };
13
34
  company: string;
14
35
  position: string;
36
+ description: string;
37
+ startDate: string;
38
+ endDate: string;
39
+ stillEmployed: string;
15
40
  duration: string;
16
41
  skills: {
17
42
  '@id': string;
18
43
  '@container': string;
19
44
  };
20
- educationAndLearning: string;
45
+ educationAndLearning: {
46
+ '@id': string;
47
+ '@container': string;
48
+ };
21
49
  degree: string;
50
+ fieldOfStudy: string;
22
51
  institution: string;
23
52
  year: string;
24
- issuanceDate: string;
53
+ awards: {
54
+ '@id': string;
55
+ '@container': string;
56
+ };
57
+ title: string;
25
58
  issuer: string;
59
+ date: string;
60
+ publications: {
61
+ '@id': string;
62
+ '@container': string;
63
+ };
64
+ publisher: string;
65
+ url: string;
66
+ certifications: {
67
+ '@id': string;
68
+ '@container': string;
69
+ };
70
+ professionalAffiliations: {
71
+ '@id': string;
72
+ '@container': string;
73
+ };
74
+ organization: string;
75
+ role: string;
76
+ volunteerWork: {
77
+ '@id': string;
78
+ '@container': string;
79
+ };
80
+ hobbiesAndInterests: {
81
+ '@id': string;
82
+ '@container': string;
83
+ };
84
+ languages: {
85
+ '@id': string;
86
+ '@container': string;
87
+ };
88
+ language: string;
89
+ proficiency: string;
90
+ testimonials: {
91
+ '@id': string;
92
+ '@container': string;
93
+ };
94
+ author: string;
95
+ projects: {
96
+ '@id': string;
97
+ '@container': string;
98
+ };
99
+ issuanceDate: string;
26
100
  credentialSubject: string;
27
101
  person: string;
28
102
  Resume: string;
@@ -29,8 +29,8 @@ export declare function generateUnsignedVC({ formData, issuerDid }: {
29
29
  * @returns {RecommendationCredential} The created unsigned Recommendation Credential.
30
30
  * @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
31
31
  */
32
- export declare function generateUnsignedRecommendation({ vc, recommendation, issuerDid, }: {
33
- vc: any;
32
+ export declare function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, }: {
33
+ vcId: string;
34
34
  recommendation: RecommendationFormDataI;
35
35
  issuerDid: string;
36
36
  }): RecommendationCredential;
@@ -12,8 +12,9 @@ export declare const getVCWithRecommendations: ({ vcId, storage }: {
12
12
  }) => Promise<{
13
13
  vc: {
14
14
  data: any;
15
+ id: string;
15
16
  };
16
- recommendations: any[];
17
+ recommendationIds: any;
17
18
  relationsFileId: any;
18
19
  }>;
19
20
  /**
@@ -26,13 +27,14 @@ export declare const getVCWithRecommendations: ({ vcId, storage }: {
26
27
  */
27
28
  export declare function saveToGoogleDrive({ storage, data, type }: SaveToGooglePropsI): Promise<any>;
28
29
  /**
29
- * Upload an image to Google Drive in the Credentials/MEDIAs folder.
30
+ * Upload any type of file to Google Drive in the Credentials/MEDIAs folder.
30
31
  * @param {GoogleDriveStorage} storage - The GoogleDriveStorage instance.
31
- * @param {File} imageFile - The image file to upload.
32
- * @returns {Promise<>} - The uploaded image file object.
32
+ * @param {File} file - The file to upload.
33
+ * @param {string} folderName - The name of the folder where the file will be saved (default is 'MEDIAs').
34
+ * @returns {Promise<{ id: string }>} - The uploaded file object.
33
35
  * @throws Will throw an error if the upload operation fails.
34
36
  */
35
- export declare function uploadImageToGoogleDrive(storage: GoogleDriveStorage, imageFile: File): Promise<{
37
+ export declare function uploadToGoogleDrive(storage: GoogleDriveStorage, file: File, folderName?: string): Promise<{
36
38
  id: string;
37
39
  }>;
38
40
  export declare function generateViewLink(fileId: string): string;
@@ -1,31 +1,121 @@
1
1
  export const inlineResumeContext = {
2
2
  '@context': {
3
3
  '@vocab': 'https://schema.hropenstandards.org/4.4/',
4
+ // Basic details
4
5
  name: 'https://schema.org/name',
5
6
  formattedName: 'https://schema.org/formattedName',
6
7
  primaryLanguage: 'https://schema.org/primaryLanguage',
8
+ // Narrative
7
9
  narrative: 'https://schema.org/narrative',
8
10
  text: 'https://schema.org/text',
11
+ // Contact Information
12
+ contact: 'https://schema.org/ContactPoint',
13
+ email: 'https://schema.org/email',
14
+ phone: 'https://schema.org/telephone',
15
+ location: 'https://schema.org/address',
16
+ street: 'https://schema.org/streetAddress',
17
+ city: 'https://schema.org/addressLocality',
18
+ state: 'https://schema.org/addressRegion',
19
+ country: 'https://schema.org/addressCountry',
20
+ postalCode: 'https://schema.org/postalCode',
21
+ socialLinks: {
22
+ '@id': 'https://schema.org/URL',
23
+ '@container': '@set',
24
+ },
25
+ linkedin: 'https://schema.org/sameAs',
26
+ github: 'https://schema.org/sameAs',
27
+ portfolio: 'https://schema.org/url',
28
+ twitter: 'https://schema.org/sameAs',
29
+ // Experience & Employment History
30
+ experience: {
31
+ '@id': 'https://schema.org/WorkExperience',
32
+ '@container': '@list',
33
+ },
9
34
  employmentHistory: {
10
35
  '@id': 'https://schema.org/employmentHistory',
11
- '@container': '@list', // Specify list container
36
+ '@container': '@list',
12
37
  },
13
- company: 'https://schema.org/company',
38
+ company: 'https://schema.org/worksFor',
14
39
  position: 'https://schema.org/jobTitle',
40
+ description: 'https://schema.org/description',
41
+ startDate: 'https://schema.org/startDate',
42
+ endDate: 'https://schema.org/endDate',
43
+ stillEmployed: 'https://schema.org/Boolean',
15
44
  duration: 'https://schema.org/temporalCoverage',
45
+ // Skills
16
46
  skills: {
17
47
  '@id': 'https://schema.org/skills',
18
- '@container': '@list', // Specify list container
48
+ '@container': '@list',
19
49
  },
20
- educationAndLearning: 'https://schema.org/educationAndLearning',
21
- degree: 'https://schema.org/degree',
22
- institution: 'https://schema.org/institution',
50
+ // Education
51
+ educationAndLearning: {
52
+ '@id': 'https://schema.org/EducationalOccupationalProgram',
53
+ '@container': '@list',
54
+ },
55
+ degree: 'https://schema.org/educationalCredentialAwarded',
56
+ fieldOfStudy: 'https://schema.org/studyField',
57
+ institution: 'https://schema.org/educationalInstitution',
23
58
  year: 'https://schema.org/year',
24
- issuanceDate: 'https://schema.org/issuanceDate',
59
+ // Awards
60
+ awards: {
61
+ '@id': 'https://schema.org/Achievement',
62
+ '@container': '@list',
63
+ },
64
+ title: 'https://schema.org/name',
25
65
  issuer: 'https://schema.org/issuer',
66
+ date: 'https://schema.org/dateReceived',
67
+ // Publications
68
+ publications: {
69
+ '@id': 'https://schema.org/CreativeWork',
70
+ '@container': '@list',
71
+ },
72
+ publisher: 'https://schema.org/publisher',
73
+ url: 'https://schema.org/url',
74
+ // Certifications
75
+ certifications: {
76
+ '@id': 'https://schema.org/EducationalOccupationalCredential',
77
+ '@container': '@list',
78
+ },
79
+ // Professional Affiliations
80
+ professionalAffiliations: {
81
+ '@id': 'https://schema.org/OrganizationRole',
82
+ '@container': '@list',
83
+ },
84
+ organization: 'https://schema.org/memberOf',
85
+ role: 'https://schema.org/jobTitle',
86
+ // Volunteer Work
87
+ volunteerWork: {
88
+ '@id': 'https://schema.org/VolunteerRole',
89
+ '@container': '@list',
90
+ },
91
+ // Hobbies and Interests
92
+ hobbiesAndInterests: {
93
+ '@id': 'https://schema.org/knowsAbout',
94
+ '@container': '@set',
95
+ },
96
+ // Languages
97
+ languages: {
98
+ '@id': 'https://schema.org/knowsLanguage',
99
+ '@container': '@list',
100
+ },
101
+ language: 'https://schema.org/inLanguage',
102
+ proficiency: 'https://schema.org/proficiencyLevel',
103
+ // Testimonials
104
+ testimonials: {
105
+ '@id': 'https://schema.org/Review',
106
+ '@container': '@list',
107
+ },
108
+ author: 'https://schema.org/author',
109
+ // Projects
110
+ projects: {
111
+ '@id': 'https://schema.org/Project',
112
+ '@container': '@list',
113
+ },
114
+ // Issuance Information
115
+ issuanceDate: 'https://schema.org/issuanceDate',
26
116
  credentialSubject: 'https://schema.org/credentialSubject',
27
- person: 'https://schema.org/Person', // Added person
28
- Resume: 'https://schema.hropenstandards.org/4.4#Resume', // Map Resume to an absolute IRI
117
+ person: 'https://schema.org/Person', // Map to Person schema
118
+ Resume: 'https://schema.hropenstandards.org/4.4#Resume',
29
119
  },
30
120
  };
31
121
  let localOBContext = {
@@ -131,10 +131,7 @@ export function generateUnsignedVC({ formData, issuerDid }) {
131
131
  * @returns {RecommendationCredential} The created unsigned Recommendation Credential.
132
132
  * @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
133
133
  */
134
- export function generateUnsignedRecommendation({ vc, recommendation, issuerDid, }) {
135
- console.log('🚀 ~ vc.id:', vc.id);
136
- console.log('🚀 ~ vc:', vc);
137
- console.log('🚀 ~ recommendation:', recommendation);
134
+ export function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, }) {
138
135
  const issuanceDate = new Date().toISOString();
139
136
  if (issuanceDate > recommendation.expirationDate)
140
137
  throw new Error('issuanceDate cannot be after expirationDate');
@@ -150,7 +147,7 @@ export function generateUnsignedRecommendation({ vc, recommendation, issuerDid,
150
147
  portfolio: 'https://schema.org/portfolio',
151
148
  },
152
149
  ],
153
- id: '', // Will be set after hashing VC
150
+ id: `urn:${generateHashedId({ id: vcId })}`,
154
151
  type: ['VerifiableCredential', 'https://schema.org/RecommendationCredential'],
155
152
  issuer: {
156
153
  id: issuerDid,
@@ -170,8 +167,6 @@ export function generateUnsignedRecommendation({ vc, recommendation, issuerDid,
170
167
  })),
171
168
  },
172
169
  };
173
- // Use the VC's hashed ID for the Recommendation's ID
174
- unsignedRecommendation.id = vc.data.id;
175
170
  return unsignedRecommendation;
176
171
  }
177
172
  /**
@@ -1,16 +1,18 @@
1
1
  export const getVCWithRecommendations = async ({ vcId, storage }) => {
2
- const vcFolderId = await storage.getFileParents(vcId);
3
- const files = await storage.findFilesUnderFolder(vcFolderId);
4
- const relationsFile = files.find((f) => f.name === 'RELATIONS');
5
- const relationsContent = await storage.retrieve(relationsFile.id);
6
- const relationsData = relationsContent.data;
7
- const [vcFileId, recommendationIds] = [relationsData.vc_id, relationsData.recommendations];
8
- const vc = await storage.retrieve(vcFileId);
9
- const recommendations = await Promise.all(recommendationIds.map(async (rec) => {
10
- const recFile = await storage.retrieve(rec);
11
- return recFile;
12
- }));
13
- return { vc: vc, recommendations, relationsFileId: relationsFile.id };
2
+ try {
3
+ const vcFolderId = await storage.getFileParents(vcId);
4
+ const files = await storage.findFilesUnderFolder(vcFolderId);
5
+ const relationsFile = files.find((f) => f.name === 'RELATIONS');
6
+ const relationsContent = await storage.retrieve(relationsFile.id);
7
+ const relationsData = relationsContent.data.body ? JSON.parse(relationsContent.data.body) : relationsContent.data;
8
+ const recommendationIds = relationsData.recommendations || [];
9
+ const vc = await storage.retrieve(vcId);
10
+ return { vc: vc, recommendationIds, relationsFileId: relationsFile.id };
11
+ }
12
+ catch (error) {
13
+ console.error('Error getting VC with recommendations:', error);
14
+ throw error;
15
+ }
14
16
  };
15
17
  /**
16
18
  * Save data to Google Drive in the specified folder type.
@@ -53,7 +55,6 @@ export async function saveToGoogleDrive({ storage, data, type }) {
53
55
  }
54
56
  // Save the file in the specific subfolder
55
57
  const file = await storage.saveFile({ data: fileData, folderId: typeFolderId });
56
- console.log('🚀 ~ file:', file);
57
58
  return file;
58
59
  }
59
60
  catch (error) {
@@ -62,17 +63,19 @@ export async function saveToGoogleDrive({ storage, data, type }) {
62
63
  }
63
64
  }
64
65
  /**
65
- * Upload an image to Google Drive in the Credentials/MEDIAs folder.
66
+ * Upload any type of file to Google Drive in the Credentials/MEDIAs folder.
66
67
  * @param {GoogleDriveStorage} storage - The GoogleDriveStorage instance.
67
- * @param {File} imageFile - The image file to upload.
68
- * @returns {Promise<>} - The uploaded image file object.
68
+ * @param {File} file - The file to upload.
69
+ * @param {string} folderName - The name of the folder where the file will be saved (default is 'MEDIAs').
70
+ * @returns {Promise<{ id: string }>} - The uploaded file object.
69
71
  * @throws Will throw an error if the upload operation fails.
70
72
  */
71
- export async function uploadImageToGoogleDrive(storage, imageFile) {
73
+ export async function uploadToGoogleDrive(storage, file, folderName = 'MEDIAs') {
72
74
  try {
73
75
  const rootFolders = await storage.findFolders();
74
76
  let credentialsFolder = rootFolders.find((f) => f.name === 'Credentials');
75
77
  if (!credentialsFolder) {
78
+ console.log('Creating Credentials folder...');
76
79
  credentialsFolder = await storage.createFolder({ folderName: 'Credentials', parentFolderId: 'root' });
77
80
  }
78
81
  const credentialsFolderId = credentialsFolder.id;
@@ -83,17 +86,16 @@ export async function uploadImageToGoogleDrive(storage, imageFile) {
83
86
  }
84
87
  const mediasFolderId = mediasFolder.id;
85
88
  // Prepare the image file data
86
- const imageData = {
87
- fileName: imageFile.name,
88
- mimeType: imageFile.type,
89
- body: imageFile,
89
+ const fileMetaData = {
90
+ fileName: file.name,
91
+ mimeType: file.type,
92
+ body: file,
90
93
  };
91
94
  // SaveFile the image in the "MEDIAs" folder
92
95
  const uploadedImage = await storage.saveFile({
93
- data: imageData,
96
+ data: fileMetaData,
94
97
  folderId: mediasFolderId,
95
98
  });
96
- console.log('🚀 ~ uploadedImage:', uploadedImage);
97
99
  return uploadedImage;
98
100
  }
99
101
  catch (error) {