UNPKG

firebase-tools

Version:
207 lines (206 loc) • 8.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getBaseParamBindings = getBaseParamBindings; exports.buildBindingOptionsWithBaseValue = buildBindingOptionsWithBaseValue; exports.setNewDefaults = setNewDefaults; exports.getParams = getParams; exports.getParamsForUpdate = getParamsForUpdate; exports.promptForNewParams = promptForNewParams; exports.readEnvFile = readEnvFile; exports.isSystemParam = isSystemParam; exports.partitionParams = partitionParams; exports.populateDefaultParams = populateDefaultParams; const path = require("path"); const clc = require("colorette"); const fs = require("fs-extra"); const error_1 = require("../error"); const logger_1 = require("../logger"); const extensionsHelper_1 = require("./extensionsHelper"); const askUserForParam = require("./askUserForParam"); const askUserForParam_1 = require("./askUserForParam"); const env = require("../functions/env"); const NONINTERACTIVE_ERROR_MESSAGE = "As of firebase-tools@11, `ext:install`, `ext:update` and `ext:configure` are interactive only commands. " + "To deploy an extension noninteractively, use an extensions manifest and `firebase deploy --only extensions`. " + "See https://firebase.google.com/docs/extensions/manifest for more details"; function getBaseParamBindings(params) { let ret = {}; for (const [k, v] of Object.entries(params)) { ret = { ...ret, ...{ [k]: v.baseValue }, }; } return ret; } function buildBindingOptionsWithBaseValue(baseParams) { let paramOptions = {}; for (const [k, v] of Object.entries(baseParams)) { paramOptions = { ...paramOptions, ...{ [k]: { baseValue: v } }, }; } return paramOptions; } function setNewDefaults(params, newDefaults) { for (const param of params) { if (newDefaults[param.param]) { param.default = newDefaults[param.param]; } else if (param.param === `firebaseextensions.v1beta.function/location` && newDefaults["LOCATION"]) { param.default = newDefaults["LOCATION"]; } } return params; } async function getParams(args) { let params; if (args.nonInteractive) { throw new error_1.FirebaseError(NONINTERACTIVE_ERROR_MESSAGE); } else { const firebaseProjectParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId); params = await askUserForParam.ask({ projectId: args.projectId, instanceId: args.instanceId, paramSpecs: args.paramSpecs, firebaseProjectParams, reconfiguring: !!args.reconfiguring, }); } return params; } async function getParamsForUpdate(args) { let params; if (args.nonInteractive) { throw new error_1.FirebaseError(NONINTERACTIVE_ERROR_MESSAGE); } else { params = await promptForNewParams({ spec: args.spec, newSpec: args.newSpec, currentParams: args.currentParams, projectId: args.projectId, instanceId: args.instanceId, }); } return params; } async function promptForNewParams(args) { const newParamBindingOptions = buildBindingOptionsWithBaseValue(args.currentParams); const allOldParams = (args.spec.params ?? []).concat(args.spec.systemParams ?? []); const allNewParams = (args.newSpec.params ?? []).concat(args.newSpec.systemParams ?? []); if (allOldParams.some((p) => p.param === "LOCATION") && allNewParams.some((p) => p.param === "firebaseextensions.v1beta.function/location") && !!args.currentParams["LOCATION"]) { newParamBindingOptions["firebaseextensions.v1beta.function/location"] = { baseValue: args.currentParams["LOCATION"], }; delete newParamBindingOptions["LOCATION"]; } for (const newP of allNewParams) { if (!newP.required && newParamBindingOptions[newP.param] === undefined) { newParamBindingOptions[newP.param] = { baseValue: newP.default ?? "", }; } } const unassignedOldParams = allOldParams.filter((oldP) => { if (oldP.param === "LOCATION" && allNewParams.some((p) => p.param === "firebaseextensions.v1beta.function/location")) { return false; } return !allNewParams.some((newP) => newP.param === oldP.param); }); if (unassignedOldParams.length) { logger_1.logger.info("The following params will no longer be used:"); for (const param of unassignedOldParams) { if (args.currentParams[param.param] !== undefined) { logger_1.logger.info(clc.red(`- ${param.param}: ${args.currentParams[param.param]}`)); } delete newParamBindingOptions[param.param]; } } const hasLocationSpec = allNewParams.some((p) => p.param === "firebaseextensions.v1beta.function/location"); const locationIsSet = !!newParamBindingOptions["firebaseextensions.v1beta.function/location"]?.baseValue || !!args.currentParams["firebaseextensions.v1beta.function/location"] || !!args.currentParams["LOCATION"]; const locationNotSet = hasLocationSpec && !locationIsSet; const triggerAdvancedSystemParams = unassignedOldParams.length > 0 || locationNotSet; const paramsToPrompt = []; for (const newP of allNewParams) { const oldP = allOldParams.find((p) => p.param === newP.param); const currentVal = newParamBindingOptions[newP.param]?.baseValue; const isSystem = isSystemParam(newP.param) || (args.newSpec.systemParams ?? []).some((p) => p.param === newP.param); if (!oldP && !isSystem) { paramsToPrompt.push(newP); continue; } if (oldP && oldP.type !== newP.type) { paramsToPrompt.push(newP); continue; } if (currentVal !== undefined && currentVal !== "" && !(0, askUserForParam_1.checkResponse)(currentVal, newP)) { paramsToPrompt.push(newP); continue; } if (newP.required && (currentVal === undefined || currentVal === "")) { paramsToPrompt.push(newP); continue; } if (triggerAdvancedSystemParams && (isSystem || newP.advanced)) { paramsToPrompt.push(newP); continue; } } let uniqueParamsToPrompt = paramsToPrompt.filter((p, index, self) => index === self.findIndex((tp) => tp.param === p.param)); if (uniqueParamsToPrompt.length) { const firebaseProjectParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId); uniqueParamsToPrompt = (0, extensionsHelper_1.substituteParams)(uniqueParamsToPrompt, firebaseProjectParams); logger_1.logger.info("To update this instance, configure the following parameters:"); for (const param of uniqueParamsToPrompt) { const chosenValue = await askUserForParam.askForParam({ projectId: args.projectId, instanceId: args.instanceId, paramSpec: param, reconfiguring: false, }); newParamBindingOptions[param.param] = chosenValue; } } return newParamBindingOptions; } function readEnvFile(envPath) { const buf = fs.readFileSync(path.resolve(envPath), "utf8"); const result = env.parse(buf.toString().trim()); if (result.errors.length) { throw new error_1.FirebaseError(`Error while parsing ${envPath} - unable to parse following lines:\n${result.errors.join("\n")}`); } return result.envs; } function isSystemParam(paramName) { const regex = /^firebaseextensions\.[a-zA-Z0-9\.]*\//; return regex.test(paramName); } function partitionParams(params) { const userParams = {}; const systemParams = {}; for (const [key, value] of Object.entries(params)) { if (isSystemParam(key)) { systemParams[key] = value; } else { userParams[key] = value; } } return { params: userParams, systemParams }; } function populateDefaultParams(params, spec) { const ret = { ...params }; for (const p of spec.params) { ret[p.param] = ret[p.param] ?? p.default; } return ret; }