Skip to content

useFeatureProvider и продвинутые флаги

useFeatureProvider

Полный доступ к внутреннему устройству провайдера — используйте для императивного управления флагами, наблюдаемости и продвинутых интеграций.

ts
import { useFeatureProvider } from 'vue-feature-toggles'

const {
  // Состояние
  flags, // Ref<Record<string, FlagValue>> — все текущие значения флагов
  isLoading, // Ref<boolean> — true, пока работает loader
  isReady, // Ref<boolean> — true после первой загрузки

  // Булевы флаги
  isEnabled, // (name) => boolean
  setFlag, // (name, value, options?) => void
  resetFlag, // (name) => void
  resetAll, // () => void
  reload, // () => Promise<void>
  getFlagSource, // (name) => FlagSource

  // Вариантные флаги
  getVariant, // (name) => string
  setVariant, // (name, variant) => void

  // Переменные
  getVariable, // <T>(flagName, varName) => Ref<T>
  setVariable, // (flagName, varName, value) => void

  // Группы
  setGroup, // (groupName, value) => void
  resetGroup, // (groupName) => void
  isGroupEnabled, // (groupName) => boolean

  // Зависимости
  getDependencyViolations, // () => Record<string, string[]>

  // Профили
  saveProfile, // (name, flags) => void
  loadProfile, // (name) => void  ('default' → resetAll)
  listProfiles, // () => string[]

  // Персистентность
  isPersisted, // (name) => boolean
  clearPersistedFlags, // () => void

  // Метаданные и срок действия
  getFlagMeta, // (name) => FlagMeta | undefined
  isExpired, // (name) => boolean

  // SSR
  serialize, // () => Record<string, FlagValue>

  // Подписки
  watchFlag, // (name, callback, options?) => WatchStopHandle

  // Интроспекция раскатки
  getRollout, // (name) => number | undefined
  getSchedule, // (name) => FlagSchedule | undefined
  isScheduleActive, // (name) => boolean

  // Интроспекция
  listVariables, // (flagName) => string[]
  listGroups, // () => Record<string, string[]>
} = useFeatureProvider()

Частые паттерны

ts
// Аварийный выключатель
setFlag('newPaymentFlow', false)

// Route guard
router.beforeEach((to) => {
  const { isEnabled } = useFeatureProvider()
  if (to.meta.feature && !isEnabled(to.meta.feature as string)) {
    return { name: 'NotFound' }
  }
})

// Реакция на изменение конкретного флага
const stop = watchFlag('darkMode', (value, oldValue) => {
  applyTheme(value ? 'dark' : 'light')
})
// позже: stop()

Переменные флагов

Переменные привязаны к флагу и разделяют его цепочку приоритетов. Их можно переопределить через URL или setVariable.

ts
app.use(FeatureToggles, {
  flags: { newCheckout: true },
  variables: {
    newCheckout: {
      maxItems: 5,
      theme: 'dark',
      buttonLabel: 'Place order',
    },
  },
})
ts
const { getVariable, setVariable } = useFeatureProvider()

const maxItems = getVariable<number>('newCheckout', 'maxItems') // Ref<number>
const theme = getVariable<string>('newCheckout', 'theme') // Ref<string>

setVariable('newCheckout', 'maxItems', 10)

Переопределение через URL: ?feature-var:newCheckout:maxItems=10

Группы флагов

ts
app.use(FeatureToggles, {
  groups: {
    beta: ['betaSearch', 'newDashboard', 'aiSuggestions'],
    maintenance: ['maintenanceMode', 'readOnlyBanner'],
  },
})
ts
const { setGroup, resetGroup, isGroupEnabled } = useFeatureProvider()

setGroup('beta', false) // выключить все бета-флаги
setGroup('maintenance', true)
isGroupEnabled('beta') // true, только когда включены ВСЕ флаги в группе
vue
<Feature group="beta"><BetaLabel /></Feature>

Зависимости флагов

Если требуемый флаг отключён, зависимый флаг принудительно выключается автоматически.

ts
app.use(FeatureToggles, {
  flags: { aiSuggestions: true, newSearch: false },
  dependencies: { aiSuggestions: ['newSearch'] },
})
// aiSuggestions принудительно false, потому что newSearch равен false
ts
const { getDependencyViolations } = useFeatureProvider()
// → { aiSuggestions: ['newSearch'] }

При нарушении в консоли разработчика выводится предупреждение.