UNPKG

@puls-atlas/cli

Version:

The Puls Atlas CLI tool for managing Atlas projects

95 lines 3.85 kB
import fs from 'fs'; import path from 'path'; import jwt from 'jsonwebtoken'; import { selectProject } from '../../utils/firebase.js'; import { logger } from '../../utils/logger.js'; import { getSecret } from '../../utils/secrets.js'; import { normalizeOptionalString } from '../../utils/value.js'; export const DEFAULT_DEVELOPER_TOKEN_EXPIRES_IN = '12h'; export const DEVELOPER_TOKEN_FILE_MODE = 0o600; const normalizeDeveloperTokenExpiresIn = value => normalizeOptionalString(value) ?? DEFAULT_DEVELOPER_TOKEN_EXPIRES_IN; const normalizeDeveloperTokenOutputPath = value => normalizeOptionalString(value); export const canPrintDeveloperTokenToStdout = stdout => stdout?.isTTY === true; export const createDeveloperToken = (email, projectId, privateKey, options = {}) => jwt.sign({}, privateKey, { audience: projectId, expiresIn: normalizeDeveloperTokenExpiresIn(options.expiresIn), issuer: projectId, subject: email }); export const createDeveloperTokenEnvContent = (email, token) => `REACT_APP_API_LOGIN=${email}\nREACT_APP_API_TOKEN=${token}\n`; export const writeDeveloperTokenEnvFile = (filePath, email, token) => { const resolvedPath = path.resolve(process.cwd(), filePath); fs.mkdirSync(path.dirname(resolvedPath), { recursive: true }); fs.writeFileSync(resolvedPath, createDeveloperTokenEnvContent(email, token), { encoding: 'utf8', mode: DEVELOPER_TOKEN_FILE_MODE }); fs.chmodSync(resolvedPath, DEVELOPER_TOKEN_FILE_MODE); return resolvedPath; }; export default async (email, options = {}, dependencies = {}) => { const loggerImpl = dependencies.logger ?? logger; const selectProjectImpl = dependencies.selectProject ?? selectProject; const getSecretImpl = dependencies.getSecret ?? getSecret; const stdout = dependencies.stdout ?? process.stdout; const writeDeveloperTokenEnvFileImpl = dependencies.writeDeveloperTokenEnvFile ?? writeDeveloperTokenEnvFile; const expiresIn = normalizeDeveloperTokenExpiresIn(options.expiresIn); const writeEnvPath = normalizeDeveloperTokenOutputPath(options.writeEnv); const spinner = loggerImpl.spinner('Generating developer token...'); try { if (!writeEnvPath && !canPrintDeveloperTokenToStdout(stdout)) { throw new Error('Refusing to print a developer token to non-interactive stdout. ' + 'Use --write-env <path> instead.'); } const { projectId } = await selectProjectImpl('.firebaserc', { environment: 'development' }); const privateKey = await getSecretImpl('puls-atlas-api-key', 'latest', projectId); const token = createDeveloperToken(email, projectId, privateKey, { expiresIn }); let resolvedWriteEnvPath = null; spinner.succeed(writeEnvPath ? 'Developer token generated and saved.' : 'Developer token generated.'); loggerImpl.break(); if (writeEnvPath) { resolvedWriteEnvPath = writeDeveloperTokenEnvFileImpl(writeEnvPath, email, token); loggerImpl.summary('Developer token saved', [{ label: 'Path', tone: 'accent', value: resolvedWriteEnvPath }, { label: 'REACT_APP_API_LOGIN', tone: 'accent', value: email }, { label: 'Expires in', tone: 'accent', value: expiresIn }]); } else { loggerImpl.summary('Copy paste the following into your app/.env.local file', [{ label: 'REACT_APP_API_LOGIN', tone: 'accent', value: email }, { label: 'REACT_APP_API_TOKEN', tone: 'accent', value: token }]); } loggerImpl.break(); loggerImpl.warning(`WARNING: make sure to keep this token private. It expires in ${expiresIn}.`); return { expiresIn, projectId, token, writeEnvPath: resolvedWriteEnvPath }; } catch (error) { spinner.fail(error.message); return null; } };