UNPKG

firebase-tools

Version:
216 lines (215 loc) 8.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.longestCommonPrefix = exports.snakeToCamelCase = exports.lowercaseFirstLetter = exports.capitalizeFirstLetter = exports.toTitleCase = exports.getInstallPathPrefix = exports.getCodebaseDir = exports.writeSDK = exports.getCodebaseRuntime = exports.copyDirectory = exports.writeFile = exports.isTypescriptCodebase = exports.extensionMatchesAnyFilter = exports.extractExtensionsFromBuilds = exports.fixDarkBlueText = void 0; const fs = require("fs"); const path = require("path"); const prompt_1 = require("../../prompt"); const fsutils = require("../../fsutils"); const utils_1 = require("../../utils"); const error_1 = require("../../error"); const projectConfig_1 = require("../../functions/projectConfig"); const functionRuntimes = require("../../deploy/functions/runtimes"); const nodeRuntime = require("./node"); function fixDarkBlueText(txt) { const DARK_BLUE = "\u001b[34m"; const BRIGHT_CYAN = "\u001b[36;1m"; return txt.replaceAll(DARK_BLUE, BRIGHT_CYAN); } exports.fixDarkBlueText = fixDarkBlueText; function extractExtensionsFromBuilds(builds, filters) { const extRecords = {}; for (const [codebase, build] of Object.entries(builds)) { if (build.extensions) { for (const [id, ext] of Object.entries(build.extensions)) { if (extensionMatchesAnyFilter(codebase, id, filters)) { if (extRecords[id]) { throw new error_1.FirebaseError(`Duplicate extension id found: ${id}`); } extRecords[id] = Object.assign(Object.assign({}, ext), { labels: { createdBy: "SDK", codebase } }); } } } } return extRecords; } exports.extractExtensionsFromBuilds = extractExtensionsFromBuilds; function extensionMatchesAnyFilter(codebase, extensionId, filters) { if (!filters) { return true; } return filters.some((f) => extensionMatchesFilter(codebase, extensionId, f)); } exports.extensionMatchesAnyFilter = extensionMatchesAnyFilter; function extensionMatchesFilter(codebase, extensionId, filter) { if (codebase && filter.codebase) { if (codebase !== filter.codebase) { return false; } } if (!filter.idChunks) { return true; } const filterId = filter.idChunks.join("-"); return extensionId === filterId; } function isTypescriptCodebase(codebaseDir) { return fsutils.fileExistsSync(path.join(codebaseDir, "tsconfig.json")); } exports.isTypescriptCodebase = isTypescriptCodebase; async function writeFile(filePath, data, options) { const shortFilePath = filePath.replace(process.cwd(), "."); if (fsutils.fileExistsSync(filePath)) { if (await (0, prompt_1.confirm)({ message: `${shortFilePath} already exists. Overwite it?`, nonInteractive: options.nonInteractive, force: options.force, default: false, })) { try { await fs.promises.writeFile(filePath, data, { flag: "w" }); (0, utils_1.logLabeledBullet)("extensions", `successfully wrote ${shortFilePath}`); } catch (err) { throw new error_1.FirebaseError(`Failed to write ${shortFilePath}:\n ${(0, error_1.getErrMsg)(err)}`); } } else { return; } } else { try { await fs.promises.mkdir(path.dirname(filePath), { recursive: true }); try { await fs.promises.writeFile(`${filePath}`, data, { flag: "w" }); (0, utils_1.logLabeledBullet)("extensions", `successfully created ${shortFilePath}`); } catch (err) { throw new error_1.FirebaseError(`Failed to create ${shortFilePath}:\n ${(0, error_1.getErrMsg)(err)}`); } } catch (err) { throw new error_1.FirebaseError(`Error during SDK file creation:\n ${(0, error_1.getErrMsg)(err)}`); } } } exports.writeFile = writeFile; async function copyDirectory(src, dest, options) { const shortDestPath = dest.replace(process.cwd(), ","); if (fsutils.dirExistsSync(dest)) { if (await (0, prompt_1.confirm)({ message: `${shortDestPath} already exists. Copy anyway?`, nonInteractive: options.nonInteractive, force: options.force, default: false, })) { const entries = await fs.promises.readdir(src, { withFileTypes: true }); for (const entry of entries) { const srcPath = path.join(src, entry.name); const destPath = path.join(dest, entry.name); if (entry.isDirectory()) { if (srcPath.includes("node_modules")) { continue; } await copyDirectory(srcPath, destPath, Object.assign(Object.assign({}, options), { force: true })); } else if (entry.isFile()) try { await fs.promises.copyFile(srcPath, destPath); } catch (err) { throw new error_1.FirebaseError(`Failed to copy ${destPath.replace(process.cwd(), ".")}:\n ${(0, error_1.getErrMsg)(err)}`); } } } else { return; } } else { await fs.promises.mkdir(dest, { recursive: true }); await copyDirectory(src, dest, Object.assign(Object.assign({}, options), { force: true })); } } exports.copyDirectory = copyDirectory; async function getCodebaseRuntime(options) { const config = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions); const codebaseConfig = (0, projectConfig_1.configForCodebase)(config, options.codebase || projectConfig_1.DEFAULT_CODEBASE); const sourceDirName = codebaseConfig.source; const sourceDir = options.config.path(sourceDirName); const delegateContext = { projectId: "", sourceDir, projectDir: options.config.projectDir, runtime: codebaseConfig.runtime, }; let delegate; try { delegate = await functionRuntimes.getRuntimeDelegate(delegateContext); } catch (err) { throw new error_1.FirebaseError(`Could not detect target language for SDK at ${sourceDir}`); } return delegate.runtime; } exports.getCodebaseRuntime = getCodebaseRuntime; async function writeSDK(extensionRef, localPath, spec, options) { const runtime = await getCodebaseRuntime(options); if (runtime.startsWith("nodejs")) { let sampleImport = await nodeRuntime.writeSDK(extensionRef, localPath, spec, options); sampleImport = fixDarkBlueText(sampleImport); return sampleImport; } else { throw new error_1.FirebaseError(`Extension SDK generation is currently only supported for NodeJs. We detected the target source to be: ${runtime}`); } } exports.writeSDK = writeSDK; function getCodebaseDir(options) { if (!options.projectRoot) { throw new error_1.FirebaseError("Unable to determine root directory of project"); } const config = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions); const codebaseConfig = (0, projectConfig_1.configForCodebase)(config, options.codebase || projectConfig_1.DEFAULT_CODEBASE); return `${options.projectRoot}/${codebaseConfig.source}/`; } exports.getCodebaseDir = getCodebaseDir; function getInstallPathPrefix(options) { return `${getCodebaseDir(options)}generated/extensions/`; } exports.getInstallPathPrefix = getInstallPathPrefix; function toTitleCase(txt) { return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase(); } exports.toTitleCase = toTitleCase; function capitalizeFirstLetter(txt) { return txt.charAt(0).toUpperCase() + txt.substring(1); } exports.capitalizeFirstLetter = capitalizeFirstLetter; function lowercaseFirstLetter(txt) { return txt.charAt(0).toLowerCase() + txt.substring(1); } exports.lowercaseFirstLetter = lowercaseFirstLetter; function snakeToCamelCase(txt) { let ret = txt.toLowerCase(); ret = ret.replace(/_/g, " "); ret = ret.replace(/\w\S*/g, toTitleCase); ret = ret.charAt(0).toLowerCase() + ret.substring(1); return ret; } exports.snakeToCamelCase = snakeToCamelCase; function longestCommonPrefix(arr) { if (arr.length === 0) { return ""; } let prefix = ""; for (let pos = 0; pos < arr[0].length; pos++) { if (arr.every((s) => s.charAt(pos) === arr[0][pos])) { prefix += arr[0][pos]; } else break; } return prefix; } exports.longestCommonPrefix = longestCommonPrefix;