Ctrl K
ComunidadGuías…

src/services/bundleLinkedChannels.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { Database } from '~/types/database.types'
import { useConsole } from '~/services/console'

export interface LinkedChannel {
  id: number
  name: string
  version?: number | null
  rollout_version?: number | null
  stable_linked?: boolean
  rollout_linked?: boolean
  version_info?: { name: string } | null
  rollout_version_info?: { name: string } | null
}

export function formatLinkedChannel(channel: LinkedChannel) {
  const names = [
    channel.version_info?.name,
    channel.rollout_version_info?.name,
  ].filter(Boolean)
  return `${channel.name} (${names.join(', ')})`
}

function mergeLinkedChannels(stableChannels: LinkedChannel[] = [], rolloutChannels: LinkedChannel[] = []) {
  const byId = new Map<number, LinkedChannel>()
  for (const channel of stableChannels)
    byId.set(channel.id, { ...channel, stable_linked: true })
  for (const channel of rolloutChannels) {
    const existing = byId.get(channel.id)
    byId.set(channel.id, {
      ...existing,
      ...channel,
      stable_linked: existing?.stable_linked,
      rollout_linked: true,
    })
  }
  return [...byId.values()]
}

export async function fetchLinkedChannelsForVersion(appId: string, versionId: number) {
  const capgo = useConsole()
  const select = 'id, name, version, rollout_version, version_info:app_versions!channels_version_fkey(name), rollout_version_info:app_versions!channels_rollout_version_fkey(name)'
  const [stableResult, rolloutResult] = await Promise.all([
    capgo
      .from('channels')
      .select(select)
      .eq('app_id', appId)
      .eq('version', versionId),
    capgo
      .from('channels')
      .select(select)
      .eq('app_id', appId)
      .eq('rollout_version', versionId),
  ])

  if (stableResult.error)
    return { data: null, error: stableResult.error }
  if (rolloutResult.error)
    return { data: null, error: rolloutResult.error }

  return {
    data: mergeLinkedChannels(stableResult.data as LinkedChannel[], rolloutResult.data as LinkedChannel[]),
    error: null,
  }
}

export async function unlinkLinkedChannels(unlink: LinkedChannel[]) {
  if (unlink.length === 0)
    return null

  const capgo = useConsole()
  const results = await Promise.all(unlink.map(async (channel) => {
    const update: Database['public']['Tables']['channels']['Update'] = {}
    if (channel.stable_linked)
      update.version = null
    if (channel.rollout_linked) {
      update.rollout_version = null
      update.rollout_enabled = false
      update.rollout_percentage_bps = 0
      update.rollout_paused_at = null
      update.rollout_pause_reason = null
    }
    return await capgo
      .from('channels')
      .update(update)
      .eq('id', channel.id)
  }))

  return results.find(({ error }) => error)?.error ?? null
}

export interface BundleListChannel {
  id: number
  name: string
}

/** Dedupe + stable name sort for bundle-list channel chips. */
export function mergeBundleListChannels(channels: BundleListChannel[]): BundleListChannel[] {
  const byId = new Map<number, BundleListChannel>()
  for (const channel of channels) {
    if (channel?.id == null || !channel.name)
      continue
    byId.set(channel.id, { id: channel.id, name: channel.name })
  }
  return [...byId.values()].sort((a, b) => a.name.localeCompare(b.name))
}

/**
 * Compact label for the bundles table Channel column.
 * One or two channels → full comma list; three+ → `first +N`.
 * Full clickable list lives in BundleChannelsPopover (metadata-style).
 */
export function formatBundleListChannels(channels: BundleListChannel[], compactAfter = 2): { label: string, title: string } {
  const merged = mergeBundleListChannels(channels)
  if (merged.length === 0)
    return { label: '', title: '' }
  const names = merged.map(channel => channel.name)
  const title = names.join(', ')
  if (names.length <= compactAfter)
    return { label: title, title }
  return { label: `${names[0]} +${names.length - 1}`, title }
}