UNPKG

@google/clasp

Version:

Develop Apps Script Projects locally

264 lines (263 loc) 12.6 kB
"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); /** * Authentication with Google's APIs. */ var http = require("http"); var url = require("url"); var google_auth_library_1 = require("google-auth-library"); var googleapis_1 = require("googleapis"); var utils_1 = require("./utils"); var open = require("opn"); var readline = require("readline"); var fs = require("fs"); // API settings // @see https://developers.google.com/oauthplayground/ var REDIRECT_URI_OOB = 'urn:ietf:wg:oauth:2.0:oob'; var oauth2ClientAuthUrlOpts = { access_type: 'offline', scope: [ 'https://www.googleapis.com/auth/script.deployments', 'https://www.googleapis.com/auth/script.projects', 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/script.webapp.deploy', 'https://www.googleapis.com/auth/cloud-platform.read-only', 'https://www.googleapis.com/auth/logging.read', ], }; var oauth2ClientSettings = { clientId: '1072944905499-vm2v2i5dvn0a0d2o4ca36i1vge8cvbn0.apps.googleusercontent.com', clientSecret: 'v6V3fKV_zWU7iw1DrpO1rknX', redirectUri: 'http://localhost', }; var oauth2Client = new google_auth_library_1.OAuth2Client(oauth2ClientSettings); // Google API clients exports.script = googleapis_1.google.script({ version: 'v1', auth: oauth2Client }); exports.logger = googleapis_1.google.logging({ version: 'v2', auth: oauth2Client }); exports.drive = googleapis_1.google.drive({ version: 'v3', auth: oauth2Client }); exports.discovery = googleapis_1.google.discovery({ version: 'v1' }); /** * Requests authorization to manage Apps Script projects. * @param {boolean} useLocalhost True if a local HTTP server should be run * to handle the auth response. False if manual entry used. * @param {string} creds location of credentials file. */ function authorize(useLocalhost, creds) { return __awaiter(this, void 0, void 0, function () { var ownCreds, credentials, token, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: ownCreds = false; try { credentials = JSON.parse(fs.readFileSync(creds, 'utf8')); if (credentials && credentials.installed && credentials.installed.client_id && credentials.installed.client_secret) { oauth2ClientSettings.clientId = credentials.installed.client_id; oauth2ClientSettings.clientSecret = credentials.installed.client_secret; ownCreds = true; console.log(utils_1.LOG.CREDENTIALS_FOUND); } else { utils_1.logError(null, utils_1.ERROR.BAD_CREDENTIALS_FILE); } } catch (err) { if (err.code === 'ENOENT') { utils_1.logError(null, utils_1.ERROR.CREDENTIALS_DNE); } console.log(utils_1.LOG.DEFAULT_CREDENTIALS); } _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); return [4 /*yield*/, (useLocalhost ? authorizeWithLocalhost() : authorizeWithoutLocalhost())]; case 2: token = _a.sent(); return [4 /*yield*/, (ownCreds ? utils_1.DOTFILE.RC_LOCAL.write(token) : utils_1.DOTFILE.RC.write(token))]; case 3: _a.sent(); console.log(utils_1.LOG.AUTH_SUCCESSFUL); process.exit(0); // gracefully exit after successful login return [3 /*break*/, 5]; case 4: err_1 = _a.sent(); utils_1.logError(null, utils_1.ERROR.ACCESS_TOKEN + err_1); return [3 /*break*/, 5]; case 5: return [2 /*return*/]; } }); }); } /** * Loads the Apps Script API credentials for the CLI. * Required before every API call. */ function loadAPICredentials() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, utils_1.DOTFILE.RC_LOCAL.read().then(function (rc) { oauth2Client.setCredentials(rc); }).catch(function (err) { return utils_1.DOTFILE.RC.read().then(function (rc) { oauth2Client.setCredentials(rc); }).catch(function (err) { utils_1.logError(err, 'Could not read API credentials. Error:'); }); })]; }); }); } exports.loadAPICredentials = loadAPICredentials; /** * Requests authorization to manage Apps Script projects. Spins up * a temporary HTTP server to handle the auth redirect. */ function authorizeWithLocalhost() { return __awaiter(this, void 0, void 0, function () { var server, port, client, authCode; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, new Promise(function (resolve, _) { var s = http.createServer(); s.listen(0, function () { return resolve(s); }); })]; case 1: server = _a.sent(); port = server.address().port; client = new google_auth_library_1.OAuth2Client(__assign({}, oauth2ClientSettings, { redirectUri: "http://localhost:" + port })); return [4 /*yield*/, new Promise(function (res, rej) { server.on('request', function (req, resp) { var urlParts = url.parse(req.url || '', true); if (urlParts.query.code) { res(urlParts.query.code); } else { rej(urlParts.query.error); } resp.end(utils_1.LOG.AUTH_PAGE_SUCCESSFUL); }); var authUrl = client.generateAuthUrl(oauth2ClientAuthUrlOpts); console.log(utils_1.LOG.AUTHORIZE(authUrl)); open(authUrl); })]; case 2: authCode = _a.sent(); server.close(); return [4 /*yield*/, client.getToken(authCode)]; case 3: return [2 /*return*/, (_a.sent()).tokens]; } }); }); } /** * Requests authorization to manage Apps Script projects. Requires the * user to manually copy/paste the authorization code. No HTTP server is * used. */ function authorizeWithoutLocalhost() { return __awaiter(this, void 0, void 0, function () { var client, authUrl, authCode; return __generator(this, function (_a) { switch (_a.label) { case 0: client = new google_auth_library_1.OAuth2Client(__assign({}, oauth2ClientSettings, { redirectUri: REDIRECT_URI_OOB })); authUrl = client.generateAuthUrl(oauth2ClientAuthUrlOpts); console.log(utils_1.LOG.AUTHORIZE(authUrl)); return [4 /*yield*/, new Promise(function (res, rej) { var rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question(utils_1.LOG.AUTH_CODE, function (code) { if (code && code.length) { res(code); } else { rej('No authorization code entered.'); } rl.close(); }); })]; case 1: authCode = _a.sent(); return [4 /*yield*/, client.getToken(authCode)]; case 2: return [2 /*return*/, (_a.sent()).tokens]; } }); }); } /** * Logs the user in. Saves the client credentials to an rc file. * @param {object} options the localhost and creds options from commander. * @param {boolean} options.localhost authorize without http server. * @param {string} options.creds location of credentials file. */ function login(options) { var _this = this; utils_1.DOTFILE.RC.read().then(function (rc) { console.warn(utils_1.ERROR.LOGGED_IN); }).catch(function (err) { return __awaiter(_this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { utils_1.DOTFILE.RC_LOCAL.read().then(function (rc) { console.warn(utils_1.ERROR.LOGGED_IN); }).catch(function (err) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, utils_1.checkIfOnline()]; case 1: _a.sent(); authorize(options.localhost, options.creds); return [2 /*return*/]; } }); }); }); return [2 /*return*/]; }); }); }); } exports.login = login;