@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.
- package/dist/models/CredentialEngine.js +12 -19
- package/dist/models/GoogleDriveStorage.js +203 -159
- package/dist/models/ResumeVC.js +118 -12
- package/dist/types/models/CredentialEngine.d.ts +2 -2
- package/dist/types/models/GoogleDriveStorage.d.ts +12 -13
- package/dist/types/models/ResumeVC.d.ts +4 -1
- package/dist/types/utils/context.d.ts +76 -2
- package/dist/types/utils/credential.d.ts +2 -2
- package/dist/types/utils/google.d.ts +7 -5
- package/dist/utils/context.js +99 -9
- package/dist/utils/credential.js +2 -7
- package/dist/utils/google.js +25 -23
- package/package.json +8 -16
|
@@ -15,6 +15,58 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export class GoogleDriveStorage {
|
|
17
17
|
accessToken;
|
|
18
|
+
folderCache = {};
|
|
19
|
+
fileIdsCache = null;
|
|
20
|
+
async updateFileIdsJson(newFileId) {
|
|
21
|
+
const constructUrl = () => {
|
|
22
|
+
const baseUrl = 'https://www.googleapis.com/drive/v3/files';
|
|
23
|
+
const queryParams = new URLSearchParams({
|
|
24
|
+
spaces: 'appDataFolder',
|
|
25
|
+
q: "name='file_ids.json'",
|
|
26
|
+
fields: 'files(id)',
|
|
27
|
+
});
|
|
28
|
+
return `${baseUrl}?${queryParams.toString()}`;
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
// ✅ Fetch `file_ids.json` ID once per session (cached)
|
|
32
|
+
if (!this.fileIdsCache) {
|
|
33
|
+
const existingFile = await this.fetcher({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
headers: {},
|
|
36
|
+
url: constructUrl(),
|
|
37
|
+
});
|
|
38
|
+
if (existingFile.files.length > 0) {
|
|
39
|
+
this.fileIdsCache = existingFile.files[0].id;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log('No existing file_ids.json found, creating a new one.');
|
|
43
|
+
this.fileIdsCache = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let existingFileIds = [];
|
|
47
|
+
// ✅ Fetch existing file IDs **only if `file_ids.json` exists**
|
|
48
|
+
if (this.fileIdsCache) {
|
|
49
|
+
try {
|
|
50
|
+
const fileContent = await this.fetcher({
|
|
51
|
+
method: 'GET',
|
|
52
|
+
headers: {},
|
|
53
|
+
url: `https://www.googleapis.com/drive/v3/files/${this.fileIdsCache}?alt=media`,
|
|
54
|
+
});
|
|
55
|
+
existingFileIds = fileContent;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.log('Error fetching existing file_ids.json content, creating new list.');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ✅ Append the new file ID to the list
|
|
62
|
+
existingFileIds.push(newFileId);
|
|
63
|
+
console.log('File ID saved to appDataFolder.', this.fileIdsCache);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Error updating file_ids.json:', error.message);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
18
70
|
constructor(accessToken) {
|
|
19
71
|
this.accessToken = accessToken;
|
|
20
72
|
}
|
|
@@ -28,7 +80,6 @@ export class GoogleDriveStorage {
|
|
|
28
80
|
},
|
|
29
81
|
body,
|
|
30
82
|
});
|
|
31
|
-
// Check the Content-Type to ensure it's JSON before parsing
|
|
32
83
|
const contentType = res.headers.get('Content-Type') || '';
|
|
33
84
|
let data;
|
|
34
85
|
if (contentType.includes('application/json')) {
|
|
@@ -39,7 +90,6 @@ export class GoogleDriveStorage {
|
|
|
39
90
|
console.error('Unexpected Response Type:', text);
|
|
40
91
|
throw new Error(`Expected JSON response but got: ${contentType}`);
|
|
41
92
|
}
|
|
42
|
-
// Handle non-200 HTTP responses
|
|
43
93
|
if (!res.ok) {
|
|
44
94
|
console.error('Error Response:', JSON.stringify(data));
|
|
45
95
|
throw new Error(data?.error?.message || 'Unknown error occurred');
|
|
@@ -54,11 +104,7 @@ export class GoogleDriveStorage {
|
|
|
54
104
|
async getFileContent(fileId) {
|
|
55
105
|
const url = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`;
|
|
56
106
|
try {
|
|
57
|
-
const response = await this.fetcher({
|
|
58
|
-
method: 'GET',
|
|
59
|
-
headers: {}, // Add additional headers if required
|
|
60
|
-
url,
|
|
61
|
-
});
|
|
107
|
+
const response = await this.fetcher({ method: 'GET', headers: {}, url });
|
|
62
108
|
return response;
|
|
63
109
|
}
|
|
64
110
|
catch (error) {
|
|
@@ -72,11 +118,7 @@ export class GoogleDriveStorage {
|
|
|
72
118
|
headers: {},
|
|
73
119
|
url: `https://www.googleapis.com/drive/v3/files?q=${encodeURIComponent(query)}&trashed=false&fields=files(id,name,mimeType,parents)`,
|
|
74
120
|
});
|
|
75
|
-
|
|
76
|
-
console.error('No files found:', result);
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
return result.files;
|
|
121
|
+
return result.files || [];
|
|
80
122
|
}
|
|
81
123
|
async createFolder({ folderName, parentFolderId }) {
|
|
82
124
|
if (!parentFolderId) {
|
|
@@ -85,7 +127,7 @@ export class GoogleDriveStorage {
|
|
|
85
127
|
const metadata = {
|
|
86
128
|
name: folderName,
|
|
87
129
|
mimeType: 'application/vnd.google-apps.folder',
|
|
88
|
-
parents: [parentFolderId],
|
|
130
|
+
parents: [parentFolderId],
|
|
89
131
|
};
|
|
90
132
|
const folder = await this.fetcher({
|
|
91
133
|
method: 'POST',
|
|
@@ -94,110 +136,107 @@ export class GoogleDriveStorage {
|
|
|
94
136
|
url: 'https://www.googleapis.com/drive/v3/files',
|
|
95
137
|
});
|
|
96
138
|
console.log(`Folder created: "${folderName}" with ID: ${folder.id}, Parent: ${parentFolderId}`);
|
|
139
|
+
await this.fetcher({
|
|
140
|
+
method: 'POST',
|
|
141
|
+
url: `https://www.googleapis.com/drive/v3/files/${folder.id}/permissions`,
|
|
142
|
+
headers: {},
|
|
143
|
+
body: JSON.stringify({ role: 'reader', type: 'anyone' }),
|
|
144
|
+
});
|
|
97
145
|
return folder;
|
|
98
146
|
}
|
|
147
|
+
async getMediaFolderId() {
|
|
148
|
+
if (this.folderCache['MEDIAs']) {
|
|
149
|
+
return this.folderCache['MEDIAs'];
|
|
150
|
+
}
|
|
151
|
+
const rootFolders = await this.findFolders();
|
|
152
|
+
let credentialsFolder = rootFolders.find((f) => f.name === 'Credentials');
|
|
153
|
+
if (!credentialsFolder) {
|
|
154
|
+
credentialsFolder = await this.createFolder({ folderName: 'Credentials', parentFolderId: 'root' });
|
|
155
|
+
}
|
|
156
|
+
const credentialsFolderId = credentialsFolder.id;
|
|
157
|
+
const subfolders = await this.findFolders(credentialsFolder.id);
|
|
158
|
+
let mediasFolder = subfolders.find((f) => f.name === 'MEDIAs');
|
|
159
|
+
if (!mediasFolder) {
|
|
160
|
+
mediasFolder = await this.createFolder({ folderName: 'MEDIAs', parentFolderId: credentialsFolderId });
|
|
161
|
+
}
|
|
162
|
+
const mediasFolderId = mediasFolder.id;
|
|
163
|
+
this.folderCache['MEDIAs'] = mediasFolderId;
|
|
164
|
+
return mediasFolderId;
|
|
165
|
+
}
|
|
166
|
+
async uploadBinaryFile({ file }) {
|
|
167
|
+
try {
|
|
168
|
+
const accessToken = this.accessToken; // Ensure access token is available
|
|
169
|
+
if (!accessToken) {
|
|
170
|
+
throw new Error('Missing Google OAuth access token.');
|
|
171
|
+
}
|
|
172
|
+
const folderId = await this.getMediaFolderId(); // Ensure folderId is correct
|
|
173
|
+
// ✅ Correct metadata for Google Drive API
|
|
174
|
+
const metadata = {
|
|
175
|
+
name: file.name,
|
|
176
|
+
mimeType: file.type,
|
|
177
|
+
parents: [folderId], // Store in the correct folder
|
|
178
|
+
};
|
|
179
|
+
// ✅ Create FormData for multipart upload
|
|
180
|
+
const formData = new FormData();
|
|
181
|
+
formData.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
|
|
182
|
+
formData.append('file', file);
|
|
183
|
+
// ✅ Correct Google Drive Upload URL
|
|
184
|
+
const url = `https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,parents`;
|
|
185
|
+
const response = await fetch(url, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: {
|
|
188
|
+
Authorization: `Bearer ${accessToken}`, // ✅ Include valid OAuth token
|
|
189
|
+
},
|
|
190
|
+
body: formData,
|
|
191
|
+
});
|
|
192
|
+
const data = await response.json();
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
throw new Error(`Google Drive Upload Error: ${data.error?.message || 'Unknown error'}`);
|
|
195
|
+
}
|
|
196
|
+
console.log('✅ File uploaded successfully:', data);
|
|
197
|
+
return data; // Returns the uploaded file ID and parents
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
console.error('❌ Error uploading file to Google Drive:', error);
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
99
204
|
async saveFile({ data, folderId }) {
|
|
205
|
+
console.log('🚀 ~ GoogleDriveStorage ~ saveFile ~ data:', data);
|
|
100
206
|
try {
|
|
101
207
|
if (!folderId) {
|
|
102
208
|
throw new Error('Folder ID is required to save a file.');
|
|
103
209
|
}
|
|
104
|
-
// Define file metadata, ensure correct folder is assigned
|
|
105
210
|
const fileMetadata = {
|
|
106
|
-
name: data.fileName || 'resume.json',
|
|
107
|
-
parents: [folderId],
|
|
108
|
-
mimeType: 'application/json',
|
|
211
|
+
name: data.fileName || 'resume.json',
|
|
212
|
+
parents: [folderId],
|
|
213
|
+
mimeType: data.mimeType || 'application/json',
|
|
109
214
|
};
|
|
110
|
-
|
|
111
|
-
const folder = await this.fetcher({
|
|
112
|
-
method: 'GET',
|
|
113
|
-
headers: {},
|
|
114
|
-
url: `https://www.googleapis.com/drive/v3/files/${folderId}?fields=trashed`,
|
|
115
|
-
});
|
|
116
|
-
if (folder.trashed) {
|
|
117
|
-
throw new Error('Parent folder is in trash');
|
|
118
|
-
}
|
|
119
|
-
// Prepare the file content as a JSON string
|
|
120
|
-
const fileContent = JSON.stringify(data);
|
|
121
|
-
// Create a Blob from the JSON string
|
|
122
|
-
const fileBlob = new Blob([fileContent], { type: 'application/json' });
|
|
123
|
-
// Create FormData and append the metadata and file content
|
|
215
|
+
const fileBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });
|
|
124
216
|
const formData = new FormData();
|
|
125
217
|
formData.append('metadata', new Blob([JSON.stringify(fileMetadata)], { type: 'application/json' }));
|
|
126
218
|
formData.append('file', fileBlob);
|
|
127
|
-
// Upload file to Google Drive
|
|
128
|
-
console.log('Uploading file...');
|
|
129
219
|
const file = await this.fetcher({
|
|
130
220
|
method: 'POST',
|
|
131
221
|
headers: {},
|
|
132
222
|
body: formData,
|
|
133
223
|
url: `https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,parents`,
|
|
134
224
|
});
|
|
135
|
-
// Set
|
|
225
|
+
// Set public read permissions
|
|
136
226
|
await this.fetcher({
|
|
137
227
|
method: 'POST',
|
|
138
228
|
url: `https://www.googleapis.com/drive/v3/files/${file.id}/permissions`,
|
|
139
|
-
headers: {},
|
|
229
|
+
headers: { 'Content-Type': 'application/json' },
|
|
140
230
|
body: JSON.stringify({
|
|
141
231
|
role: 'reader',
|
|
142
232
|
type: 'anyone',
|
|
143
233
|
}),
|
|
144
234
|
});
|
|
145
|
-
|
|
146
|
-
let existingFileId = null;
|
|
147
|
-
let existingFileIds = [];
|
|
148
|
-
try {
|
|
149
|
-
const existingFileQuery = await this.fetcher({
|
|
150
|
-
method: 'GET',
|
|
151
|
-
headers: {},
|
|
152
|
-
url: `https://www.googleapis.com/drive/v3/files?spaces=appDataFolder&q=name='file_ids.json'&fields=files(id)`,
|
|
153
|
-
});
|
|
154
|
-
if (existingFileQuery.files?.length > 0) {
|
|
155
|
-
existingFileId = existingFileQuery.files[0].id;
|
|
156
|
-
const fileContent = await this.fetcher({
|
|
157
|
-
method: 'GET',
|
|
158
|
-
headers: {},
|
|
159
|
-
url: `https://www.googleapis.com/drive/v3/files/${existingFileId}?alt=media`,
|
|
160
|
-
});
|
|
161
|
-
existingFileIds = JSON.parse(fileContent);
|
|
162
|
-
}
|
|
163
|
-
console.log('existingFileId', existingFileId);
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
console.log('Creating new file_ids.json');
|
|
167
|
-
}
|
|
168
|
-
// Add new file ID
|
|
169
|
-
existingFileIds.push(file.id);
|
|
170
|
-
// Metadata for app data file
|
|
171
|
-
const appDataFileMetadata = {
|
|
172
|
-
name: 'file_ids.json',
|
|
173
|
-
mimeType: 'application/json',
|
|
174
|
-
parents: ['appDataFolder'],
|
|
175
|
-
};
|
|
176
|
-
// Update or create file_ids.json
|
|
177
|
-
const formDataForAppData = new FormData();
|
|
178
|
-
formDataForAppData.append('metadata', new Blob([JSON.stringify(appDataFileMetadata)], { type: 'application/json' }));
|
|
179
|
-
formDataForAppData.append('file', new Blob([JSON.stringify(existingFileIds)], { type: 'application/json' }));
|
|
180
|
-
if (existingFileId) {
|
|
181
|
-
await this.fetcher({
|
|
182
|
-
method: 'PATCH',
|
|
183
|
-
headers: {},
|
|
184
|
-
body: formDataForAppData,
|
|
185
|
-
url: `https://www.googleapis.com/upload/drive/v3/files/${existingFileId}?uploadType=multipart&fields=id`,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
await this.fetcher({
|
|
190
|
-
method: 'POST',
|
|
191
|
-
headers: {},
|
|
192
|
-
body: formDataForAppData,
|
|
193
|
-
url: `https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&spaces=appDataFolder`,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
console.log(file);
|
|
235
|
+
console.log(`File uploaded successfully: ${file.id}`);
|
|
197
236
|
return file;
|
|
198
237
|
}
|
|
199
238
|
catch (error) {
|
|
200
|
-
console.error('Error:', error
|
|
239
|
+
console.error('Error in saveFile:', error);
|
|
201
240
|
throw error;
|
|
202
241
|
}
|
|
203
242
|
}
|
|
@@ -207,10 +246,8 @@ export class GoogleDriveStorage {
|
|
|
207
246
|
* @returns file content
|
|
208
247
|
*/
|
|
209
248
|
async retrieve(id) {
|
|
210
|
-
const metadataUrl = `https://www.googleapis.com/drive/v3/files/${id}?fields=id,name`;
|
|
211
249
|
const dataUrl = `https://www.googleapis.com/drive/v3/files/${id}?alt=media`;
|
|
212
250
|
try {
|
|
213
|
-
// Fetch actual file data
|
|
214
251
|
const dataResponse = await fetch(dataUrl, {
|
|
215
252
|
method: 'GET',
|
|
216
253
|
headers: {
|
|
@@ -223,7 +260,6 @@ export class GoogleDriveStorage {
|
|
|
223
260
|
return null;
|
|
224
261
|
}
|
|
225
262
|
const contentType = dataResponse.headers.get('Content-Type');
|
|
226
|
-
console.log(`File content type: ${contentType}`);
|
|
227
263
|
let fileData;
|
|
228
264
|
if (contentType?.includes('application/json')) {
|
|
229
265
|
fileData = await dataResponse.json();
|
|
@@ -242,7 +278,7 @@ export class GoogleDriveStorage {
|
|
|
242
278
|
else {
|
|
243
279
|
fileData = await dataResponse.arrayBuffer();
|
|
244
280
|
}
|
|
245
|
-
return { data: fileData };
|
|
281
|
+
return { data: fileData, id: id };
|
|
246
282
|
}
|
|
247
283
|
catch (error) {
|
|
248
284
|
console.error(`Error retrieving file with ID ${id}:`, error.message);
|
|
@@ -254,13 +290,18 @@ export class GoogleDriveStorage {
|
|
|
254
290
|
* @param folderId [Optional]
|
|
255
291
|
* @returns
|
|
256
292
|
*/
|
|
257
|
-
|
|
293
|
+
async findFolders(folderId) {
|
|
294
|
+
const cacheKey = folderId || 'root';
|
|
295
|
+
if (this.folderCache[cacheKey]) {
|
|
296
|
+
return this.folderCache[cacheKey];
|
|
297
|
+
}
|
|
258
298
|
const query = folderId
|
|
259
299
|
? `'${folderId}' in parents and mimeType='application/vnd.google-apps.folder'`
|
|
260
300
|
: `'root' in parents and mimeType='application/vnd.google-apps.folder'`;
|
|
261
301
|
const folders = await this.searchFiles(query);
|
|
262
|
-
|
|
263
|
-
|
|
302
|
+
this.folderCache[cacheKey] = folders;
|
|
303
|
+
return folders;
|
|
304
|
+
}
|
|
264
305
|
/**
|
|
265
306
|
* Get all files content for the specified type ('KEYPAIRs' | 'VCs' | 'SESSIONs' | 'DIDs' | 'RECOMMENDATIONs')
|
|
266
307
|
* @param type
|
|
@@ -268,58 +309,56 @@ export class GoogleDriveStorage {
|
|
|
268
309
|
*/
|
|
269
310
|
async getAllFilesByType(type) {
|
|
270
311
|
try {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
312
|
+
if (!this.folderCache['Credentials']) {
|
|
313
|
+
const rootFolders = await this.findFolders();
|
|
314
|
+
this.folderCache['Credentials'] = rootFolders;
|
|
315
|
+
}
|
|
316
|
+
const credentialsFolder = this.folderCache['Credentials'].find((f) => f.name === 'Credentials');
|
|
274
317
|
if (!credentialsFolder) {
|
|
275
318
|
console.error('Credentials folder not found.');
|
|
276
319
|
return [];
|
|
277
320
|
}
|
|
278
|
-
const credentialsFolderId = credentialsFolder.id;
|
|
279
|
-
// Step 2: Handle special case for 'VCs'
|
|
280
321
|
if (type === 'VCs') {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
322
|
+
if (!this.folderCache['VCs']) {
|
|
323
|
+
const vcSubfolder = await this.findFolders(credentialsFolder.id);
|
|
324
|
+
const vcsFolder = vcSubfolder.find((f) => f.name === 'VCs');
|
|
325
|
+
const vcSubFolders = await this.findFolders(vcsFolder.id);
|
|
326
|
+
this.folderCache['VCs'] = vcSubFolders.filter((folder) => folder.name.startsWith('VC-'));
|
|
327
|
+
}
|
|
328
|
+
const vcSubfolders = this.folderCache['VCs'];
|
|
329
|
+
if (!vcSubfolders.length) {
|
|
330
|
+
console.error(`No subfolders found for type: ${type}`);
|
|
286
331
|
return [];
|
|
287
332
|
}
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const files = await this.findFilesUnderFolder(folder.id);
|
|
294
|
-
console.log('🚀 ~ GoogleDriveStorage ~ vcSubfolders.map ~ files:', files);
|
|
295
|
-
return Promise.all(files.map(async (file) => {
|
|
296
|
-
return await this.retrieve(file.id);
|
|
297
|
-
}));
|
|
298
|
-
}));
|
|
299
|
-
console.log('🚀 ~ GoogleDriveStorage ~ getAllFilesByType ~ fileContents:', fileContents);
|
|
300
|
-
return fileContents;
|
|
333
|
+
const allFilesNested = await Promise.all(vcSubfolders.map(async (folder) => await this.findFilesUnderFolder(folder.id)));
|
|
334
|
+
const allVcJsonFiles = allFilesNested.flat().filter((file) => file.mimeType === 'application/json');
|
|
335
|
+
const fileContentsResults = await Promise.allSettled(allVcJsonFiles.map((file) => this.retrieve(file.id)));
|
|
336
|
+
const validFileContents = fileContentsResults.filter((result) => result.status === 'fulfilled').map((result) => result.value);
|
|
337
|
+
return validFileContents.filter((file) => file.data.fileName !== 'RELATIONS');
|
|
301
338
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
339
|
+
if (!this.folderCache[type]) {
|
|
340
|
+
const subfolders = await this.findFolders(credentialsFolder.id);
|
|
341
|
+
const targetFolder = subfolders.find((f) => f.name === type);
|
|
342
|
+
this.folderCache[type] = targetFolder ? targetFolder.id : null;
|
|
343
|
+
}
|
|
344
|
+
const targetFolderId = this.folderCache[type];
|
|
345
|
+
if (!targetFolderId) {
|
|
306
346
|
console.error(`Folder for type ${type} not found.`);
|
|
307
347
|
return [];
|
|
308
348
|
}
|
|
309
349
|
const filesResponse = await this.fetcher({
|
|
310
350
|
method: 'GET',
|
|
311
351
|
headers: {},
|
|
312
|
-
url: `https://www.googleapis.com/drive/v3/files?q='${
|
|
352
|
+
url: `https://www.googleapis.com/drive/v3/files?q='${targetFolderId}' in parents and trashed=false&fields=files(id,name,mimeType)`,
|
|
313
353
|
});
|
|
314
|
-
const files = filesResponse.files;
|
|
315
|
-
const fileContents = await Promise.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return fileContents;
|
|
354
|
+
const files = filesResponse.files || [];
|
|
355
|
+
const fileContents = await Promise.allSettled(files.map((file) => this.retrieve(file.id)));
|
|
356
|
+
console.log('🚀 ~ GoogleDriveStorage ~ getAllFilesByType ~ fileContents:', fileContents);
|
|
357
|
+
return fileContents.filter((res) => res.status === 'fulfilled').map((res) => res.value);
|
|
319
358
|
}
|
|
320
359
|
catch (error) {
|
|
321
360
|
console.error(`Error getting files of type ${type}:`, error);
|
|
322
|
-
return [];
|
|
361
|
+
return [];
|
|
323
362
|
}
|
|
324
363
|
}
|
|
325
364
|
/**
|
|
@@ -330,9 +369,7 @@ export class GoogleDriveStorage {
|
|
|
330
369
|
*/
|
|
331
370
|
async updateFileName(fileId, newFileName) {
|
|
332
371
|
try {
|
|
333
|
-
const metadata = {
|
|
334
|
-
name: newFileName, // New name for the file
|
|
335
|
-
};
|
|
372
|
+
const metadata = { name: newFileName };
|
|
336
373
|
const updatedFile = await this.fetcher({
|
|
337
374
|
method: 'PATCH',
|
|
338
375
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -348,7 +385,6 @@ export class GoogleDriveStorage {
|
|
|
348
385
|
}
|
|
349
386
|
}
|
|
350
387
|
async findFileByName(name) {
|
|
351
|
-
// find the file named under Credentials folder
|
|
352
388
|
const rootFolders = await this.findFolders();
|
|
353
389
|
const credentialsFolderId = rootFolders.find((f) => f.name === 'Credentials')?.id;
|
|
354
390
|
if (!credentialsFolderId)
|
|
@@ -364,7 +400,6 @@ export class GoogleDriveStorage {
|
|
|
364
400
|
console.log('No files found in the folder.');
|
|
365
401
|
return [];
|
|
366
402
|
}
|
|
367
|
-
// Fetch content for each file
|
|
368
403
|
const filesWithContent = await Promise.all(files.map(async (file) => {
|
|
369
404
|
try {
|
|
370
405
|
const content = await this.getFileContent(file.id);
|
|
@@ -372,7 +407,7 @@ export class GoogleDriveStorage {
|
|
|
372
407
|
}
|
|
373
408
|
catch (error) {
|
|
374
409
|
console.error(`Error fetching content for file "${file.name}" (ID: ${file.id}):`, error);
|
|
375
|
-
return { ...file, content: null };
|
|
410
|
+
return { ...file, content: null };
|
|
376
411
|
}
|
|
377
412
|
}));
|
|
378
413
|
return filesWithContent;
|
|
@@ -382,12 +417,8 @@ export class GoogleDriveStorage {
|
|
|
382
417
|
const updateUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`;
|
|
383
418
|
const updatedFile = await this.fetcher({
|
|
384
419
|
method: 'PATCH',
|
|
385
|
-
headers: {
|
|
386
|
-
|
|
387
|
-
},
|
|
388
|
-
body: JSON.stringify({
|
|
389
|
-
name: data.fileName,
|
|
390
|
-
}),
|
|
420
|
+
headers: { 'Content-Type': 'application/json' },
|
|
421
|
+
body: JSON.stringify({ name: data.fileName }),
|
|
391
422
|
url: updateUrl,
|
|
392
423
|
});
|
|
393
424
|
console.log('✅ File renamed successfully:', updatedFile);
|
|
@@ -398,44 +429,50 @@ export class GoogleDriveStorage {
|
|
|
398
429
|
}
|
|
399
430
|
}
|
|
400
431
|
async getFileParents(fileId) {
|
|
401
|
-
console.log('🚀 ~ GoogleDriveStorage ~ getFileParents ~ fileId', fileId);
|
|
402
432
|
const file = await this.fetcher({
|
|
403
433
|
method: 'GET',
|
|
404
434
|
headers: {},
|
|
405
435
|
url: `https://www.googleapis.com/drive/v3/files/${fileId}?fields=parents`,
|
|
406
436
|
});
|
|
437
|
+
console.log('FILE: ', file);
|
|
407
438
|
return file.parents;
|
|
408
439
|
}
|
|
409
440
|
async updateRelationsFile({ relationsFileId, recommendationFileId }) {
|
|
410
441
|
const relationsFileContent = await this.retrieve(relationsFileId);
|
|
411
|
-
const relationsData = relationsFileContent.data;
|
|
442
|
+
const relationsData = relationsFileContent.data.body ? JSON.parse(relationsFileContent.data.body) : relationsFileContent.data;
|
|
412
443
|
relationsData.recommendations.push(recommendationFileId);
|
|
413
444
|
const updatedContent = JSON.stringify(relationsData);
|
|
414
445
|
const updateResponse = await this.fetcher({
|
|
415
446
|
method: 'PATCH',
|
|
416
|
-
headers: {
|
|
417
|
-
'Content-Type': 'application/json',
|
|
418
|
-
},
|
|
447
|
+
headers: { 'Content-Type': 'application/json' },
|
|
419
448
|
body: updatedContent,
|
|
420
449
|
url: `https://www.googleapis.com/upload/drive/v3/files/${relationsFileId}?uploadType=media`,
|
|
421
450
|
});
|
|
422
|
-
|
|
451
|
+
this.updateFileIdsJson(relationsFileId);
|
|
423
452
|
return updateResponse;
|
|
424
453
|
}
|
|
425
454
|
async createRelationsFile({ vcFolderId }) {
|
|
426
455
|
const files = await this.findFilesUnderFolder(vcFolderId);
|
|
427
456
|
const vcFile = files.find((file) => file.name === 'VC');
|
|
457
|
+
const vcContent = await this.getFileContent(vcFile.id);
|
|
458
|
+
console.log('🚀 ~ GoogleDriveStorage ~ createRelationsFile ~ vcContent:', vcContent);
|
|
459
|
+
const subject = JSON.parse(vcContent.body).credentialSubject;
|
|
460
|
+
console.log('🚀 ~ GoogleDriveStorage ~ createRelationsFile ~ subject:', subject);
|
|
428
461
|
const relationsFile = await this.saveFile({
|
|
429
462
|
data: {
|
|
430
463
|
fileName: 'RELATIONS',
|
|
431
464
|
mimeType: 'application/json',
|
|
432
465
|
body: JSON.stringify({
|
|
433
|
-
|
|
466
|
+
vc: {
|
|
467
|
+
fileId: vcContent.id,
|
|
468
|
+
subject,
|
|
469
|
+
},
|
|
434
470
|
recommendations: [],
|
|
435
471
|
}),
|
|
436
472
|
},
|
|
437
473
|
folderId: vcFolderId,
|
|
438
474
|
});
|
|
475
|
+
await this.updateFileIdsJson(relationsFile.id);
|
|
439
476
|
return relationsFile;
|
|
440
477
|
}
|
|
441
478
|
/**
|
|
@@ -459,25 +496,19 @@ export class GoogleDriveStorage {
|
|
|
459
496
|
}
|
|
460
497
|
}
|
|
461
498
|
async update(fileId, data) {
|
|
462
|
-
console.log('🚀 ~ GoogleDriveStorage ~ update ~ data:', data);
|
|
463
|
-
console.log('🚀 ~ GoogleDriveStorage ~ update ~ fileId:', fileId);
|
|
464
|
-
// ✅ Ensure JSON file type
|
|
465
499
|
const metadata = {
|
|
466
500
|
name: data.fileName || 'resume.json',
|
|
467
501
|
mimeType: 'application/json',
|
|
468
502
|
};
|
|
469
503
|
const uploadUrl = `https://www.googleapis.com/upload/drive/v3/files/${fileId}?uploadType=multipart`;
|
|
470
|
-
// ✅ Create multipart request to update Google Drive JSON file
|
|
471
504
|
const formData = new FormData();
|
|
472
505
|
formData.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
|
|
473
|
-
formData.append('file', new Blob([JSON.stringify(data.body)], { type: 'application/json' })
|
|
474
|
-
);
|
|
475
|
-
console.log('🚀 ~ GoogleDriveStorage ~ update ~ FormData:', formData);
|
|
506
|
+
formData.append('file', new Blob([JSON.stringify(data.body)], { type: 'application/json' }));
|
|
476
507
|
try {
|
|
477
508
|
const response = await this.fetcher({
|
|
478
509
|
method: 'PATCH',
|
|
479
|
-
headers: {},
|
|
480
|
-
body: formData,
|
|
510
|
+
headers: {},
|
|
511
|
+
body: formData,
|
|
481
512
|
url: `${uploadUrl}&fields=id,name,mimeType`,
|
|
482
513
|
});
|
|
483
514
|
console.log('✅ File updated successfully:', response);
|
|
@@ -490,12 +521,22 @@ export class GoogleDriveStorage {
|
|
|
490
521
|
}
|
|
491
522
|
async getFileIdsFromAppDataFolder() {
|
|
492
523
|
try {
|
|
524
|
+
const constructUrl = () => {
|
|
525
|
+
const baseUrl = 'https://www.googleapis.com/drive/v3/files';
|
|
526
|
+
const queryParams = new URLSearchParams({
|
|
527
|
+
spaces: 'appDataFolder',
|
|
528
|
+
q: "name='file_ids.json'",
|
|
529
|
+
fields: 'files(id)',
|
|
530
|
+
});
|
|
531
|
+
return `${baseUrl}?${queryParams.toString()}`;
|
|
532
|
+
};
|
|
493
533
|
// Step 1: Search for the file_ids.json file in the appDataFolder
|
|
494
534
|
const response = await this.fetcher({
|
|
495
535
|
method: 'GET',
|
|
496
536
|
headers: {},
|
|
497
|
-
url:
|
|
537
|
+
url: constructUrl(),
|
|
498
538
|
});
|
|
539
|
+
console.log(': GoogleDriveStorage getFileIdsFromAppDataFolder response', response);
|
|
499
540
|
// Step 2: Check if the file exists
|
|
500
541
|
if (!response.files || response.files.length === 0) {
|
|
501
542
|
console.log('No file_ids.json found in appDataFolder.');
|
|
@@ -503,14 +544,17 @@ export class GoogleDriveStorage {
|
|
|
503
544
|
}
|
|
504
545
|
// Step 3: Get the file ID of file_ids.json
|
|
505
546
|
const fileId = response.files[0].id;
|
|
547
|
+
console.log(': GoogleDriveStorage getFileIdsFromAppDataFolder fileId', fileId);
|
|
506
548
|
// Step 4: Fetch the content of file_ids.json
|
|
507
549
|
const fileContent = await this.fetcher({
|
|
508
550
|
method: 'GET',
|
|
509
551
|
headers: {},
|
|
510
552
|
url: `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`,
|
|
511
553
|
});
|
|
554
|
+
console.log(': GoogleDriveStorage getFileIdsFromAppDataFolder fileContent', fileContent);
|
|
512
555
|
// Step 5: Parse the file content (array of file IDs)
|
|
513
|
-
const fileIds =
|
|
556
|
+
const fileIds = fileContent;
|
|
557
|
+
console.log(': GoogleDriveStorage getFileIdsFromAppDataFolder fileIds', fileIds);
|
|
514
558
|
return fileIds;
|
|
515
559
|
}
|
|
516
560
|
catch (error) {
|