UNPKG

eas-cli

Version:
266 lines (265 loc) 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAndLinkChannelAsync = exports.doesChannelExistAsync = exports.ensureChannelExistsAsync = exports.createChannelOnAppAsync = exports.listAndRenderBranchesAndUpdatesOnChannelAsync = exports.listAndRenderChannelsOnAppAsync = exports.selectChannelOnAppAsync = exports.CHANNELS_LIMIT = void 0; const tslib_1 = require("tslib"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const graphql_1 = require("graphql"); const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag")); const errors_1 = require("./errors"); const print_utils_1 = require("./print-utils"); const queries_1 = require("../branch/queries"); const utils_1 = require("../branch/utils"); const client_1 = require("../graphql/client"); const BranchQuery_1 = require("../graphql/queries/BranchQuery"); const ChannelQuery_1 = require("../graphql/queries/ChannelQuery"); const UpdateChannelBasicInfo_1 = require("../graphql/types/UpdateChannelBasicInfo"); const log_1 = tslib_1.__importStar(require("../log")); const projectUtils_1 = require("../project/projectUtils"); const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields")); const json_1 = require("../utils/json"); const queries_2 = require("../utils/queries"); exports.CHANNELS_LIMIT = 25; async function selectChannelOnAppAsync(graphqlClient, { projectId, selectionPromptTitle, paginatedQueryOptions, }) { if (paginatedQueryOptions.nonInteractive) { throw new Error('Unable to select a channel in non-interactive mode.'); } const updateChannel = await (0, queries_2.paginatedQueryWithSelectPromptAsync)({ limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT, offset: paginatedQueryOptions.offset, queryToPerform: (limit, offset) => queryChannelsOnAppAsync(graphqlClient, { appId: projectId, limit, offset }), promptOptions: { title: selectionPromptTitle, makePartialChoiceObject: updateChannel => ({ title: updateChannel.name }), getIdentifierForQueryItem: updateChannel => updateChannel.id, }, }); if (!updateChannel) { throw new Error(`Could not find any channels for app "${projectId}"`); } return updateChannel; } exports.selectChannelOnAppAsync = selectChannelOnAppAsync; async function listAndRenderChannelsOnAppAsync(graphqlClient, { projectId, paginatedQueryOptions, }) { if (paginatedQueryOptions.nonInteractive) { const channels = await queryChannelsOnAppAsync(graphqlClient, { appId: projectId, limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT, offset: paginatedQueryOptions.offset, }); renderPageOfChannels(channels, paginatedQueryOptions); } else { await (0, queries_2.paginatedQueryWithConfirmPromptAsync)({ limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT, offset: paginatedQueryOptions.offset, queryToPerform: (limit, offset) => queryChannelsOnAppAsync(graphqlClient, { limit, offset, appId: projectId }), promptOptions: { title: 'Load more channels?', renderListItems: channels => { renderPageOfChannels(channels, paginatedQueryOptions); }, }, }); } } exports.listAndRenderChannelsOnAppAsync = listAndRenderChannelsOnAppAsync; async function listAndRenderBranchesAndUpdatesOnChannelAsync(graphqlClient, { projectId: appId, channelName, paginatedQueryOptions, }) { const channel = await ChannelQuery_1.ChannelQuery.viewUpdateChannelAsync(graphqlClient, { appId, channelName }); renderChannelHeaderContent({ channelName: channel.name, channelId: channel.id, isPaused: channel.isPaused, }); if (paginatedQueryOptions.nonInteractive) { const branches = await queryBranchesAndUpdateGroupsOnChannelAsync(graphqlClient, { appId, channelName, offset: paginatedQueryOptions.offset, limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT, }); renderPageOfBranchesOnChannel(channel, branches, paginatedQueryOptions); } else { await (0, queries_2.paginatedQueryWithConfirmPromptAsync)({ limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT, offset: paginatedQueryOptions.offset, queryToPerform: (limit, offset) => queryBranchesAndUpdateGroupsOnChannelAsync(graphqlClient, { channelName, appId, offset, limit, }), promptOptions: { title: 'Load more channels?', renderListItems: branches => { renderPageOfBranchesOnChannel(channel, branches, paginatedQueryOptions); }, }, }); } } exports.listAndRenderBranchesAndUpdatesOnChannelAsync = listAndRenderBranchesAndUpdatesOnChannelAsync; async function queryChannelsOnAppAsync(graphqlClient, { appId, offset, limit }) { return await ChannelQuery_1.ChannelQuery.viewUpdateChannelsOnAppAsync(graphqlClient, { appId, offset, limit, }); } async function queryBranchesAndUpdateGroupsOnChannelAsync(graphqlClient, args) { return await BranchQuery_1.BranchQuery.listBranchesOnChannelAsync(graphqlClient, args); } function renderPageOfChannels(currentPage, { json }) { if (json) { (0, json_1.printJsonOnlyOutput)({ currentPage }); } else { for (const channel of currentPage) { renderChannelHeaderContent({ channelName: channel.name, channelId: channel.id, isPaused: channel.isPaused, }); log_1.default.addNewLineIfNone(); (0, print_utils_1.logChannelDetails)(channel); if (currentPage.indexOf(channel) < currentPage.length - 1) { log_1.default.log(`\n${chalk_1.default.dim('———')}\n`); } } } } function renderPageOfBranchesOnChannel(channel, currentPage, { json }) { const channelWithNewBranches = { ...channel, updateBranches: currentPage }; if (json) { (0, json_1.printJsonOnlyOutput)({ currentPage: channelWithNewBranches }); } else { // The channel details contain both the branch and latest update group log_1.default.addNewLineIfNone(); (0, print_utils_1.logChannelDetails)(channelWithNewBranches); } } function renderChannelHeaderContent({ channelName, channelId, isPaused, }) { log_1.default.addNewLineIfNone(); log_1.default.log(chalk_1.default.bold('Channel:')); log_1.default.log((0, formatFields_1.default)([ { label: 'Name', value: channelName }, { label: 'ID', value: channelId }, { label: 'Status', value: isPaused ? 'Paused' : 'Active' }, ])); log_1.default.addNewLineIfNone(); log_1.default.log((0, chalk_1.default) `{bold Branches pointed at this channel and their most recent update group:}`); } async function createChannelOnAppAsync(graphqlClient, { appId, branchId, channelName, }) { // Point the new channel at a branch with its same name. const branchMapping = JSON.stringify({ data: [{ branchId, branchMappingLogic: 'true' }], version: 0, }); return await (0, client_1.withErrorHandlingAsync)(graphqlClient .mutation((0, graphql_tag_1.default) ` mutation CreateUpdateChannelOnApp($appId: ID!, $name: String!, $branchMapping: String!) { updateChannel { createUpdateChannelForApp(appId: $appId, name: $name, branchMapping: $branchMapping) { id ...UpdateChannelBasicInfoFragment } } } ${(0, graphql_1.print)(UpdateChannelBasicInfo_1.UpdateChannelBasicInfoFragmentNode)} `, { appId, name: channelName, branchMapping, }) .toPromise()); } exports.createChannelOnAppAsync = createChannelOnAppAsync; async function ensureChannelExistsAsync(graphqlClient, { appId, branchId, channelName }) { try { await createChannelOnAppAsync(graphqlClient, { appId, channelName, branchId, }); } catch (e) { const isIgnorableError = e.graphQLErrors?.length === 1 && e.graphQLErrors[0].extensions.errorCode === 'CHANNEL_ALREADY_EXISTS'; if (!isIgnorableError) { throw e; } } } exports.ensureChannelExistsAsync = ensureChannelExistsAsync; async function doesChannelExistAsync(graphqlClient, { appId, channelName }) { try { await ChannelQuery_1.ChannelQuery.viewUpdateChannelAsync(graphqlClient, { appId, channelName, }); } catch (err) { if (err instanceof errors_1.ChannelNotFoundError) { return false; } throw err; } return true; } exports.doesChannelExistAsync = doesChannelExistAsync; /** * Creates a channel and links it to a branch with the same name. * * @param appId the app ID, also known as the project ID * @param channelName the name of the channel to create * @param shouldPrintJson print only the JSON output */ async function createAndLinkChannelAsync(graphqlClient, { appId, channelName, shouldPrintJson, }) { let branchId; let hasCreatedBranch = false; try { const branch = await BranchQuery_1.BranchQuery.getBranchByNameAsync(graphqlClient, { appId, name: channelName, }); branchId = branch.id; } catch (error) { if (error instanceof utils_1.BranchNotFoundError) { const newBranch = await (0, queries_1.createUpdateBranchOnAppAsync)(graphqlClient, { appId, name: channelName, }); branchId = newBranch.id; hasCreatedBranch = true; } else { throw error; } } const { updateChannel: { createUpdateChannelForApp: newChannel }, } = await createChannelOnAppAsync(graphqlClient, { appId, channelName, branchId, }); if (!newChannel) { throw new Error(`Could not create channel with name ${channelName} on project with id ${appId}`); } if (shouldPrintJson) { (0, json_1.printJsonOnlyOutput)(newChannel); } else { const projectDisplayName = await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, appId); const learnMoreLink = (0, log_1.learnMore)('https://docs.expo.dev/eas-update/eas-cli/'); log_1.default.addNewLineIfNone(); if (hasCreatedBranch) { log_1.default.withTick(`Created update channel ${chalk_1.default.bold(`"${newChannel.name}"`)} and branch ${chalk_1.default.bold(`"${newChannel.name}"`)} on ${chalk_1.default.bold(projectDisplayName)} project. ${learnMoreLink}`); } else { log_1.default.withTick(`Created update channel ${chalk_1.default.bold(`"${newChannel.name}"`)} on ${chalk_1.default.bold(projectDisplayName)} project and connected it with existing ${chalk_1.default.bold(`"${newChannel.name}"`)} branch. ${learnMoreLink}`); } } return newChannel; } exports.createAndLinkChannelAsync = createAndLinkChannelAsync;