UNPKG

@google/clasp

Version:

Develop Apps Script Projects locally

318 lines (317 loc) 13 kB
import Debug from 'debug'; import fs from 'fs/promises'; import { google } from 'googleapis'; import { fetchWithPages } from './utils.js'; import { assertAuthenticated, assertScriptConfigured, handleApiError } from './utils.js'; import path from 'path'; const debug = Debug('clasp:core'); export class Project { constructor(options) { this.options = options; } get scriptId() { var _a; return (_a = this.options.project) === null || _a === void 0 ? void 0 : _a.scriptId; } get projectId() { var _a; return (_a = this.options.project) === null || _a === void 0 ? void 0 : _a.projectId; } get parentId() { var _a; return (_a = this.options.project) === null || _a === void 0 ? void 0 : _a.parentId; } // TODO - Do we need the assertion or can just use accessor? getProjectId() { assertScriptConfigured(this.options); return this.options.project.projectId; } async createScript(name, parentId) { var _a; debug('Creating script %s', name); assertAuthenticated(this.options); if ((_a = this.options.project) === null || _a === void 0 ? void 0 : _a.scriptId) { debug('Warning: Creating script while id already exists'); } const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { const requestOptions = { requestBody: { parentId, title: name, }, }; debug('Creating project with request %O', requestOptions); const res = await script.projects.create(requestOptions); if (!res.data.scriptId) { throw new Error('Unexpected error, script ID missing from response.'); } debug('Created script %s', res.data.scriptId); const scriptId = res.data.scriptId; this.options.project = { scriptId, parentId }; return scriptId; } catch (error) { handleApiError(error); } } async createWithContainer(name, mimeType) { var _a; debug('Creating container bound script %s (%s)', name, mimeType); assertAuthenticated(this.options); if ((_a = this.options.project) === null || _a === void 0 ? void 0 : _a.scriptId) { debug('Warning: Creating script while id already exists'); } let parentId; const credentials = this.options.credentials; const drive = google.drive({ version: 'v3', auth: credentials }); try { const requestOptions = { requestBody: { mimeType, name, }, }; debug('Creating project with request %O', requestOptions); const res = await drive.files.create(requestOptions); parentId = res.data.id; debug('Created container %s', parentId); if (!parentId) { throw new Error('Unexpected error, container ID missing from response.'); } } catch (error) { handleApiError(error); } const scriptId = await this.createScript(name, parentId); return { parentId, scriptId, }; } async listScripts() { debug('Fetching scripts'); assertAuthenticated(this.options); const credentials = this.options.credentials; const drive = google.drive({ version: 'v3', auth: credentials }); try { return fetchWithPages(async (pageSize, pageToken) => { var _a, _b; const requestOptions = { pageSize, pageToken, fields: 'nextPageToken, files(id, name)', q: 'mimeType="application/vnd.google-apps.script"', }; debug('Fetching scripts from drive with request %O', requestOptions); const res = await drive.files.list(requestOptions); return { results: ((_a = res.data.files) !== null && _a !== void 0 ? _a : []), pageToken: (_b = res.data.nextPageToken) !== null && _b !== void 0 ? _b : undefined, }; }); } catch (error) { handleApiError(error); } } async version(description = '') { var _a; debug('Creating version: %s', description); assertAuthenticated(this.options); assertScriptConfigured(this.options); const credentials = this.options.credentials; const scriptId = this.options.project.scriptId; const script = google.script({ version: 'v1', auth: credentials }); try { const requestOptions = { requestBody: { description: description !== null && description !== void 0 ? description : '', }, scriptId: scriptId, }; debug('Creating version with request %O', requestOptions); const res = await script.projects.versions.create(requestOptions); const versionNumber = (_a = res.data.versionNumber) !== null && _a !== void 0 ? _a : 0; debug('Created new version %d', versionNumber); return versionNumber; } catch (error) { handleApiError(error); } } async listVersions() { debug('Fetching versions'); assertAuthenticated(this.options); assertScriptConfigured(this.options); const scriptId = this.options.project.scriptId; const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { return fetchWithPages(async (pageSize, pageToken) => { var _a, _b; const requestOptions = { scriptId, pageSize, pageToken, }; debug('Fetching versions with request %O', requestOptions); const res = await script.projects.versions.list(requestOptions); return { results: (_a = res.data.versions) !== null && _a !== void 0 ? _a : [], pageToken: (_b = res.data.nextPageToken) !== null && _b !== void 0 ? _b : undefined, }; }); } catch (error) { handleApiError(error); } } async listDeployments() { debug('Listing deployments'); assertAuthenticated(this.options); assertScriptConfigured(this.options); const scriptId = this.options.project.scriptId; const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { return fetchWithPages(async (pageSize, pageToken) => { var _a, _b; const requestOptions = { scriptId, pageSize, pageToken, }; debug('Fetching deployments with request %O', requestOptions); const res = await script.projects.deployments.list(requestOptions); return { results: (_a = res.data.deployments) !== null && _a !== void 0 ? _a : [], pageToken: (_b = res.data.nextPageToken) !== null && _b !== void 0 ? _b : undefined, }; }); } catch (error) { handleApiError(error); } } async deploy(description = '', deploymentId, versionNumber) { debug('Deploying project: %s (%s)', description, versionNumber !== null && versionNumber !== void 0 ? versionNumber : 'HEAD'); assertAuthenticated(this.options); assertScriptConfigured(this.options); if (versionNumber === undefined) { versionNumber = await this.version(description); } const scriptId = this.options.project.scriptId; const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { let deployment; if (!deploymentId) { const requestOptions = { scriptId: scriptId, requestBody: { description: description !== null && description !== void 0 ? description : '', versionNumber: versionNumber, manifestFileName: 'appsscript', }, }; debug('Creating deployment with request %O', requestOptions); const res = await script.projects.deployments.create(requestOptions); deployment = res.data; } else { const requestOptions = { scriptId: scriptId, deploymentId: deploymentId, requestBody: { deploymentConfig: { description: description !== null && description !== void 0 ? description : '', versionNumber: versionNumber, scriptId: scriptId, manifestFileName: 'appsscript', }, }, }; debug('Updating existing deployment with request %O', requestOptions); const res = await script.projects.deployments.update(requestOptions); deployment = res.data; } return deployment; } catch (error) { handleApiError(error); } } async entryPoints(deploymentId) { var _a, _b; assertAuthenticated(this.options); assertScriptConfigured(this.options); const scriptId = this.options.project.scriptId; const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { const res = await script.projects.deployments.get({ scriptId, deploymentId }); const entryPoints = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.entryPoints) !== null && _b !== void 0 ? _b : []; return entryPoints; } catch (error) { handleApiError(error); } } async undeploy(deploymentId) { debug('Deleting deployment %s', deploymentId); assertAuthenticated(this.options); assertScriptConfigured(this.options); const scriptId = this.options.project.scriptId; const credentials = this.options.credentials; const script = google.script({ version: 'v1', auth: credentials }); try { const requestOptions = { scriptId: scriptId, deploymentId, }; debug('Deleting deployment with request %O', requestOptions); await script.projects.deployments.delete(requestOptions); } catch (error) { handleApiError(error); } } async updateSettings() { debug('Updating settings'); assertScriptConfigured(this.options); const srcDir = path.relative(this.options.files.projectRootDir, this.options.files.contentDir); const settings = { scriptId: this.options.project.scriptId, rootDir: srcDir, parentId: this.options.project.parentId, projectId: this.options.project.projectId, scriptExtensions: this.options.files.fileExtensions['SERVER_JS'], htmlExtensions: this.options.files.fileExtensions['HTML'], jsonExtensions: this.options.files.fileExtensions['JSON'], filePushOrder: [], skipSubdirectories: this.options.files.skipSubdirectories, }; await fs.writeFile(this.options.configFilePath, JSON.stringify(settings, null, 2)); } async setProjectId(projectId) { debug('Setting project ID %s in file %s', projectId, this.options.configFilePath); assertScriptConfigured(this.options); this.options.project.projectId = projectId; this.updateSettings(); } exists() { var _a; return ((_a = this.options.project) === null || _a === void 0 ? void 0 : _a.scriptId) !== undefined; } async readManifest() { debug('Reading manifest'); assertScriptConfigured(this.options); const manifestPath = path.join(this.options.files.contentDir, 'appsscript.json'); debug('Manifest path is %s', manifestPath); const content = await fs.readFile(manifestPath); const manifest = JSON.parse(content.toString()); return manifest; } }