UNPKG

eas-cli

Version:
134 lines (133 loc) 8.15 kB
"use strict"; 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;