Overwrite file. Overwrite Apps Script file.
This is not a question to create a new Apps Script file. That won't help me. I need to update an existing Apps Script file. This question is similar to creating a new file, but it's not the same issue. The syntax for an update, and the requirements for an update may be different enough from creating a new file, that I can't get a solution from the answer about creating a new file. I've looked at an answer for creating a new file, and that has not answered my question.
I have tried using the Advanced Drive Service to update an existing Apps Script file with another Apps Script file.
function updateMyScript() {
var targetFileID = 'File ID';
var dataSource = {
"files": [
{
"id":"739a57da-f77c-4e1a-96df-7d86ef227d62",
"name":"Code",
"type":"server_js",
"source":"function doGet() {\n return HtmlService.createHtmlOutputFromFile(\u0027index\u0027);\n}\n"
},
{
"id":"2c7e8b5a-dbc5-4cd2-80e9-77b6291b3167",
"name":"index",
"type":"html",
"source":"\u003chtml\u003e\n \u003cbody\u003e\n New message!!\n \u003c/body\u003e\n\u003c/html\u003e"
}
]
};
var filesResource = Drive.Files.get(targetFileID);
var blob = Utilities.newBlob(JSON.stringify(dataSource), "application/vnd.google-apps.script+json");
var whatRezult = Drive.Files.update(filesResource, targetFileID, blob, {"convert":"true"});
Logger.log('whatRezult: ' + whatRezult);
};
The id
properties in the dataSource
object are id's of each specific .gs
or html
file inside of the project. I got those id's by downloading the "target" Apps Script file to JSON, then opening up the JSON file and copying out the file id's. So, I know that those are correct. I'd like a way to retrieve those individual file ID's from the project with code. The post about creating a new apps script file, does not explain how to get the "sub" ID's from the project file. The project file ID is not the same as each file ID inside of the project. The name
and type
properties are obvious. And there are only two types of files which, from the example, have types of server_js
and "html". It looks like the source
for the internal files to the Apps Script project file can be a string literal. So, you can just type in whatever you want the replacement content to be.
The target ID
is self explanatory.
If there is a way to do this with either the Advanced Drive Service or UrlFetchApp.fetch()
that will answer my question. I only want to use Apps Script. So, I'm not looking for a solution written in some other language, or that is run from outside of Apps Script.
With the above code, I'm getting an error from the next to last line:
Drive.Files.update(filesResource, targetFileID, blob, {"convert":"true"});
The error is:
The app does not have the required scope to update Apps Scripts.
So, obviously, it's looking for a scope setting to be indicated somewhere. I'm guessing that it would go into the the fourth parameter for the options.
The new Apps Script API now allows for an Apps Script project to be updated. The project that is updated can be bound to a document. (Sheet, Form, Doc) This code uses the REST API, and makes a PUT request from Apps Script code using
UrlFetchApp.fetch(url,options)
This code is being run from an Apps Script file to update another Apps Script file.The Apps Script API must be enabled for the Apps Script file running the code. The Apps Script API is enabled in the Google Cloud console. From the code editor, choose "Resources" and "Cloud Platform project" Search for Apps Script API and enable it.
You must use the correct scopes in order for the code to run without an authorization error.
The scopes can be set in the appsscript.json file. To view the appsscript.json file, you must first click the View menu, and choose the "Show manifest" menu item.
The first time that the Apps Script API is used, the PUT request may not work, and will return an error with a link to the Google Cloud console. That's why it's important to view the return response
Logger.log('typeof response: ' + typeof response)
from theresponse = UrlFetchApp.fetch(url,options);
statement.You need to ask for the special Drive-AppsScript scope:
Since you cannot tell Apps Script to ask this scope for you (it determines its own scopes automatically by analyzing your code). You need to do the oAuth dance yourself (by using Eric's lib for example). But then since you also cannot set this token you retrieved yourself for the script to use in its built-in or advanced service calls (not that I know of anyway), you'll have to do the UrlFetch call manually too, and pass your "custom" token in the header (like shown in the "create new script" question.
The UrlFetch call to
update
is very similar to theinsert
one. Just change the method toPUT
and add the apps script project id in the path.I've created a GitHub repository of a project that will update one Apps Script file (the target) from a source Apps Script file. It's totally free to copy and use.
GitHub Repository - apps-script-update
See the Read Me file in the GitHub repository for instructions
The code at GitHub is using the newer Apps Script API, which is different from the original answer.