import { getPluginConfigContent } from '@/scripts/shared' import { PluginType } from '@ones-open/cli-utils' import type { ProjectCIDeployConfigBranch, ProjectLocalConfig, ProjectPluginConfig, } from '@ones-open/cli-utils' import type { LoginResponseSchema, PickteamCLIOptionsSchema, Team } from '@ones-open/cli-utils' import { isEmpty } from '@senojs/lodash' import inquirer from 'inquirer' import type { QuestionCollection } from 'inquirer' import { convertCIDeploymentBranchName, updateCIDeploymentConfig } from '../ci' import { updateLocalConfig } from '../login' import { convertCIDeploymentConfigToLoginParams, getCIDeploymentConfigMap, validateCanPickteamForCIDeployment, } from './ci' import { convertLocalConfigToLoginParams, getLocalConfigContent, validateCanPickteamForLocal, } from './local' import { cwd } from 'process' type PickteamTargetType = 'local' | 'ci' interface PickteamParamsValidatorOptions { currentWorkingDirectory?: string [k: string]: unknown } type PickteamParamsValidatorType = ( params: PickteamCLIOptionsSchema, validatorOptions?: PickteamParamsValidatorOptions, ) => Promise type PickteamPromptsInitialAnswer = Required> const PICKTEAM_COMMAND_ALLOW_TYPE = new Set(['local', 'ci']) function isPickteamCommandAllowTargetType(targetType: string): targetType is PickteamTargetType { return PICKTEAM_COMMAND_ALLOW_TYPE.has(targetType) } function getPickteamCommandConfigContent( targetType: PickteamTargetType, currentWorkingDirectory = cwd(), ) { switch (targetType) { case 'local': return getLocalConfigContent(currentWorkingDirectory) case 'ci': return getCIDeploymentConfigMap({ currentWorkingDirectory }) } } function getPickteamCommandParamsValidator(targetType: PickteamTargetType) { let validator: PickteamParamsValidatorType switch (targetType) { case 'local': validator = validateCanPickteamForLocal break case 'ci': validator = validateCanPickteamForCIDeployment break } if (!validator) throw new Error(`No validator found for target type ${targetType}`) return validator } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function getPickteamCommandLoginParams(targetType: PickteamTargetType, convertParams?: any) { if (!convertParams) throw new Error('Can not get login params, please check your input params') let loginParams switch (targetType) { case 'local': loginParams = await convertLocalConfigToLoginParams(convertParams) break case 'ci': loginParams = await convertCIDeploymentConfigToLoginParams(convertParams) break } if (!loginParams || Object.values(loginParams).some(isEmpty)) { const errorMessage = `Can not convert login params for target type ${targetType}` + `\nPlease make sure you already executed 'npx op ${targetType}' command before` throw new Error(errorMessage) } return loginParams } function validatePickteamCommandInputParams( targetType: PickteamTargetType, rawParams: Omit, options?: PickteamParamsValidatorOptions, ) { const validator = getPickteamCommandParamsValidator(targetType) const validatorOptions = { currentWorkingDirectory: cwd(), ...options, } return validator({ target: targetType, ...rawParams }, validatorOptions) } async function pickTheTeamInfo( { teams }: LoginResponseSchema, options?: Omit, ) { const { teamUuid: teamUUID, teamName } = options ?? {} const isPickingTeamByOptions = Boolean(teamUUID ?? teamName) if (isPickingTeamByOptions) { const team = teams.find(({ uuid, name }) => uuid === teamUUID || name === teamName) if (!team) { throw new Error( `Picking team by '${teamUUID || teamName}' failed, no team found in team list`, ) } return team } const teamMap = new Map(teams.map((team) => [team.uuid, team])) const teamChoices = [...teamMap].map(([, { uuid, name }]) => ({ name: `${name} (${uuid})`, value: uuid, })) const pickTeamPrompt: QuestionCollection = { type: 'list', name: 'teamUUID', message: 'Pick the team below to update information into the config file:', choices: teamChoices, } const pickTeamAnswer = await inquirer.prompt(pickTeamPrompt) const pickedTeam = teamMap.get(pickTeamAnswer.teamUUID) as Team return pickedTeam } interface UpdateTeamInfoIntoConfigOptions { targetType: PickteamTargetType config?: Map | ProjectLocalConfig pluginConfig?: ProjectPluginConfig branchName?: string } async function updateTeamInfoIntoConfig( { uuid: teamUUID, org_uuid: orgUUID }: Team, { targetType, config, pluginConfig, branchName }: UpdateTeamInfoIntoConfigOptions, ) { const configContent = config ?? (await getPickteamCommandConfigContent(targetType)) const isCIDeploymentConfig = configContent instanceof Map if (isCIDeploymentConfig) { if (!branchName) throw new Error('Branch name is required for update ci deployment config') const { service: { scope }, } = pluginConfig ?? (await getPluginConfigContent()) // 'scope' value or value type read from 'plugin.yaml' may invalidated. // considering uncertain demand from sprint P8050, we no need to validating the value and value type for now. // so just compare the value directly. const isOrgLevelPlugin = scope === PluginType.Organization const freshBranchConfig = { 'ones-check-point': isOrgLevelPlugin ? 'organization' : 'team', 'ones-check-id': isOrgLevelPlugin ? orgUUID : teamUUID, 'organization_uuid': orgUUID, 'team_uuid': teamUUID, } as ProjectCIDeployConfigBranch const freshDeploymentConfig = { [convertCIDeploymentBranchName(branchName)]: freshBranchConfig, } await updateCIDeploymentConfig(freshDeploymentConfig) } else { const freshLocalConfigFields = { local: { organization_uuid: orgUUID, team_uuid: teamUUID, }, } await updateLocalConfig(freshLocalConfigFields) } } async function displayPickteamPromptAfterLogin() { const confirmPrompt: QuestionCollection = { type: 'confirm', name: 'isNeedExecutePickteam', message: `Do you want to execute 'npx op pickteam' for update team information into config file?`, default: true, } const { isNeedExecutePickteam } = await inquirer.prompt(confirmPrompt) return isNeedExecutePickteam } export { isPickteamCommandAllowTargetType, validatePickteamCommandInputParams, getPickteamCommandConfigContent, getPickteamCommandParamsValidator, getPickteamCommandLoginParams, updateTeamInfoIntoConfig, pickTheTeamInfo, displayPickteamPromptAfterLogin, } export type { PickteamTargetType, PickteamParamsValidatorOptions, PickteamParamsValidatorType, PickteamPromptsInitialAnswer, }