I'm trying to make a method that copies a folder tree in google drive using the drive API. I'm coming across some issues with asynchronous methods not working, if anybody can spot the flaw in the code, or point me towards some useful articles it would be very helpful.
I need the line that is causing the error to be awaited because the next recursive call requires the ID of the folder that is being required with the 'copy' function. It returns a promise, so it seems like it should be working.
In general, I am not very experienced with asynchronous programming so I could be overlooking something simple, but I have been stuck on this for a while now. Thanks!!
code:
function authorize() {
const auth = new google.auth.GoogleAuth({
keyFile: 'creds.json',
scopes: SCOPES
})
return google.drive({version: 'v3', auth})
}
function search(driveService, parentFolder) {
return new Promise((resolve, reject) => {
driveService.files.list({
pageSize: 20,
q: `'${parentFolder}' in parents and trashed = false`,
fields: 'files(id, name, mimeType)'
}).then(({data}) => resolve(data))
.catch(err => reject(err))
})
}
function createRoot(driveService, CLIENT_NAME, NEW_FOLDER_LOCATION) {
let fileMetadata = {
'name': CLIENT_NAME,
'mimeType': 'application/vnd.google-apps.folder',
'parents': [NEW_FOLDER_LOCATION]
}
return new Promise((resolve, reject) => {
const file = driveService.files.create({
resource: fileMetadata,
fields: 'id'
}, function(err, file) {
if(err) {
reject(err);
} else {
resolve(file.data.id);
}
})
})
}
function copy(driveService, copyContentId, contentNewName, root){
let fileMetadata = {
'name': contentNewName,
'parents': [root]
};
return new Promise((resolve, reject) => {
const file = driveService.files.copy({
'fileId': copyContentId,
'resource': fileMetadata
}, function(err, file) {
if(err) {
reject(err);
} else {
resolve(file.data.id);
}
})
})
}
async function recursive(driveService, startSearch, rootFolder) {
let children = await search(driveService, startSearch);
if(children.files.length > 0) {
children.files.forEach((element) => {
if(element.mimeType === 'application/vnd.google-apps.folder') {
let name = element.name.replace('Last, First', CLIENT_NAME);
let folderID = await copy(driveService, element.id, name, rootFolder);
recursive(driveService, element.id, folderID);
} else {
let name = element.name.replace('Last, First', CLIENT_NAME);
let fileID = await copy(driveService, element.id, name, rootFolder);
}
})
} else {
console.log('end of branch');
}
}
async function run() {
try{
const google = await authorize();
const root = await createRoot(google, CLIENT_NAME, NEW_FOLDER_LOCATION);
await recursive(google, START_SEARCH, root);
} catch(err) {
console.log('error', err);
}
}
run();
output:
app.js:75
let folderID = await copy(driveService, element.id, name, rootFolder);
^^^^^
SyntaxError: await is only valid in async functions and the top level bodies of modules
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1031:15)
at Module._compile (node:internal/modules/cjs/loader:1065:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47