eas-cli
Version:
EAS command line tool
134 lines (133 loc) • 8.15 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateOrSetProjectIdAsync = exports.getProjectIdAsync = exports.saveProjectIdToAppConfigAsync = void 0;
const tslib_1 = require("tslib");
const config_1 = require("@expo/config");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const createGraphqlClient_1 = require("./createGraphqlClient");
const findProjectDirAndVerifyProjectSetupAsync_1 = require("./findProjectDirAndVerifyProjectSetupAsync");
const AppQuery_1 = require("../../../graphql/queries/AppQuery");
const log_1 = tslib_1.__importStar(require("../../../log"));
const ora_1 = require("../../../ora");
const expoConfig_1 = require("../../../project/expoConfig");
const fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1 = require("../../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync");
const User_1 = require("../../../user/User");
/**
* Save an EAS project ID to the appropriate field in the app config.
*
* @deprecated Should not be used outside of context functions except in the init command.
* @deprecated Starting from `@expo/config` from SDK 52, the `modifyConfigAsync` function is merging existing data. Once this is released, we can use that instead of manually merging.
*/
async function saveProjectIdToAppConfigAsync(projectDir, projectId, options = {}) {
// NOTE(cedric): we disable plugins to avoid writing plugin-generated content to `expo.extra`
const exp = await (0, expoConfig_1.getPrivateExpoConfigAsync)(projectDir, { skipPlugins: true, ...options });
const result = await (0, expoConfig_1.createOrModifyExpoConfigAsync)(projectDir, {
extra: { ...exp.extra, eas: { ...exp.extra?.eas, projectId } },
}, { skipSDKVersionRequirement: true });
switch (result.type) {
case 'success':
break;
case 'warn': {
log_1.default.warn();
log_1.default.warn(`Warning: Your project uses dynamic app configuration, and the EAS project ID can't automatically be added to it.`);
log_1.default.warn(chalk_1.default.dim('https://docs.expo.dev/workflow/configuration/#dynamic-configuration-with-appconfigjs'));
log_1.default.warn();
log_1.default.warn(`To complete the setup process, set "${chalk_1.default.bold('extra.eas.projectId')}" in your ${chalk_1.default.bold((0, config_1.getProjectConfigDescription)(projectDir))}:`);
log_1.default.warn();
log_1.default.warn(chalk_1.default.bold(JSON.stringify({ expo: { extra: { eas: { projectId } } } }, null, 2)));
log_1.default.warn();
throw new Error(result.message);
}
case 'fail':
throw new Error(result.message);
default:
throw new Error('Unexpected result type from modifyConfigAsync');
}
}
exports.saveProjectIdToAppConfigAsync = saveProjectIdToAppConfigAsync;
/**
* Get the EAS project ID from the app config. If the project ID is not set in the config,
* use the owner/slug to identify an EAS project on the server (asking for confirmation first),
* and attempt to save the EAS project ID to the appropriate field in the app config. If unable to
* save to the app config, throw an error.
*
* @returns the EAS project ID
*
* @deprecated Should not be used outside of context functions.
*/
async function getProjectIdAsync(sessionManager, exp, options) {
// all codepaths in this function require a logged-in user with access to the owning account
// since they either query the app via graphql or create it, which includes getting info about
// the owner
const { actor, authenticationInfo } = await sessionManager.ensureLoggedInAsync({
nonInteractive: options.nonInteractive,
});
const graphqlClient = (0, createGraphqlClient_1.createGraphqlClient)(authenticationInfo);
const projectId = await validateOrSetProjectIdAsync({ exp, graphqlClient, actor, options });
return projectId;
}
exports.getProjectIdAsync = getProjectIdAsync;
async function validateOrSetProjectIdAsync({ exp, graphqlClient, actor, options, cwd, }) {
const localProjectId = exp.extra?.eas?.projectId;
if (localProjectId) {
if (typeof localProjectId !== 'string') {
throw new Error(`Project config: "extra.eas.projectId" must be a string, found ${typeof localProjectId}. If you're not sure how to set it up on your own, remove the property entirely and it will be automatically configured on the next EAS CLI run.`);
}
// check that the local project ID matches account and slug
const appForProjectId = await AppQuery_1.AppQuery.byIdAsync(graphqlClient, localProjectId);
if (exp.owner && exp.owner !== appForProjectId.ownerAccount.name) {
throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) does not match owner specified in the "owner" field (${exp.owner}). ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
}
const actorUsername = (0, User_1.getActorUsername)(actor);
if (!exp.owner && appForProjectId.ownerAccount.name !== actorUsername) {
if (actorUsername) {
throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) does not match the logged in user (${actorUsername}) and the "owner" field is not specified. To ensure all libraries work correctly, "owner": "${appForProjectId.ownerAccount.name}" should be added to the project config, which can be done automatically by re-running "eas init". ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
}
else {
// robot caller
throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) must be specified in "owner" field when using a robot access token. To ensure all libraries work correctly, "owner": "${appForProjectId.ownerAccount.name}" should be added to the project config, which can be done automatically by re-running "eas init". ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
}
}
if (exp.slug && exp.slug !== appForProjectId.slug) {
throw new Error(`Project config: Slug for project identified by "extra.eas.projectId" (${appForProjectId.slug}) does not match the "slug" field (${exp.slug}). ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
}
return localProjectId;
}
const projectDir = await (0, findProjectDirAndVerifyProjectSetupAsync_1.findProjectRootAsync)({
cwd,
});
if (!projectDir) {
throw new Error('This command must be run inside a project directory.');
}
log_1.default.warn('EAS project not configured.');
const getAccountNameForEASProjectSync = (exp, user) => {
if (exp.owner) {
return exp.owner;
}
switch (user.__typename) {
case 'User':
return user.username;
case 'SSOUser':
return user.username;
case 'Robot':
throw new Error('The "owner" manifest property is required when using robot users. See: https://docs.expo.dev/versions/latest/config/app/#owner');
}
};
const projectId = await (0, fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1.fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync)(graphqlClient, {
accountName: getAccountNameForEASProjectSync(exp, actor),
projectName: exp.slug,
}, {
nonInteractive: options.nonInteractive,
}, actor);
const spinner = (0, ora_1.ora)(`Linking local project to EAS project ${projectId}`).start();
try {
await saveProjectIdToAppConfigAsync(projectDir, projectId, options);
spinner.succeed(`Linked local project to EAS project ${projectId}`);
}
catch (e) {
spinner.fail();
throw e;
}
return projectId;
}
exports.validateOrSetProjectIdAsync = validateOrSetProjectIdAsync;
;