title: calling remote code from google-apps-script using eval
body: <p>I am facing the problem of sharing a script with a bunch of functions designed to help in manipulation of different copies of the same original google spreadsheet (each user has a personal copy).
  Each spreadsheet copy has its own bounded script copy, so if I improve any function I have to update every single copy of the script.</p>
  
  <p>To overcome this problem, I saw it is possible to call a <strong>library</strong> from your script project, and put all shared functions in that library. Some references I read:</p>
  
  <p><a href="https://stackoverflow.com/questions/20643885/how-can-i-invoke-my-standalone-script-in-my-spreadsheet">How can I invoke my standalone script in my spreadsheet?</a> ; 
  <a href="https://stackoverflow.com/questions/25892753/how-to-use-a-google-apps-script-in-multiple-documents">How to use a google apps script in multiple documents</a> ; 
  <a href="https://stackoverflow.com/questions/27915709/how-to-pass-bounded-script-to-another-user-so-he-can-add-it-to-his-own-spreadshe">How to pass bounded script to another user so he can add it to his own spreadsheets?</a> ; <a href="https://stackoverflow.com/questions/16997274/distribute-google-apps-script-and-push-updates">Distribute Google Apps Script and push updates</a> ; 
  <a href="https://issuetracker.google.com/issues/36755072" rel="nofollow noreferrer">https://issuetracker.google.com/issues/36755072</a></p>
  
  <p>There you can see several problems of using that approach:</p>
  
  <ul>
  <li>To propagate your library updates (dinamically, not having to touch the user sheets again), it has to be included in the sheet-bounded scripts using development mode and giving your users <strong><em>edit</em></strong> access to your library script (if they only have view access, they use a static version of your library). </li>
  <li>You need to redesign your original sheet-bounded code, so the functions are invoqued preceded by the name used to designate your library: libraryname.functionName() -might not be a problem, but I mention it just in case somebody else is getting errors because of this, like I did-. </li>
  <li>From my tests, I have the feeling that code runs much more slowly when using the library, compared to the same code pasted in the sheet-bounded script.</li>
  </ul>
  
  <p>So I wonder if it is possible to include the code in some other way, and I found some comments about <strong>using eval() to include javascript code from a external url</strong>:</p>
  
  <p><a href="https://stackoverflow.com/questions/18646554/importing-external-javascript-to-google-apps-script">importing external javascript to google apps script</a> ; 
  <a href="https://stackoverflow.com/questions/26731438/inject-external-javascript-file-in-google-app-scriptgoogle-docs#answer-26734725">inject external javascript file in google app script(Google Docs)</a> ; 
  <a href="https://ctrlq.org/code/20380-load-external-javascript-with-eval" rel="nofollow noreferrer">https://ctrlq.org/code/20380-load-external-javascript-with-eval</a></p>
  
  <p>Basically, this is how they say to do it:</p>
  
  <pre><code>eval(UrlFetchApp.fetch('http://path.to/external/javascript.js').getContentText());
  </code></pre>
  
  <p><strong>My questions:</strong></p>
  
  <ul>
  <li><p>I do not fully understand how eval() should work in the above examples. Is it intended to be run from a script which runs in the google app server? (so my included file will still be calling SpreadsheetApp. or DriveApp. functions)</p></li>
  <li><p>If the code inside eval() defines a bunch of functions, are they still available after eval() finishes? Can we call them from user driven events, like clicking menu options?  </p></li>
  <li><p>And if we can call them, should be invoqued in a special way? I wasn't able to do it</p></li>
  </ul>
  
  <p>I could just load a new menu (defined in remote.js) using eval(remote.js). 
  BUT the other functions defined in remote.js are not available to menu calls anymore (clicking on menu raises errors like <em>Script function not found: f1</em>).</p>
  
  <ul>
  <li>Should I perhaps load all the functions someway before the menu is defined? I tried it defining function f1() at the begin but it doesn't make a difference with respect to f2(), which is at the end. I also tried 2 separate calls, 1st eval(remote_functions.js), 2nd eval(remote_menuLoader.js), but this didn't make a difference either (so my code below shows just a single eval call, which loads a single remote.js with definitions of both functions and menu which will call them). </li>
  </ul>
  
  <p><strong>My code:</strong></p>
  
  <p><strong>Google spreadsheet bounded-script:</strong></p>
  
  <pre><code>var app = SpreadsheetApp.getActiveSpreadsheet();
  function onOpen() {
    app.addMenu("LOAD remote menu", [
      {name: "eval(remote.js) to load new menu", functionName: "evalRemote"}
    ]);
  }
  function evalRemote() {
    var remotejs_url="https://drive.google.com/uc?authuser=0&amp;id=1wCjewWFTPdH-Luw53zWh_KHX-RhRhFIn&amp;export=view";
    eval(UrlFetchApp.fetch(remotejs_url).getContentText());
    var message=remote_onOpen(app);  
    Browser.msgBox(message);
  }
  </code></pre>
  
  <p><strong>remote.js file:</strong></p>
  
  <pre><code>function f1() {
      Browser.msgBox("you called f1");
  }
  
  function remote_onOpen(app) {
      var menuName="REMOTE-loaded menu";
      app.addMenu(menuName, [
      {name: "FUNCTION 1", functionName: "f1"}
      ,{name: "FUNCTION 2", functionName: "f2"}
      ]);
      return("remote_onOpen(app) function was called;\\n " 
      + "A reference to '" + app.getName() + "' was passed \\n"
      + "in order to create this new menu on it:\\n" 
      + "'" + menuName + "'\\n\\n" 
      + "You should now have 2 new functions available.");
  }
  
  function f2() {
      Browser.msgBox("you called f2");
  }
  </code></pre>