@basenative /旗帜
带有百分比推出、基于规则的目标和可插拔提供者的特性标志
部分 BaseNative 生态系统——基于信号的web运行时,基于原生HTML。
安装
npm install @basenative/flags
快速入门
import { createFlagManager, createMemoryProvider } from '@basenative/flags';
const provider = createMemoryProvider({
newDashboard: { enabled: true },
betaSearch: { percentage: 20 },
premiumFeature: {
enabled: false,
rules: [{ attribute: 'plan', value: 'pro', value: true }],
},
});
const flags = createFlagManager(provider);
// Simple boolean check
const showNew = await flags.isEnabled('newDashboard'); // true
// Percentage rollout (consistent per userId)
const inBeta = await flags.isEnabled('betaSearch', { userId: 'user-42' });
// Get all flags for client hydration
const allFlags = await flags.getAll({ userId: 'user-42' });
服务器中间件
import { flagMiddleware } from '@basenative/flags';
import { createPipeline } from '@basenative/middleware';
const pipeline = createPipeline()
.use(flagMiddleware(flags));
// ctx.state.flags is now an object of resolved flag values
模板的指令: @feature
@basenative/flags 注册一个 @feature 模板指令 @basenative/runtime作为导入这个包的副作用——它在任何地方都可以工作 render() (SSR)或 hydrate() (客户端)运行,没有额外的布线;
<template @feature="newDashboard">
<p>Try the new dashboard.</p>
</template>
<template @else>
<p>Classic dashboard.</p>
</template>
@feature 读取 ctx.$flags 从渲染/水合物上下文- a 同步 { isEnabled(name) } 对象。 flagManager.isEnabled() 是异步的(它等待提供程序),而模板呈现端到端是同步的,所以在呈现之前解析每个标志一次,使用 createFlagContext():
import { createFlagManager, createMemoryProvider, createFlagContext } from '@basenative/flags';
import { render } from '@basenative/server';
const flags = createFlagManager(createMemoryProvider({ newDashboard: { enabled: true } }));
const $flags = await createFlagContext(flags, { userId: user.id });
const html = render(template, { ...data, $flags });
在客户端,水合物具有相同的形状-通常从服务器响应中嵌入(例如: $flags.flags),并重组为 { isEnabled: (name) => Boolean(flags[name]) },或者一个活动对象,如果你想让标志对变化做出反应:
import { hydrate } from '@basenative/runtime';
hydrate(root, { ...data, $flags: { isEnabled: (name) => window.__FLAGS__[name] } });
没有 $flags 在上下文中, @feature 将标志视为禁用-它呈现 @else 如果存在,则不存在-并发出 BN_FEATURE_NO_PROVIDER 诊断(通过 options.onDiagnostic),而不是对无法求值的标志猜测“enabled”。 flagName 是一个字面的标志名,而不是一个表达式-没有引号,不像 @if/@switch.
在一个非——<template> 元素, @feature="x" 控制流不像其他流吗 @name 在那里,它变成了一个名为 feature, @basenative/validate 将其标记为 BN_E_CONTROL_FLOW_ON_ELEMENT.
createFlagContext(flagManager, context?)
为每个标志解析一次 context 形状与…相同 isEnabled并返回一个普通的同步快照: { flags: Record<string, boolean>, isEnabled: (name) => boolean }. 使用它的 isEnabled 在 ctx.$flags 用于 @feature.
API
createFlagManager(provider, options?)
创建标志求值管理器。选项: defaultValue -未找到标志时返回的值(默认值: false)。
返回:
isEnabled(flagName, context?)——返回Promise<boolean>. 上下文字段,如userId和sessionId用于百分比滚出散列。getAll(context?)——返回Promise<Record<string, boolean>>为给定上下文解析了所有标志。setFlag(flagName, config)-如果提供程序支持写,则更新标志的配置。
标志配置形状
{
enabled: true, // simple boolean
percentage: 25, // % rollout, 0-100
rules: [ // rule-based targeting
{ attribute: 'plan', value: 'pro', result: true }
]
}
供应商
createMemoryProvider(options)-内存提供程序。选项:flags- initial flag config map。.getFlag(name)-返回一个标志配置。.getAllFlags()—返回所有标志配置。.setFlag(name, config)-更新标志配置。
createRemoteProvider(options)-从HTTP端点获取标志。选项:url,token,ttl(缓存TTL以毫秒为单位)。
flagMiddleware(flagManager, options?)
解析当前请求上下文和集合的所有标志 ctx.state.flags. 选项: getContext(ctx) -从请求上下文中提取评估上下文的函数。
许可证
apache - 2.0