One can use external libraries like Moment.js via eval
& UrlFetchApp
in the "standard" Apps Script projects because the variables exports
and module
are not defined, so the library installs itself into the global context
Indeed, we can verify the result by inspecting this
in the Apps Script Editor:
Code.gs
var momentURL = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.4/moment.min.js";
function main() {
eval(UrlFetchApp.fetch(momentURL).getContentText());
Logger.log(this["moment"]);
}
Executing main
yields
function e() {
return Qe.apply(null, arguments);
}
For transpiled TypeScript, because exports
and module
are globally defined, the initialization of eval
'd libraries assumes that it has a more recent runtime / package management system than that provided by Google Apps Script.
Code.ts
import * as moment from "moment";
const momentURL = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.4/moment.min.js";
function main() {
eval(UrlFetchApp.fetch(momentURL).getContentText());
Logger.log(`this['moment']: ${this["moment"]}`);
Logger.log(`this.module: ${this.module}`);
for (let key in this.module)
Logger.log(`this.module[${key}]: ${this.module[key]}`);
}
$ clasp push
-->
Code.gs
// Compiled using ts2gas 1.6.0 (TypeScript 3.2.2)
var exports = exports || {};
var module = module || { exports: exports };
//import * as moment from "moment";
var momentURL = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.4/moment.min.js";
function main() {
eval(UrlFetchApp.fetch(momentURL).getContentText());
Logger.log("this['moment']: " + this["moment"]);
Logger.log("this.module: " + this.module);
for (var key in this.module)
Logger.log("this.module[" + key + "]: " + this.module[key]);
}
Which yields a log of
this['moment']: undefined
this.module: [object Object]
this.module[exports]:
function e() {
return Qe.apply(null, arguments);
}
Solutions
So the eval
is successful, but binds to module.exports
and not moment
. You can (in the transpiled Apps Script) refer to module.exports
instead of moment
:
Logger.log(module.exports().format("YYYY")); // 2019
Probably you will need to use a different method than clasp, since it seems ts2gas
(as of v1.6.0) does not support import / export transpiling. This observed behavior wherein module.exports
in transpiled TS is the eval'd import seems heinously fragile, and will certainly not be easy to work around when writing the actual TypeScript.
Related: