@google/dscc-gen
Version:
Create component & connector projects with sane defaults.
157 lines (156 loc) • 7.26 kB
JavaScript
;
/**
* @license
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = require("chalk");
const path = require("path");
const terminal_link_1 = require("terminal-link");
const files = require("../files");
const index_1 = require("../index");
const util = require("../util");
const appsscript = require("./appsscript");
const validation = require("./validation");
const clear = require('clear');
const green = chalk_1.default.bold.rgb(15, 157, 88);
const blue = chalk_1.default.bold.rgb(66, 133, 244);
const yellow = chalk_1.default.bold.rgb(244, 160, 0);
const red = chalk_1.default.bold.rgb(219, 68, 55);
const getTemplates = (answers) => {
return [
{ match: /{{MANIFEST_NAME}}/, replace: answers.projectName },
{ match: /{{MANIFEST_LOGO_URL}}/, replace: answers.manifestLogoUrl },
{ match: /{{MANIFEST_COMPANY}}/, replace: answers.manifestCompany },
{ match: /{{MANIFEST_COMPANY_URL}}/, replace: answers.manifestCompanyUrl },
{ match: /{{MANIFEST_ADDON_URL}}/, replace: answers.manifestAddonUrl },
{ match: /{{MANIFEST_SUPPORT_URL}}/, replace: answers.manifestSupportUrl },
{ match: /{{MANIFEST_DESCRIPTION}}/, replace: answers.manifestDescription },
{
match: /{{MANIFEST_SOURCES}}/,
replace: `[${answers
.manifestSources.split(',')
.map((a) => `"${a}"`)
.join(',')}]`,
},
];
};
const ensureAuthenticated = async (execOptions) => {
const authenticated = util.spinnify('Ensuring clasp is authenticated...', async () => {
return validation.claspAuthenticated();
});
if (!authenticated) {
const infoText = yellow('Clasp must be globally authenticated for dscc-gen.');
const claspLogin = green('npx @google/clasp login');
console.log(`${infoText}\nrunning ${claspLogin} ...\n`);
await util.exec('npx @google/clasp login', execOptions, true);
}
};
const installDependencies = async (projectPath, answers) => {
return util.spinnify('Installing project dependencies...', async () => util.npmInstall(projectPath, answers));
};
const createAppsScriptProject = async (projectPath, projectName, execOptions) => {
return util.spinnify('Creating Apps Script project...', async () => {
await appsscript.create(projectPath, projectName);
// Since clasp creating a new project overwrites the manifest, we want to
// copy the template manifest over the one generated by clasp.
await util.exec('mv temp/appsscript.json src/appsscript.json', execOptions);
await appsscript.push(projectPath);
});
};
const cloneAppsScriptProject = async (projectPath, scriptId) => {
// We don't need the template source files since we want the Apps Scripts project's
return util.spinnify('Cloning existing project...', async () => {
await util.exec('rm -rf src', { cwd: projectPath });
await appsscript.clone(projectPath, scriptId, 'src');
});
};
const manageDeployments = async (projectPath, answers) => {
let productionDeploymentId;
if (answers.scriptId !== undefined) {
// See if there is already a 'Production' deployment.
productionDeploymentId = await util.spinnify('Checking for a production deployment', async () => {
return appsscript.getDeploymentIdByName(projectPath, 'Production');
});
}
if (productionDeploymentId === undefined) {
productionDeploymentId = await util.spinnify('Creating a production deployment', async () => {
return await appsscript.deploy(projectPath, 'Production');
});
}
const latestDeploymentId = await util.spinnify('Getting the latest deploymentId', async () => {
return await appsscript.getDeploymentIdByName(projectPath, '@HEAD');
});
if (latestDeploymentId === undefined) {
throw new Error(`Wasn't able to get the latest deploymentId. This is probably a bug with dscc-gen.`);
}
return util.spinnify('Updating templates with your values...', async () => {
return files.fixTemplates(projectPath, [
{ match: /{{PRODUCTION_DEPLOYMENT_ID}}/, replace: productionDeploymentId },
{ match: /{{LATEST_DEPLOYMENT_ID}}/, replace: latestDeploymentId },
]);
});
};
exports.createFromTemplate = async (answers) => {
clear();
const { projectName, basePath } = answers;
const templatePath = path.join(basePath, 'templates', answers.projectChoice);
const projectPath = path.join(index_1.PWD, projectName);
await files.createAndCopyFiles(projectPath, templatePath, projectName);
await util.spinnify('Updating templates with your values...', async () => {
await files.fixTemplates(projectPath, getTemplates(answers));
});
const execOptions = { cwd: projectPath };
await installDependencies(projectPath, answers);
await ensureAuthenticated(execOptions);
if (answers.scriptId !== undefined) {
await cloneAppsScriptProject(projectPath, answers.scriptId);
}
else {
await createAppsScriptProject(projectPath, projectName, execOptions);
}
await manageDeployments(projectPath, answers);
// Remove temp directory.
await util.exec('rm -rf temp', execOptions);
const connectorOverview = blue(terminal_link_1.default('connector overview', 'https://developers.google.com/datastudio/connector/'));
const styledProjectName = green(projectName);
const cdDirection = yellow(`cd ${projectName}`);
const runCmd = answers.yarn ? 'yarn' : 'npm run';
const open = red(`${runCmd} open`);
const push = blue(`${runCmd} push`);
const watch = green(`${runCmd} watch`);
const prettier = yellow(`${runCmd} prettier`);
const tryLatest = red(`${runCmd} try_latest`);
const tryProduction = blue(`${runCmd} try_production`);
const updateProduction = green(`${runCmd} update_production`);
console.log(`\
Created a new community connector: ${styledProjectName}\n\
\n\
If this is your first connector, see ${connectorOverview}\n\
\n\
${cdDirection} to start working on your connector\n\
\n\
Scripts are provided to simplify development:\n\
\n\
${open} - open your project in Apps Script.\n\
${push} - push your local changes to Apps Script.\n\
${watch} - watches for local changes & pushes them to Apps Script.\n\
${prettier} - formats your code using community standards.\n\
${tryLatest} - opens the deployment with your latest code.\n\
${tryProduction} - opens your production deployment.\n\
${updateProduction} - updates your production deployment to use the latest code.\n\
`);
return 0;
};