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