UNPKG

eas-cli

Version:
255 lines (254 loc) 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const core_1 = require("@oclif/core"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const fs_extra_1 = tslib_1.__importDefault(require("fs-extra")); const path_1 = tslib_1.__importDefault(require("path")); const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand")); const flags_1 = require("../../commandUtils/flags"); const generated_1 = require("../../graphql/generated"); const EnvironmentVariableMutation_1 = require("../../graphql/mutations/EnvironmentVariableMutation"); const EnvironmentVariablesQuery_1 = require("../../graphql/queries/EnvironmentVariablesQuery"); const log_1 = tslib_1.__importDefault(require("../../log")); const projectUtils_1 = require("../../project/projectUtils"); const prompts_1 = require("../../prompts"); const prompts_2 = require("../../utils/prompts"); const variableUtils_1 = require("../../utils/variableUtils"); class EnvCreate extends EasCommand_1.default { static description = 'create an environment variable for the current project or account'; static args = [ { name: 'environment', description: "Environment to create the variable in. One of 'production', 'preview', or 'development'.", required: false, }, ]; static flags = { name: core_1.Flags.string({ description: 'Name of the variable', }), value: core_1.Flags.string({ description: 'Text value or the variable', }), link: core_1.Flags.boolean({ description: 'Link account-wide variable to the current project', hidden: true, // every account-wide variable is global for now so it's not user facing }), force: core_1.Flags.boolean({ description: 'Overwrite existing variable', default: false, }), type: core_1.Flags.enum({ description: 'The type of variable', options: ['string', 'file'], }), ...flags_1.EASVariableVisibilityFlag, ...flags_1.EASEnvironmentVariableScopeFlag, ...flags_1.EASMultiEnvironmentFlag, ...flags_1.EASNonInteractiveFlag, }; static contextDefinition = { ...this.ContextOptions.ProjectId, ...this.ContextOptions.Analytics, ...this.ContextOptions.LoggedIn, }; async runAsync() { const { args, flags } = await this.parse(EnvCreate); const validatedFlags = this.sanitizeFlags(flags); const { name, value, scope, 'non-interactive': nonInteractive, environment: environments, visibility, link, force, type, fileName, } = await this.promptForMissingFlagsAsync(validatedFlags, args); const { projectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(EnvCreate, { nonInteractive, }); const [projectDisplayName, ownerAccount] = await Promise.all([ (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId), (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId), ]); let overwrite = false; if (scope === generated_1.EnvironmentVariableScope.Project) { const existingVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.byAppIdAsync(graphqlClient, { appId: projectId, filterNames: [name], }); const existingVariable = existingVariables.find(variable => !environments || variable.environments?.some(env => environments?.includes(env))); if (existingVariable) { if (existingVariable.scope === generated_1.EnvironmentVariableScope.Project) { await this.promptForOverwriteAsync({ nonInteractive, force, message: `Variable ${name} already exists on this project.`, suggestion: 'Do you want to overwrite it?', }); overwrite = true; } if (existingVariable.scope === generated_1.EnvironmentVariableScope.Shared) { await this.promptForOverwriteAsync({ nonInteractive, force, message: `Account-wide variable with ${name} name already exists on this account.`, suggestion: 'Do you want to unlink it first?', }); log_1.default.withTick(`Unlinking account-wide variable ${chalk_1.default.bold(name)} on project ${chalk_1.default.bold(projectDisplayName)}.`); await (0, variableUtils_1.performForEnvironmentsAsync)(environments, async (environment) => { await EnvironmentVariableMutation_1.EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(graphqlClient, existingVariable.id, projectId, environment); }); } } const variable = overwrite && existingVariable ? await EnvironmentVariableMutation_1.EnvironmentVariableMutation.updateAsync(graphqlClient, { id: existingVariable.id, name, value, visibility, environments, type, fileName, }) : await EnvironmentVariableMutation_1.EnvironmentVariableMutation.createForAppAsync(graphqlClient, { name, value, environments, visibility, type: type ?? generated_1.EnvironmentSecretType.String, fileName, }, projectId); if (!variable) { throw new Error(`Could not create variable with name ${name} on project ${projectDisplayName}`); } log_1.default.withTick(`Created a new variable ${chalk_1.default.bold(name)} on project ${chalk_1.default.bold(projectDisplayName)}.`); } else if (scope === generated_1.EnvironmentVariableScope.Shared) { const existingVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.sharedAsync(graphqlClient, { appId: projectId, filterNames: [name], }); const existingVariable = existingVariables.find(variable => !environments || variable.environments?.some(env => environments?.includes(env))); if (existingVariable) { if (force) { overwrite = true; } else { throw new Error(`Account-wide variable with ${name} name already exists on this account.\n` + `Use a different name or delete the existing variable on website or by using the "eas env:delete --name ${name} --scope account" command.`); } } const variable = overwrite && existingVariable ? await EnvironmentVariableMutation_1.EnvironmentVariableMutation.updateAsync(graphqlClient, { id: existingVariable.id, name, value, visibility, environments, type, }) : await EnvironmentVariableMutation_1.EnvironmentVariableMutation.createSharedVariableAsync(graphqlClient, { name, value, visibility, environments, isGlobal: true, // TODO: every account-wide variable is global for now so it's not user facing type: type ?? generated_1.EnvironmentSecretType.String, }, ownerAccount.id); if (!variable) { throw new Error(`Could not create variable with name ${name} on account ${ownerAccount.name}`); } log_1.default.withTick(`Created a new variable ${chalk_1.default.bold(name)} on account ${chalk_1.default.bold(ownerAccount.name)}.`); if (link) { log_1.default.withTick(`Linking account-wide variable ${chalk_1.default.bold(name)} to project ${chalk_1.default.bold(projectDisplayName)}.`); await (0, variableUtils_1.performForEnvironmentsAsync)(environments, async (environment) => { await EnvironmentVariableMutation_1.EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(graphqlClient, variable.id, projectId, environment); }); log_1.default.withTick(`Linked account-wide variable ${chalk_1.default.bold(name)} to project ${chalk_1.default.bold(projectDisplayName)}.`); } } } async promptForOverwriteAsync({ nonInteractive, force, message, suggestion, }) { if (!nonInteractive) { const confirmation = await (0, prompts_1.confirmAsync)({ message: `${message} ${suggestion}`, }); if (!confirmation) { log_1.default.log('Aborting'); throw new Error(`${message}`); } } else if (!force) { throw new Error(`${message} Use --force to overwrite it.`); } } async promptForMissingFlagsAsync({ name, value, environment: environments, visibility, 'non-interactive': nonInteractive, type, ...rest }, { environment }) { if (!name) { name = await (0, prompts_2.promptVariableNameAsync)(nonInteractive); } let newType; let newVisibility = visibility ? (0, prompts_2.parseVisibility)(visibility) : undefined; if (type === 'file') { newType = generated_1.EnvironmentSecretType.FileBase64; } else if (type === 'string') { newType = generated_1.EnvironmentSecretType.String; } if (!type && !value && !nonInteractive) { newType = await (0, prompts_2.promptVariableTypeAsync)(nonInteractive); } if (!newVisibility) { newVisibility = await (0, prompts_2.promptVariableVisibilityAsync)(nonInteractive); } if (!value) { value = await (0, prompts_2.promptVariableValueAsync)({ nonInteractive, hidden: newVisibility !== generated_1.EnvironmentVariableVisibility.Public, filePath: newType === generated_1.EnvironmentSecretType.FileBase64, }); } let environmentFilePath; let fileName; if (newType === generated_1.EnvironmentSecretType.FileBase64) { environmentFilePath = path_1.default.resolve(value); if (!(await fs_extra_1.default.pathExists(environmentFilePath))) { throw new Error(`File "${value}" does not exist`); } fileName = path_1.default.basename(environmentFilePath); } value = environmentFilePath ? await fs_extra_1.default.readFile(environmentFilePath, 'base64') : value; if (environment && !(0, variableUtils_1.isEnvironment)(environment.toUpperCase())) { throw new Error("Invalid environment. Use one of 'production', 'preview', or 'development'."); } let newEnvironments = environments ? environments : environment ? [environment.toUpperCase()] : undefined; if (!newEnvironments) { newEnvironments = await (0, prompts_2.promptVariableEnvironmentAsync)({ nonInteractive, multiple: true }); if (!newEnvironments || newEnvironments.length === 0) { throw new Error('No environments selected'); } } newVisibility = newVisibility ?? generated_1.EnvironmentVariableVisibility.Public; return { name, value, environment: newEnvironments, visibility: newVisibility, link: rest.link ?? false, force: rest.force ?? false, 'non-interactive': nonInteractive, type: newType, fileName, ...rest, }; } sanitizeFlags(flags) { if (flags.scope !== 'account' && flags.link) { throw new Error(`Unexpected argument: --link can only be used when creating account-wide variables`); } return { ...flags, scope: flags.scope === 'account' ? generated_1.EnvironmentVariableScope.Shared : generated_1.EnvironmentVariableScope.Project, }; } } exports.default = EnvCreate;