@atlaskit/feature-gate-js-client

中文文档
8.0.0发布于 2026/11/02Apache-2.0TypeScriptESM + CJS近 30 天下载 568.1万

Statsig js-lite客户端的地图集包.

中文使用文档
文档目录20 节
  1. 使用量
  2. 这个仓库是干什么的?
  3. 客户用户
  4. 安装
  5. 初始化
  6. 评价
  7. 订阅
  8. 基于文件的持久覆盖
  9. 单一页面上的多个客户端
  10. 孤立的云支持
  11. 测试
  12. 欢乐
  13. 齐压
  14. 剧作家
  15. 故事书
  16. 发展
  17. 我该怎么安排?
  18. 捐款准则
  19. 释放
  20. 我和谁说话?

特性GateJs 客户端

Statsig js-lite客户端的地图集包.

使用量

import FeatureGateJsClient from '@atlaskit/feature-gate-js-client';

这个仓库是干什么的?

Js客户端覆盖前端功能门使用大小写. 这个客户端是模拟靴子陷阱 特性门值来自后端,不接收活更新.

客户用户

安装

客户可以从国家防范机制档案库中调取.

yarn add @atlaskit/feature-gate-js-client

初始化

客户端在尝试使用前必须初始化,否则会出错.

初始化客户有三种方式:

1. 默认初始化机制

这将通过调用特性旗服务来初始化客户端 (单位:千美元)fx3 请检查url=值 (帮助)),并用返回的值将客户端拖入。 如果 客户端以任何理由未能初始化, 包括获取时间超过2秒 值,将使用默认值.

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
    PerimeterType,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.initialize(
        {
            // This is an fx3 api key used to fetch the feature flag values.
            // Supported keys found at go/fx3/resources/api-keys
            apiKey: 'client-test',
            // This is the environment that you are operating in, targeting rules can target specific environments
            environment: FeatureGateEnvironment.Production,
            // This will be used to filter data from Statsig to only one target app.
            // View [doc](https://hello.atlassian.net/wiki/spaces/MEASURE/pages/2955970231/How-to+Use+TargetApps+in+Statsig)
            // for details on using targetApp.
            targetApp: 'jira_web',
            // [Optional] Default is 2000ms
            // This is the fetch timeout used for requests to feature-flag-service to get values to bootstrap the client.
            // The higher this value the longer your application will need to wait to render if you block on client initialization
            // Too low and your application will be more likely to fallback on default values
            fetchTimeoutMs: 1000,
            // [Optional] Default is false
            // This is a boolean to indicate whether to use the `gateway/api` url for the request to feature flag service.
            // Note that this option takes precendence over the environment and perimeter options in building the url.
            // To be used for applications with strict cross-origin policies, as it will keep all requests to the same origin.
            useGatewayUrl: true,
            // [Optional] Default is false
            // Whether to include flags served by the Feature Flag Platform (FFP). When true, values are fetched from the
            // feature-flag-service `/api/v1/evalFlags` endpoint instead of `/api/v2/frontend/experimentValues`.
            // Each flag is then served by the platform the service assigns it to. When false, FFP is treated as disabled.
            includeFfpFlags: false,
            // [Optional] Must be one of the strings from the exported enum PerimeterType.
            // If provided, will build base url for the `feature-flag-service` based on environment and perimeter type, and
            // will disable all logging to Statsig in perimeters where it is prohibited..
            perimeter: PerimeterType.FEDRAMP_MODERATE,
        },
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that can be used for targeting and will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
    );
} catch (err) {
    console.error('Failed to initialize FeatureGates client.', err);
}

如果您的应用程序有登录流程或其他机制,使用户能够 在会话中更改,然后可以使用 updateUser 方法应用此更改。 这个 此方法的签名几乎与 initialize,但仅需要选项 用于获取新的一组值.

重要性:调用这种方法将完全重新启用客户端并使用一对新的旗帜. 完成后,您需要重新发送整个页面,以确保所有东西都能接上 新旗帜值 。 您应该避免频繁使用它,因为它对用户有影响 经历.

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
    PerimeterType,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.updateUser(
        {
            // This is an fx3 api key used to fetch the feature flag values.
            // Supported keys found at go/fx3/resources/api-keys
            apiKey: 'client-test',
            // This is the environment that you are operating in, targeting rules can target specific environments
            environment: FeatureGateEnvironment.Production,
            // [Optional] Default is 2000ms
            // This is the fetch timeout used for requests to feature-flag-service to get values to bootstrap the client.
            fetchTimeoutMs: 1000,
            // [Optional] Default is false
            // This is a boolean to indicate whether to use the `gateway/api` url for the request to feature flag service.
            // Note that this option takes precendence over the environment and perimeter options in building the url.
            // To be used for applications with strict cross-origin policies, as it will keep all requests to the same origin.
            useGatewayUrl: true,
            // [Optional] Default is false
            // Whether to include flags served by the Feature Flag Platform (FFP). When true, values are fetched from the
            // feature-flag-service `/api/v1/evalFlags` endpoint instead of `/api/v2/frontend/experimentValues`.
            // Each flag is then served by the platform the service assigns it to. When false, FFP is treated as disabled.
            includeFfpFlags: false,
            // [Optional] Default is COMMERCIAL. Must be one of the values from the exported enum PerimeterType.
            // If provided, will build base url for the `feature-flag-service` based on environment and perimeter type, and
            // will disable all logging to Statsig in perimeters where it is prohibited.
            perimeter: PerimeterType.FEDRAMP_MODERATE,
        },
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that can be used for targeting and will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
    );
} catch (err) {
    console.error('Failed to update the FeatureGates user.', err);
}

2. 从价值入手

您必须使用我们一个包装后端客户端获取自己的值( 也可以在此找到 ) repo)并提供给此前端客户端

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.initializeFromValues(
        {
            // [Optional] This should come directly from a backend or service from the Statsig.getClientInitializeResponse(user) call
            // Or supplied from the statsig UI
            // Should be provided if it is available. It is optional so initialisation can still occur if the request to fetch the key fails
            // If not provided, a default string will be used but exposure event data will not be sent back to Statsig
            sdkKey: 'client-test',
            // This is the environment that you are operating in, targeting rules can target specific environments
            environment: FeatureGateEnvironment.Production,
            // This will be used to filter config data relevant to the listed products
            products: [FeatureGateProducts.Jira],
        },
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
        // This should come directly from a backend or service from the Statsig.getClientInitializeResponse(user) call
        initializeValues,
    );
} catch (err) {
    console.error('Failed to initialize FeatureGates client.', err);
}

如果您的应用程序有登录流程或其他机制,使用户能够 在会话中更改,然后可以使用 updateUserWithValues 方法应用此更改. 这种方法的签名几乎与 initializeFromValues,但是它没有 需要任何选项.

重要性:调用这种方法将完全重新启用客户端并使用一对新的旗帜. 完成后,您需要重新发送整个页面,以确保所有东西都能接上 新旗帜值 。 您应该避免频繁使用它,因为它对用户有影响 经历.

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.updateWithValues(
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
        // This should come directly from a backend or service from the Statsig.getClientInitializeResponse(user) call
        initializeValues,
    );
} catch (err) {
    console.error('Failed to update FeatureGates user.', err);
}

如果在初始化过程中有任何问题,那么客户端将会被置于一种总是模式中 返回默认值,并返回被拒绝的许诺。 你就能抓住这个被拒的承诺 如果您希望记录自己的日志和参数,或者您希望停止申请 装入默认值.

FeatureGates 客户端只有一次实例,所以只有第一个初始化的呼叫才会开始 初始化 。 任何后续的呼唤,都会还原现有的第一个承诺 初始化, 参数值将被忽略 。 为了确认客户是否 已经开始初始化,你可以打电话 FeatureGates.initializeCalled()。 。 。 .

3. 使用提供者初始化

此初始化使用提供方的操作来获取客户端 sdk 关键值和实验值.

支助提供者有:

  • @atlaskit/feature-gate-single-fetch-provider
  • @atlaskit/feature-gate-polling-provider
import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
    PerimeterType,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.initializeWithProvider(
        {
            // This is an fx3 api key used to fetch the feature flag values.
            // Supported keys found at go/fx3/resources/api-keys
            apiKey: 'client-test',
            // This is the environment that you are operating in, targeting rules can target specific environments
            environment: FeatureGateEnvironment.Production,
            // This will be used to filter data from Statsig to only one target app.
            // View [doc](https://hello.atlassian.net/wiki/spaces/MEASURE/pages/2955970231/How-to+Use+TargetApps+in+Statsig)
            // for details on using targetApp.
            targetApp: 'jira_web',
            // [Optional] Must be one of the strings from the exported enum PerimeterType.
            // If provided, will build base url for the `feature-flag-service` based on environment and perimeter type, and
            // will disable all logging to Statsig in perimeters where it is prohibited..
            perimeter: PerimeterType.FEDRAMP_MODERATE,
        },
        new Provider(/* ... */),
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that can be used for targeting and will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
    );
} catch (err) {
    console.error('Failed to initialize FeatureGates client.', err);
}

如果您的应用程序有登录流程或其他机制,使用户能够 在会话中更改,然后可以使用 updateUserWithProvider 方法应用此更改. 这种方法将使用相同的提供者和选项 initializeWithProvider这需要 新用户的标识符和自定义属性。 与网络有关,它会 用于获取新的一组值.

重要性:调用这种方法将完全重新启用客户端并使用一对新的旗帜. 完成后,您需要重新发送整个页面,以确保所有东西都能接上 新旗帜值 。 您应该避免频繁使用它,因为它对用户有影响 经历.

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.updateUserWithProvider(
        {
            // These are expected identifiers, you must provide them if they are relevant to your product and will be added to exposures events
            analyticsAnonymousId: '<analyticsAnonymousId>',
            atlassianAccountId: '<aaid>',
            atlassianOrgId: '<orgid>',
            tenantId: '<tenantid>',
            transactionAccountId: '<transactionAccountId>',
            trelloUserId: '<trelloUserId>',
            trelloWorkspaceId: '<trelloWorkspaceId>',
        },
        {
            // These are additional custom attributes that can be used for targeting and will be added to exposure events
            exampleCustomAttribute: '<attributeValue>',
        },
    );
} catch (err) {
    console.error('Failed to update the FeatureGates user.', err);
}

特性旗子平台值

在从Statsig向地标旗平台迁移的过程中,旗帜由一个平台服务 或别. 与 includeFfpFlags: true, (中文(简体) ), initialize 财务报告和审定财务报表 updateUser 获取特性旗 服务 /api/v1/evalFlags 结束点, 将它们分割并返回 { statsig, ffp }因此,每个 旗帜键出现在一个平台下。 没有它,只获取 Statsig 值和 FFP 被视为残疾。 客户端读取 FFP 的密钥(通过 @atlaskit/flag-client) 当最新的FFFP 值包含它,而 Statsig 则不包含; 评估 API 不改变 :

  • checkGate 读取 FFP 布尔旗.
  • getExperiment 编号 : getExperimentValue 将 FFP JSON 对象旗读作实验参数。 任意 其他FFP旗是一面平整的 Statsig 动态配置,所以用 value 参数,用于 实例 getExperimentValue('example.flag', 'value', 'default')。 。 。 .
  • 局部的覆被仍然优先,地层总是由Statsig服务.
  • FFP 曝光遥测在联邦RAMP中以及何时停止使用 disableAllLogging 已经设定.

从数值初始化或更新时,通过 ffp 作为服务响应的成员 可选最后一个参数 initializeFromValues 编号 : updateUserWithValues,或作为 ffp 在一个 Provider是因为 getExperimentValues 结果。 在省略后,Statsig为每一面旗帜服务. 过 不变: requestContext 需要,没有它,FFP对用户没有任何好处.

答复还有: status 每个平台: OK, (中文(简体) ), DISABLED (故意不使用)或 UNAVAILABLE (无法评价). 客户端只使用平台的值 OK, (中文(简体) ), 所以只使用不健康平台的旗帜 返回他们的代码默认值; 当没有FFP时, 该服务为仍在从Statsig迁移的旗帜服务. initialize 财务报告和审定财务报表 updateUser 获取一次。 虽然至少有一个平台 OK,或者两者都不使用,它们就会解决;当一个平台 无法使用(或既不使用),客户端登录外部生产警告并发送 degraded featureGatesClientValues 操作活动 statsigStatus, (中文(简体) ), ffpStatus 财务报告和审定财务报表 trigger 属性。 当没有平台时 OK 一个是 UNAVAILABLE (例如,Statsig为 无法使用,且 FFP 已禁用),没有值可使用,因此拒绝任何失败 获取 : initialize 仍然启动 Statsig 没有值,所以评价返回默认值,以及 updateUser 保存上一个用户的值。 供应商可以报告其价值的状况 返回通过 status 区域。 投票服务商再次打来 当平台是 UNAVAILABLE (大约30秒后,退到它的投票间隔), 但不是为了 DISABLED,并保留最后一个 OK 无法打开的平台的值 恢复状态 它用它通常的回放来重复一个没有可用平台的响应,就像5xx一样. 这个 除非用户更改,否则不重试408和429以外的4xx响应.

评价

为了评估一个大门:

import FeatureGates from '@atlaskit/feature-gate-js-client';

// Note: this checkGate call will automatically fire an exposure event
if (FeatureGates.checkGate('gateName')) {
    // do something here
}

为了评估一项实验:

import FeatureGates from '@atlaskit/feature-gate-js-client';

// Note: this call will automatically fire an exposure event
if (FeatureGates.getExperimentValue('myExperiment', 'myBooleanParameter', false)) {
    // do something here
}

为了使用更复杂的实验配置:

import FeatureGates from '@atlaskit/feature-gate-js-client';

// You can provide an optional function like this to reject any incoming values that don't meet your expectations.
// If this function does not pass, the default value will be returned instead.
const isHexCode = (value: unknown) =>
    typeof value === 'string' && value.startsWith('#') && value.length === 7;

// Note: this call will automatically fire an exposure event. You can provide "fireExposureEvent: false" in the options if you wish to suppress it.
const buttonColor: string = FeatureGates.getExperimentValue(
    'myExperiment',
    'myButtonColorStringParameter',
    '#000000',
    {
        typeGuard: isHexCode,
    },
);

新建只使用FFP的旗帜与迁移的旗帜

旗帜分为两组,而产品则从Statsig移动到地物旗平台(FFP):

旗帜读出来为什么
新旗帜,只在FFP中创建FeatureGates.ffpClient它在斯达西格不存在.
原已存在的Statsig旗,其中一面被迁移到FFPcheckGate, (中文(简体) ), getExperiment, (中文(简体) ), getExperimentValue它们从Feature Flag Service分配给它的任何平台提供每个密钥.

读取新的只使用 FFP 的旗帜, 其输入方法为 FeatureGates.ffpClient,这是 FlagClient 联 合 国 @atlaskit/flag-client 此软件包管理 :

import FeatureGates from '@atlaskit/feature-gate-js-client';
import type { EvaluationDetails } from '@atlaskit/flag-client/types';

const enabled = FeatureGates.ffpClient?.getBooleanValue('my-new-flag', false) ?? false;
const limit = FeatureGates.ffpClient?.getNumberValue('my-new-limit', 10) ?? 10;
const theme = FeatureGates.ffpClient?.getObjectValue('my-new-theme', { color: 'blue' }) ?? {
    color: 'blue',
};

// To log the exposure later, for example when the user sees the feature:
const details: EvaluationDetails<boolean> | undefined = FeatureGates.ffpClient?.getBooleanDetails(
    'my-new-flag',
    false,
    { disableExposureLogging: true },
);
if (details) {
    FeatureGates.ffpClient?.logExposure(details);
}
  • ffpClient 实值 undefined 直到一个初始化方法被调用。 之后就一样了 包括横跨 updateUser 打电话.
  • 在FFP值到达之前,当服务不为用户使用FFP时,请读回 默认你通过.
  • 本地覆盖( O)overrideGate, (中文(简体) ), overrideConfig, (中文(简体) ), setOverrides)不适用.
  • FFP 曝光遥测在联邦RAMP中以及何时停止使用 disableAllLogging 已经设定.
  • FfpEvaluationClient,类型 ffpClient,从 @atlaskit/feature-gate-js-client/ffp/types使用的方法类型(EvaluationDetails, (中文(简体) ), EvaluationOptions 和其余的)来自 @atlaskit/flag-client/types,所以添加 @atlaskit/flag-client 作为导入它们的依赖.

继续读取已有的 Statsig 旗 checkGate 或者说 getExperimentValue 当它是 迁移。 不要切换到 ffpClient数字 : ffpClient 仅服务 FFP 值,因此返回 默认任何用户 Statsig 仍然为旗帜服务 。 相反,不要只读FFP的旗帜 与 checkGate 或者说 getExperimentValue: 它们将 FFP 值映射到 Statsig 形状( 见 特性旗子平台值和正在退休 斯达西格.

方法 ffpClient 符合 FlagClient,所以一旦迁移完成,代码: 读取 ffpClient 可以移动到一个 FlagClient 从 @atlaskit/flag-client 而不改变它的读数.

曝光事件日志

曝光事件进行分批处理,并每10秒被送往Statsig. Statsig 的活动域名 looking API 被一些广告屏蔽器所屏蔽,所以默认情况下我们将通过这些请求代理 xp.atlassian.com 减少接触损失.

订阅

要订阅更改的大门。 当检查门值改变时, 调用会调用 .

import FeatureGates from '@atlaskit/feature-gate-js-client';

const unsubscribe = FeatureGates.onGateUpdated('gateName', () => {});

// To unsubscribe
unsubscribe();

要订阅对实验值的修改。 当实验值值时, 回调将被调用 变化.

import FeatureGates from '@atlaskit/feature-gate-js-client';

const unsubscribe = FeatureGates.onExperimentValueUpdated(
    'myExperiment',
    'myButtonColorStringParameter',
    '#000000',
    () => {},
    {
        typeGuard: isHexCode,
    },
);

// To unsubscribe
unsubscribe();

订阅客户端更新的新的一组值,无论其基础是什么 价值观已经改变.

import FeatureGates from '@atlaskit/feature-gate-js-client';

// Note: The callback will be called whenever a new set of values is set even if none of the values in the set have changed.
const unsubscribe = FeatureGates.onAnyUpdated(() => {});

// To unsubscribe
unsubscribe();

基于文件的持久覆盖

对于没有浏览器本地Storage的 CLI 工具和本地开发环境,您可以使用 FilePersistentOverrideAdapter。这允许您对文件系统上的文件坚持特性标记覆盖.

不要用这个包 在丛生的背景 - 那个 FilePersistentOverrideAdapter 设计对象仅为CLI工具和当地发展环境. 它不会在浏览器环境中正常工作,并可能造成出错.

import { FilePersistentOverrideAdapter } from '@atlaskit/feature-gate-js-client/file-persistent-override-adapter';
import { FeatureGateClient } from '@atlaskit/feature-gate-js-client/client';

// Create the file override adapter with a path where overrides will be stored
const overrideAdapter = new FilePersistentOverrideAdapter('/path/to/overrides.json');

// Create a client instance with the adapter
const client = new FeatureGateClient({
  overrideAdapter: overrideAdapter
});


await client.initialize({
  // ... standard initialization options
});

与浏览器本地Storage适配器不同,文件适配器会创建任何存储文件的必要目录,并妥善处理文件系统错误.

单一页面上的多个客户端

通常我们不允许在单一页面上多处使用功能门客户端,因为 客户端会发出很多重的网络呼叫 可能会对运行产生巨大影响 如果许多客户在一页上存在的话。 但是,在有些情况下 将客户端隔离到产品上是绝对必要的. 我们揭发了一种方法 来抓新客户 而不是用静态方法处理此案.

由于所涉业绩问题 请在使用前询问我们 独立客户端 这样我们可以检查是否有其他的解决方案不会影响 并让我们知道需要分开客户的情况.

import FeatureGateClient from '@atlaskit/feature-gate-js-client/client';

const featureGates = new FeatureGateClient();

// Usage is the same as the static API
await featureGates.initialize({
    // ...
});
featureGates.checkGate('my-gate');

孤立的云支持

客户端支持孤立的云环境,并能够 init 在IC环境中使用FFS. SDK 自动解决右边 stargate api url 基于用户提供的环境和窗口位置.

如果用户正在运行这个客户端作为服务器代码的一部分,并作为后端 SDK 并想要直接与 FFS 交谈,他们需要通过 isolationContextId 这是可选的 输入 ClientOptions。 。 。 . SDK将根据 isolationContextId sDK将从中进行初始化.

import FeatureGates, {
    FeatureGateEnvironment,
    FeatureGateProducts,
    PerimeterType,
} from '@atlaskit/feature-gate-js-client';

try {
    await FeatureGates.initialize(
        {
            // This is an fx3 api key used to fetch the feature flag values.
            // Supported keys found at go/fx3/resources/api-keys
            apiKey: 'client-test',
            isolationContextId: 'ic-7bf',
        });
} catch (err) {
    console.error('Failed to initialize FeatureGates client.', err);
}

测试

欢乐

测试初始化状态

您可以通过模拟返回值来测试各种初始化状态 initialize 财务报告和审定财务报表 updateUser。请注意,你还需要嘲笑 initializeCalled,因为这通常由 真实 initialize 函数.

import FeatureGates from '@atlaskit/feature-gate-js-client';

jest.mock('@atlaskit/feature-gate-js-client', () => ({
    ...jest.requireActual('@atlaskit/feature-gate-js-client'),
    initializeCalled: jest.fn(),
    initialize: jest.fn(),
    updateUser: jest.fn(),
}));

const MockedFeatureGates = jest.mocked(FeatureGates);

describe('with successful initialization', () => {
    beforeEach(() => {
        MockedFeatureGates.initializeCalled.mockReturnValue(true);
        MockedFeatureGates.initialize.mockResolvedValue();
        MockedFeatureGates.updateUser.mockResolvedValue();
    });

    afterEach(() => jest.resetAllMocks());
});

describe('with failed initialization', () => {
    beforeEach(() => {
        MockedFeatureGates.initializeCalled.mockReturnValue(true);
        MockedFeatureGates.initialize.mockRejectedValue();
        MockedFeatureGates.updateUser.mockRejectedValue();
    });

    afterEach(() => jest.resetAllMocks());
});

describe('with pending initialization', () => {
    // These can be called within your tests transition from the pending
    // initialization state into a successful/failed state.
    let resolveInitPromise;
    let rejectInitPromise;
    beforeEach(() => {
        const initPromise = new Promise((resolve, reject) => {
            resolveInitPromise = resolve;
            rejectInitPromise = reject;
        });
        MockedFeatureGates.initializeCalled.mockReturnValue(true);
        MockedFeatureGates.initialize.mockReturnValue(initPromise);
        MockedFeatureGates.updateUser.mockReturnValue(initPromise);
    });

    afterEach(() => jest.resetAllMocks());
});

超过数值

在 Jest 测试中,可以有两种方法可以覆盖值:

  1. 使用模拟
  2. 使用内置覆盖方法

使用模拟

import FeatureGates, { DynamicConfig, EvaluationReason } from '@atlaskit/feature-gate-js-client';

jest.mock('@atlaskit/feature-gate-js-client', () => ({
    ...jest.requireActual('@atlaskit/feature-gate-js-client'),
    getExperiment: jest.fn(),
    checkGate: jest.fn(),
}));

const MockedFeatureGates = jest.mocked(FeatureGates);

describe('with mocked experiments and gates', () => {
    beforeEach(() => {
        const overrides = {
            configs: {
                'example-experiment': {
                    cohort: 'variation',
                },
            },
            gates: {
                'example-gate': true,
            },
        };

        MockedFeatureGates.getExperiment.mockImplementation((experimentName) => {
            const values = overrides.configs[experimentName] || {};
            return new DynamicConfig(experimentName, values, 'rule-id', {
                time: Date.now(),
                reason: EvaluationReason.LocalOverride,
            });
        });

        MockedFeatureGates.checkGate.mockImplementation((gateName, defaultValue) => {
            return overrides.gates[gateName] || defaultValue;
        });
    });

    afterEach(() => jest.resetAllMocks());
});

使用覆盖方法

import FeatureGates, { FeatureGateEnvironment } from '@atlaskit/feature-gate-js-client';

describe('with overridden gates and experiments', () => {
    beforeAll(async () => {
        // setOverrides can only be called if the client is _actually_ initialized. You can't mock the initialization, you will have invoke it properly.
        await FeatureGates.initializeWithValues(
            {
                environment: FeatureGateEnvironment.Development,
                sdkKey: 'client-default-key',
                localMode: true,
            },
            {},
            {},
        );
    });

    beforeEach(() => {
        const overrides = {
            configs: {
                'example-experiment': {
                    cohort: 'variation',
                },
            },
            gates: {
                'example-gate': true,
            },
        };

        FeatureGates.setOverrides(overrides);
    });

    afterEach(() => FeatureGates.clearAllOverrides());
});

齐压

超过数值

这个 .visit 命令在 Cypress 中创建了新窗口, 并使用它自己的特异功能Gates 实例, 所以您 将无法简单地导入模块并应用分贝.

// ❌ This will not work!

import FeatureGates, { LocalOverrides } from '@atlaskit/feature-gate-js-client';

const overrides: LocalOverrides = {
    configs: {
        'example-experiment': {
            cohort: 'variation',
        },
    },
    gates: {
        'example-gate': true,
    },
};

// These interact with the FeatureGates instance that your test framework is running in
cy.stub(
    FeatureGates,
    'checkGate',
    (gateName, defaultValue) => overrides.gates[gateName] || defaultValue,
);

cy.stub(FeatureGates, 'getExperiment', (experimentName) => {
    const values = overrides.configs[experimentName] || {};
    return new DynamicConfig(experimentName, values, 'rule-id', {
        time: Date.now(),
        reason: EvaluationReason.LocalOverride,
    });
});

// This will creates a new window, with its own FeatureGates instance.
cy.visit('http://localhost:3000/');

// The test feature will not exist since the stubs don't exist on the visited window.
cy.get('#test-feature').dblclick();

相反,您需要获得存在于生成窗口上的客户端的引用,以及 应用您的功能代替.

我们暴露了一个 window.__FEATUREGATES_JS__ 变量,将包含 窗户.

// ✅ Do this instead!

import { LocalOverrides } from '@atlaskit/feature-gate-js-client';

const overrides: LocalOverrides = {
    configs: {
        'example-experiment': {
            cohort: 'variation',
        },
    },
    gates: {
        'example-gate': true,
    },
};

cy.visit('http://localhost:3001', {
    // onLoad provides a reference to the generated window, and it is also only invoked when all scripts have finished loading, so the __FEATUREGATES_JS__
    // variable will be available at this point.
    onLoad: (contentWindow) => {
        const FeatureGates = contentWindow.__FEATUREGATES_JS__;

        // Note that the client would not have been initialized by this point, so we can't use the override* or setOverrides methods.
        // We also don't want to wait until the initialization completes, because then the page may have already started to render without these overrides.
        cy.stub(
            FeatureGates,
            'checkGate',
            (gateName, defaultValue) => overrides.gates[gateName] || defaultValue,
        );

        cy.stub(FeatureGates, 'getExperiment', (experimentName) => {
            const values = overrides.configs[experimentName] || {};
            return new DynamicConfig(experimentName, values, {
                time: Date.now(),
                reason: EvaluationReason.LocalOverride,
            });
        });
    },
});

您也可以设置您自己的自定义命令, 它会听下一个 window:load 要完成的事件 在任何页面访问前都可以引用的同样内容:

import { LocalOverrides } from '@atlaskit/feature-gate-js-client';

Cypress.Commands.add('featureGateOverrides', (overrides: LocalOverrides) => {
    // Use cy.once instead of cy.on so that this only affects the next visit.
    cy.once('window:load', (contentWindow) => {
        const FeatureGates = contentWindow.__FEATUREGATES_JS__;

        cy.stub(
            FeatureGates,
            'checkGate',
            (gateName, defaultValue) => overrides?.gates?.[gateName] || defaultValue,
        );

        cy.stub(FeatureGates, 'getExperiment', (experimentName) => {
            const values = overrides?.configs?.[experimentName] || {};

            return new DynamicConfig(experimentName, values, {
                time: Date.now(),
                reason: EvaluationReason.LocalOverride,
            });
        });
    });
});

// Once the command has been added, you can use it in any of your tests like this
cy.featureGateOverrides({
    configs: {
        'example-experiment': {
            cohort: 'variation',
        },
    },
    gates: {
        'example-gate': true,
    },
}).visit('http://localhost:3001');

剧作家

与 Cypress 类似, Playwright 要求您在页面加载后应用您的根. 我们可以利用 页面。添加Init脚本 钩入这个生命周期,以便支起 window.__FEATUREGATES_JS__。 。 。 .

超过数值

import {
  LocalOverrides,
  DynamicConfig,
  EvaluationReason,
} from '@atlaskit/feature-gate-js-client';
import { Page } from '@playwright/test';

export async function withFeatureGateOverrides(
  page: Page,
  overrides: LocalOverrides,
) {
  await page.addInitScript(
    ({ overridesSerialized, localOverrideReason }) => {
      const FeatureGates = {
        initialize: () => Promise.resolve(),
        checkGate: (gateName: string) => {
          return overridesSerialized.gates?.[gateName] ?? false;
        },

        getExperiment: (experimentName: string) => {
          const values = overridesSerialized.configs?.[experimentName] || {};
          return new DynamicConfig(experimentName, values, 'rule-id', {
            time: Date.now(),
            reason: localOverrideReason,
          });
        },
      };

      window.__FEATUREGATES_JS__ = {
        ...window.__FEATUREGATES_JS__,
        ...FeatureGates,
      };
    },
    {
      overridesSerialized: overrides,
      localOverrideReason: EvaluationReason.LocalOverride,
    },
  );
}

以下是消费这个的例子:

import { expect, test } from '@playwright/test';
import { withFeatureGateOverrides } from './utils/statsig';

test.describe('Playwright test suite', () => {
  test.beforeEach(async ({ page }) => {
    await withFeatureGateOverrides(page, {
      configs: {},
      gates: {
        your_feature_gate: true,
      },
      layers: {},
    });
  });

  test('should pass', async ({ page }) => {
    await expect(1).toEqual(1);
  });
});

故事书

超过数值

故事本上没有任何嘲弄或取笑API,但你可以使用 override* 财务报告和审定财务报表 setOverrides 用于替换此客户端的方法.

请注意,在调用这些方法之前,客户必须先初始化,而且 每本故事手册被卸载后,需要清除,因为这些内容将持续 (原始内容存档于2018-10-21). localStorage.

设置最简单的方法是使用 FeatureGatesInitializationWithDefaults 构成部分 我们的反应 SDK (@atlassian/feature-gates-react与 overrides 道具集,因为这个管理 初始化和清理给你。 请看 组成部分文件 页:1 更多信息.

发展

我该怎么安排?

  • 设立情况概述
    • 此 repo 软件包使用纱线
    • 运行 yarn install 在根目录中设置您 git 钩.
    • 为了开始运行 yarn 以安装依赖关系
  • 如何运行测试
    • 为了运行所有测试 只需运行 yarn test packages/measurement/feature-gate-js-client 从平台目录
    • 为了在运行开发时在监视模式下运行滑稽测试 yarn test:jest --watch
    • 注:您可能需要运行 yarn build @atlaskit/feature-gate-js-client 创建版本.ts 一些测试所需的文件

捐款准则

  • 所有新逻辑都必须测试
    • 无需直接通过 Statsig APIs
    • 参数转换算作新逻辑
  • 代码审查
    • 更改必须经过拉动请求才能合并
  • 其他准则

释放

这个包是AFP单列波的一部分. 使用 yarn changeset 承诺. 文档

我和谁说话?

这回波是实验平台团队拥有的 伸手去 {\fn方正粗倩简体\fs12\an8\1chffff00\b0}帮助巫师 如果你需要的话 一只手。 一只手。 .

版本与发布记录

@atlaskit/feature-gate-js-client 共发布 65 个版本,首次发布于 2024/03/01;过去 12 个月发布了 16 个版本。

版本发布日期距今
8.0.0latest2026/11/025 天前
7.1.02026/10/299 天前
7.0.02026/09/241 个月前
6.0.22026/08/033 个月前
6.0.12026/07/153 个月前
6.0.02026/06/164 个月前

关于 @atlaskit/feature-gate-js-client 的常见问题

@atlaskit/feature-gate-js-client 是什么?

Statsig js-lite客户端的地图集包.

如何安装 @atlaskit/feature-gate-js-client?

在项目目录运行 npm install @atlaskit/feature-gate-js-client,或使用 pnpm add / yarn add / bun add。

@atlaskit/feature-gate-js-client 支持 TypeScript 吗?

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

@atlaskit/feature-gate-js-client 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@atlaskit/feature-gate-js-client 可以商用吗?

@atlaskit/feature-gate-js-client 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@atlaskit/feature-gate-js-client 的下载量有多少?

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

@atlaskit/feature-gate-js-client 还在维护吗?

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