@controlvar/js-sdk

中文文档
0.3.0发布于 2026/11/07MITTypeScriptCommonJS零依赖构建来源已验证近 30 天下载 3543

JavaScript/TypeScript SDK 用于 Controlvar 公共 API (Node QQ 18和浏览器,零运行时间依赖性)

中文使用文档
文档目录10 节
  1. 安装
  2. 本版本的更改
  3. 事件编号
  4. 快开始
  5. API 密码
  6. 招生情况: assigned 财务报告和审定财务报表 reason
  7. 曝光钩
  8. 使用的后端端点
  9. 合同烟
  10. 发展

@ controlvar/js-sdk (英语)

贝塔. 这是 0.x 发布: 锁定您测试的精确版本 .

Controlvar公共API的JavaScript/TypeScript客户端. 18号节点和浏览器, 零运行时间依赖关系(全球) fetch),"共同JS"以类型声明来构建.

旗帜评估和实验任务 由服务器决定 默认; 结果为 内存中每个用户+密钥被缓存. 服务器侧码可以选择使用 当地评价 (单位:千美元)evaluation: 'local',β:旗从服务器的规则中按程序回答,并带有 服务器的答案,任何无法解答的都完全转到服务器。 见 docs/sdk/local-evaluation.md。 。 。 .

完整文档: docs/sdk/javascript.md。 。 。 .

安装

如果安装 @getexperimently/js-sdk,此软件包在工程改名前的名称,解开并安装 @controlvar/js-sdk。 。 。 .

这个 @controlvar/js-sdk 软件包已打开 无0.3.0是一个 β释放.

npm install @controlvar/[email protected]

欲研究SDK本身,见下文Development.

本版本的更改

  • getStringValue, (中文(简体) ), getNumberValue 财务报告和审定财务报表 getJsonValue 新的: 他们读取了字符串的值, 数字或Json旗服务。 无法返回时, 每人返回默认值, 并传递原因到 onError(err, 'value')。见 旗帜值。 。 。 .
  • FlagEvaluation 收益 value 财务报告和审定财务报表 valueType。 。 。 .
  • onExposure 是新: 当创建客户端时, 您会给客户端一个函数, 它每次调用一次 时间:服务器在实验中输入一个用户,而答案并非来自其缓存。 见 下出出相钩.
  • SwallowedOperation,类型 onError第二次辩论有两个新成员: 'value',用于 返回默认值的键入计数器,以及 'exposure',用于在 onExposure。 。 。 . ExperimentationErrorCode类型 ExperimentationError是因为 code,有两个新成员: 'TYPE_MISMATCH',对于一个旗帜服务 另一种类型比读取器 'HOOK_ERROR', (中文(简体) ), 失败的 onExposure。可以详尽地检查任一类型,例如 switch 谁 default 指定值为 never,停止编译,直到它处理全部四个 新成员: 'value', (中文(简体) ), 'exposure', (中文(简体) ), 'TYPE_MISMATCH' 财务报告和审定财务报表 'HOOK_ERROR'。 。 。 .
  • eventId 新开的 track() 财务报告和审定财务报表 trackBatch()。见下文事件编号.
  • 本地评价也回答字符串,数字或json旗的值. SDK 无法使用旗下条目 改为(a) evaluation 或者说 value_type 它不知道,或者一个错误类型的值)只发送 标记到服务器, 其余的规则仍然在本地响应; 在此之前 版本 a evaluation 它不知道拒绝整个规则, 客户端继续回答 从它的上一个.
  • 一旦当地评价停止回答国旗(maxStaleMs 规则被抛弃, close()),它在当地回答的用户呼叫到服务器;在此版本之前 用户从缓存中保存本地答案最多 cacheTtlMs。 。 。 .
  • A 类 cacheTtlMs 联 合 国 0 缓存什么。 在这个版本之前,一个答案在同一版本内被重用 毫秒,每个缓存的答案都活了一毫秒 cacheTtlMs。 。 。 .
  • 有限度 cacheTtlMs 24小时以上a track() 没有键仍然到达实验 或旗子,其答案仍然被缓存;在此版本之前,它只到达在 最后24小时.
  • 请求错误消息将方法和路径命名为没有查询字符串,该字符串带有 用户 id 和用户的属性; 在此版本之前, 有的将完整 URL 命名 .

事件编号

track() 财务报告和审定财务报表 trackBatch() 拿着 eventId编号 event_id。服务器存储发送的事件 同样的 event_id,用户,实验,旗帜和事件名称仅使用一次. 它需要一个 包含 Controlvar 服务器 event_id 更改( # 1640, 之后的第一个平台发布) 合并:一个更老的服务器忽略了字段.

  • SDK没有身份证明: eventId 没有人被派遣,再被派遣 再来一次 做一次ID, 当事件发生, 并给同样的一个 每次发送它.
  • undefined, (中文(简体) ), null 财务报告和审定财务报表 '' 无。 服务器拒绝超过 255 个字符的ID 或 一个持有 NUL 的 422SDK不检查它.
  • 一次活动吸引了几个实验和旗帜 在每个条目中都带有同样的标识。 A 类 429 重审后发送同样的ID。 SDK不会再次发出取消时间的请求.

快开始

import { ExperimentationClient } from '@controlvar/js-sdk';

const client = new ExperimentationClient({ apiUrl: 'http://localhost:8000', apiKey: 'eptk_...' });
const user = { userId: 'user-123', attributes: { plan: 'pro' } };

const assignment = await client.getAssignment('checkout_flow', user); // { experimentKey, userId, variantId, variantName, isControl, configuration, assigned?, reason? }
const variant = await client.getVariant('checkout_flow', user);       // variantName, 'control' on failure
const { enabled, config, reason } = await client.evaluateFlag('new_search', user); // attributes sent as ?context=
const on = await client.isFeatureEnabled('new_search', user);         // false on failure

await client.track('user-123', 'purchase', { value: 49.99, experimentKey: 'checkout_flow' });
await client.track('user-123', 'page_view'); // no key → every experiment + flag answered for this user

A 类 track 在每一个实验中都没有按键,并标出客户端为用户在 最后24小时, 缓存与否, 但实验是草稿、 暂停、 完成或存档. 没有,它就被发送一次,没有钥匙,并被保存为历史。 密钥存在于此客户端的记忆中 (最多10 000个用户) clearCache() 留着吧 在服务器上,通过 experimentKey 打开 转换.

API 密码

方法回返失败时
getAssignment(experimentKey, user)Promise<Assignment>拒绝方式 ExperimentationError (单位:千美元)code, (中文(简体) ), status, (中文(简体) ), body(中文(简体) )
getVariant(experimentKey, user)Promise<string>defaultVariant (单位:千美元)'control'(中文(简体) )
evaluateFlag(flagKey, user)Promise<FlagEvaluation> —— 说 { key, enabled, config, reason?, value?, valueType? }拒绝方式 ExperimentationError
isFeatureEnabled(flagKey, user)Promise<boolean>false
getStringValue(flagKey, user, defaultValue)Promise<string>,字符串旗的字符串服务于此用户defaultValue绝不拒绝; onError(err, 'value')
getNumberValue(flagKey, user, defaultValue)Promise<number>,数字标记的数字服务于此用户defaultValue绝不拒绝; onError(err, 'value')
getJsonValue(flagKey, user, defaultValue)Promise<T>,用于此用户的新对象或阵列副本defaultValue绝不拒绝; onError(err, 'value')
getAllFlags(userId, attributes?)Promise<Record<string, boolean>> (没有缓存)拒绝
track(userId, eventName, { value?, properties?, experimentKey?, featureFlagKey?, eventType?, timestamp?, eventId? })Promise<void>绝不拒绝; onError
trackBatch(events)Promise<{ successCount, failureCount, errors }> (满分100分)从不拒绝
reportError({ errorType, message, featureFlagKey?, experimentKey?, userId?, stackTrace?, metadata?, timestamp? })Promise<boolean>数字 : true 当服务器存储报告时( 201)false绝不拒绝; onError
fetchAssignments(userId, { activeOnly? })Promise<AssignmentRecord[]> 从服务器拒绝
getAssignments(userId), (中文(简体) ), getEvaluatedFlags(userId), (中文(简体) ), clearCache()模拟缓存访问—— 说
getCachedFlags(userId)FlagEvaluation[]: 缓存、 未过期的用户评价; 在本地模式下, 每个带 source (单位:千美元)'local' 或者说 'server'(中文(简体) )—— 说
ready({ timeoutMs? }), (中文(简体) ), status(), (中文(简体) ), close()本地模式: 准备状态、 规则设置状态、 关闭( 发送评价计数)从不拒绝
consistentHash(userId, flagKey), (中文(简体) ), md5Hex(s), (中文(简体) ), md5Bytes(s)兼容散列工具( 不是旗下打桶功能)—— 说

配置 : apiUrl, (中文(简体) ), apiKey (所需); timeoutMs (5000个), cacheTtlMs (30万; 计; 0 缓存什么, defaultVariant (单位:千美元)'control', (中文(简体) ), fetch, (中文(简体) ), onError(err, 'track' | 'trackBatch' | 'refresh' | 'flush' | 'evaluate' | 'reportError' | 'value' | 'exposure'), (中文(简体) ), onExposure(exposure) (见接触钩), evaluation (单位:千美元)'server' 或者说 'local', (中文(简体) ), refreshIntervalMs (30 000美元,最低5 000美元), maxStaleMs。 。 。 . 失败永远不会被缓存; 同时调用同一个用户 + 密钥共享一个请求; a 429 是 之后再试一次 Retry-After。 。 。 .

user.attributes 以 context 派任时 财务报告和审定财务报表 国旗评价 (单位:千美元)&context=<url-encoded JSON>,在空出时省略),所以旗下目标设定规则与之相对评价 (单位:千美元)country 也匹配 user.country; 嵌入对象平整为点键, 如 app.version) (中文(简体) ). Caches 仅由 user + 密钥键入- call clearCache() 修改用户属性后.

reportError 决定 true 当服务器存储报告时。 存储的报告数到 旗下错误率和自动回滚 仅当客户端的密钥有 sdk:ruleset 范围和范围 由用户创建,用户可以更改特征标记;旗帜的安全检查显示其他人是 uncounted_error_count。 。 。 .

招生情况: assigned 财务报告和审定财务报表 reason

一个 Assignment 还携带 assigned 财务报告和审定财务报表 reason。 。 。 . assigned: false 表示服务器没有 注册用户( e)reason 实值 'holdout', (中文(简体) ), 'mutual_exclusion' 或者说 'targeting')并返回 控制变体,这样你就能实现默认体验;没有记录曝光. 导出时 与仓库接触,不包括与 assigned: false:用户没有注册, 财务报告和审定财务报表 reason 说为什么 在字段之前的服务器不会发送, 所以 assigned 实值 undefined (从来没有) false) (中文(简体) ). 特意决定如何对待这些行而不是放下 带有 assigned === true 过滤器.

一个不是ACTIVE的实验 以控制变体回答每个用户, assigned: false 财务报告和审定财务报表 reason 达到其地位'draft', (中文(简体) ), 'paused', (中文(简体) ), 'completed' 或者说 'archived') (中文(简体) ).

曝光钩

onExposure 是您创建客户端时给客户端的函数。 客户每人打一次电话 时间:服务器将用户录入实验,而答案并非来自客户端 缓存:服务器记录曝光的那一刻. 用它来传送曝光到你的分析 工具或仓库.

const client = new ExperimentationClient({
  apiUrl: 'http://localhost:8000',
  apiKey: process.env.CONTROLVAR_API_KEY!,
  onExposure: (exposure) => {
    // your analytics tool's call goes here
    console.log('exposure', exposure.experimentKey, exposure.variantName, exposure.userId);
  },
  onError: (error, operation) => {
    if (operation === 'exposure') console.warn('onExposure failed', error.cause);
  },
});

它收到一个 Exposure数字 : experimentKey, (中文(简体) ), userId, (中文(简体) ), variantId (单位:千美元)null 当服务器发送时 (无)和 variantName。它不要求缓存的答案, 实验没有注册的用户 或未运行的实验(assigned: false),一个失败的呼叫,或者一个特征旗. 若为 它扔出,或者返回一个承诺,拒绝,答案是不变的,错误将发生 onError 操作 'exposure' 财务报告和审定财务报表 code 'HOOK_ERROR'。 。 。 .

详细情况 : 曝光钩。 。 。 .

使用的后端端点

每个请求都携带 X-API-Key, (中文(简体) ), Content-Type: application/json, (中文(简体) ), Accept: application/json。 。 。 .

SDK电话方法和路径200个答复
getAssignment, (中文(简体) ), getVariantPOST /api/v1/tracking/assign {experiment_key, user_id, context?}{experiment_key, user_id, variant_id, variant_name, is_control, configuration, assigned, reason}
evaluateFlag, (中文(简体) ), isFeatureEnabledGET /api/v1/feature-flags/evaluate/{flag_key}?user_id=…&context=<url-encoded JSON>{key, enabled, config, reason}
getAllFlagsGET /api/v1/feature-flags/user/{user_id}?context=<url-encoded JSON>{"<flag_key>": bool}
track 有密钥POST /api/v1/tracking/track忽略
track 无密钥POST /api/v1/tracking/batch {events: [...]} (≤100),每个实验一个条目并标出它到达的旗帜;没有, POST /api/v1/tracking/track 无密钥忽略
trackBatchPOST /api/v1/tracking/batch {events: [...]} (≤100){success_count, failure_count, errors}
fetchAssignmentsGET /api/v1/tracking/assignments/{user_id}?active_only=true列列表

出错:401个坏键,404个未知的实验或旗下键,或无控制变体(从未被缓存)的草稿实验,422个无效事件,429个速率有限. 非 ACTIVE 的旗帜不是错误: 它回答 enabled: false, (中文(简体) ), reason: "inactive"。 。 。 .

合同烟

cd sdk/js && npm run build --silent && node examples/contract_smoke.mjs

信封 : CONTROLVAR_API_URL (默认) http://localhost:8000, (中文(简体) ), CONTROLVAR_API_KEY (必须), CONTRACT_EXPERIMENT_KEY (单位:千美元)sdk_contract_ab, (中文(简体) ), CONTRACT_FLAG_KEY (单位:千美元)sdk_contract_flag, (中文(简体) ), CONTRACT_USER_ID。 。 。 .

CI负责SDK的合约烟雾 与真正的API: js 位于 sdks: 清单 SDK 现场合同工作 pr-qa-gate.yml (英语)。 。 。 .

发展

从 sdk/js 在克隆中 此寄存器数字 :

npm install
npm test
npm run build
  • npm test: Jest测试(嘲弄;当地评价员对照测试/sdk-contract/Rulesset-vectors.json)
  • npm run build: tsc → det/ (CommonJS +.d.ts) (中文(简体) )

版本与发布记录

@controlvar/js-sdk 共发布 5 个版本,首次发布于 2026/10/18;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.3.0latest2026/11/073 天前
0.2.02026/10/2912 天前
0.1.12026/10/1823 天前
0.0.1-stagestage2026/10/1823 天前
0.0.0-stage2026/10/1823 天前

关于 @controlvar/js-sdk 的常见问题

@controlvar/js-sdk 是什么?

JavaScript/TypeScript SDK 用于 Controlvar 公共 API (Node QQ 18和浏览器,零运行时间依赖性)

如何安装 @controlvar/js-sdk?

在项目目录运行 npm install @controlvar/js-sdk,或使用 pnpm add / yarn add / bun add。

@controlvar/js-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@controlvar/js-sdk 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@controlvar/js-sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@controlvar/js-sdk 可以商用吗?

@controlvar/js-sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@controlvar/js-sdk 的下载量有多少?

根据 npm 官方下载统计,@controlvar/js-sdk 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,543 次,日均约 118 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@controlvar/js-sdk 还在维护吗?

最新版本 0.3.0 发布于 2026/11/07(3 天前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/10/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。