UNPKG

@bubblewrap/cli

Version:

CLI tool to Generate TWA projects from a Web Manifest

157 lines (156 loc) 7.71 kB
"use strict"; /* * Copyright 2019 Google Inc. All Rights Reserved. * * 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 * * http://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 }); exports.build = void 0; const core_1 = require("@bubblewrap/core"); const path = require("path"); const fs = require("fs"); const strings_1 = require("../strings"); const Prompt_1 = require("../Prompt"); const validator_1 = require("@bubblewrap/validator"); const pwaValidationHelper_1 = require("../pwaValidationHelper"); const inputHelpers_1 = require("../inputHelpers"); class Build { constructor(args, androidSdkTools, keyTool, gradleWrapper, jarSigner, log = new core_1.ConsoleLog('build'), prompt = new Prompt_1.InquirerPrompt()) { this.args = args; this.androidSdkTools = androidSdkTools; this.keyTool = keyTool; this.gradleWrapper = gradleWrapper; this.jarSigner = jarSigner; this.log = log; this.prompt = prompt; } /** * Checks if the keystore password and the key password are part of the environment prompts the * user for a password otherwise. * * @returns {Promise<SigningKeyPasswords} the password information collected from enviromental * variables or user input. */ async getPasswords(signingKeyInfo) { // Check if passwords are set as environment variables. const envKeystorePass = process.env['BUBBLEWRAP_KEYSTORE_PASSWORD']; const envKeyPass = process.env['BUBBLEWRAP_KEY_PASSWORD']; if (envKeyPass !== undefined && envKeystorePass !== undefined) { this.prompt.printMessage(strings_1.enUS.messageUsingPasswordsFromEnv); return { keystorePassword: envKeystorePass, keyPassword: envKeyPass, }; } // Ask user for the keystore password this.prompt.printMessage(strings_1.enUS.messageEnterPasswords(signingKeyInfo.path, signingKeyInfo.alias)); const keystorePassword = await this.prompt.promptPassword(strings_1.enUS.promptKeystorePassword, inputHelpers_1.createValidateString(6)); const keyPassword = await this.prompt.promptPassword(strings_1.enUS.promptKeyPassword, inputHelpers_1.createValidateString(6)); return { keystorePassword: keystorePassword, keyPassword: keyPassword, }; } async runValidation() { try { const manifestFile = path.join(process.cwd(), 'twa-manifest.json'); const twaManifest = await core_1.TwaManifest.fromFile(manifestFile); const pwaValidationResult = await validator_1.PwaValidator.validate(new URL(twaManifest.startUrl, twaManifest.webManifestUrl)); return core_1.Result.ok(pwaValidationResult); } catch (e) { return core_1.Result.error(e); } } async generateAssetLinks(twaManifest, passwords) { try { const digitalAssetLinksFile = './assetlinks.json'; const keyInfo = await this.keyTool.keyInfo({ path: twaManifest.signingKey.path, alias: twaManifest.signingKey.alias, keypassword: passwords.keyPassword, password: passwords.keystorePassword, }); const sha256Fingerprint = keyInfo.fingerprints.get('SHA256'); if (!sha256Fingerprint) { this.prompt.printMessage(strings_1.enUS.messageSha256FingerprintNotFound); return; } const digitalAssetLinks = core_1.DigitalAssetLinks.generateAssetLinks(twaManifest.packageId, sha256Fingerprint); await fs.promises.writeFile(digitalAssetLinksFile, digitalAssetLinks); this.prompt.printMessage(strings_1.enUS.messageDigitalAssetLinksSuccess(digitalAssetLinksFile)); } catch (e) { this.prompt.printMessage(strings_1.enUS.errorAssetLinksGeneration); } } async buildApk(signingKey, passwords) { await this.gradleWrapper.assembleRelease(); await this.androidSdkTools.zipalign('./app/build/outputs/apk/release/app-release-unsigned.apk', // input file './app-release-unsigned-aligned.apk'); const outputFile = './app-release-signed.apk'; await this.androidSdkTools.apksigner(signingKey.path, passwords.keystorePassword, signingKey.alias, passwords.keyPassword, './app-release-unsigned-aligned.apk', // input file path outputFile); this.prompt.printMessage(strings_1.enUS.messageApkSucess(outputFile)); } async buildAppBundle(signingKey, passwords) { await this.gradleWrapper.bundleRelease(); const inputFile = 'app/build/outputs/bundle/release/app-release.aab'; const outputFile = './app-release-bundle.aab'; await this.jarSigner.sign(signingKey, passwords.keystorePassword, passwords.keyPassword, inputFile, outputFile); this.prompt.printMessage(strings_1.enUS.messageAppBundleSuccess(outputFile)); } async build() { if (!await this.androidSdkTools.checkBuildTools()) { this.prompt.printMessage(strings_1.enUS.messageInstallingBuildTools); await this.androidSdkTools.installBuildTools(); } let validationPromise = null; if (!this.args.skipPwaValidation) { validationPromise = this.runValidation(); } const twaManifest = await core_1.TwaManifest.fromFile('./twa-manifest.json'); const passwords = await this.getPasswords(twaManifest.signingKey); // Builds the Android Studio Project this.prompt.printMessage(strings_1.enUS.messageBuildingApp); await this.buildApk(twaManifest.signingKey, passwords); await this.buildAppBundle(twaManifest.signingKey, passwords); await this.generateAssetLinks(twaManifest, passwords); if (validationPromise !== null) { const result = await validationPromise; if (result.isOk()) { const pwaValidationResult = result.unwrap(); pwaValidationHelper_1.printValidationResult(pwaValidationResult, this.log); if (pwaValidationResult.status === 'FAIL') { this.prompt.printMessage(strings_1.enUS.warnPwaFailedQuality); } } else { const e = result.unwrapError(); this.log.debug(e.message); this.prompt.printMessage(strings_1.enUS.errorFailedToRunQualityCriteria); } } return true; } } async function build(config, args, log = new core_1.ConsoleLog('build'), prompt = new Prompt_1.InquirerPrompt()) { const jdkHelper = new core_1.JdkHelper(process, config); const androidSdkTools = await core_1.AndroidSdkTools.create(process, config, jdkHelper, log); const keyTool = new core_1.KeyTool(jdkHelper, log); const gradleWrapper = new core_1.GradleWrapper(process, androidSdkTools); const jarSigner = new core_1.JarSigner(jdkHelper); const build = new Build(args, androidSdkTools, keyTool, gradleWrapper, jarSigner, log, prompt); return build.build(); } exports.build = build;