eas-cli
Version:
EAS command line tool
255 lines (254 loc) • 12.8 kB
JavaScript
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;
;