azure-appconfiguration-ts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Azure App Configuration SDK for TypeScript

适用于TypeScript的Azure App Configuration SDK

Centralized configuration management with feature flags and dynamic refresh.
支持功能标志与动态刷新的集中式配置管理。

Installation

安装

bash
undefined
bash
undefined

Low-level CRUD SDK

底层CRUD SDK

npm install @azure/app-configuration @azure/identity
npm install @azure/app-configuration @azure/identity

High-level provider (recommended for apps)

高层级Provider(推荐用于应用程序)

npm install @azure/app-configuration-provider @azure/identity
npm install @azure/app-configuration-provider @azure/identity

Feature flag management

功能标志管理

npm install @microsoft/feature-management
undefined
npm install @microsoft/feature-management
undefined

Environment Variables

环境变量

bash
AZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io
bash
AZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io

OR

AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
undefined
AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
undefined

Authentication

身份验证

typescript
import { AppConfigurationClient } from "@azure/app-configuration";
import { DefaultAzureCredential } from "@azure/identity";

// DefaultAzureCredential (recommended)
const client = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  new DefaultAzureCredential()
);

// Connection string
const client2 = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_CONNECTION_STRING!
);
typescript
import { AppConfigurationClient } from "@azure/app-configuration";
import { DefaultAzureCredential } from "@azure/identity";

// DefaultAzureCredential(推荐使用)
const client = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  new DefaultAzureCredential()
);

// 连接字符串
const client2 = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_CONNECTION_STRING!
);

CRUD Operations

CRUD操作

Create/Update Settings

创建/更新配置项

typescript
// Add new (fails if exists)
await client.addConfigurationSetting({
  key: "app:settings:message",
  value: "Hello World",
  label: "production",
  contentType: "text/plain",
  tags: { environment: "prod" },
});

// Set (create or update)
await client.setConfigurationSetting({
  key: "app:settings:message",
  value: "Updated value",
  label: "production",
});

// Update with optimistic concurrency
const existing = await client.getConfigurationSetting({ key: "myKey" });
existing.value = "new value";
await client.setConfigurationSetting(existing, { onlyIfUnchanged: true });
typescript
// 添加新配置项(若已存在则失败)
await client.addConfigurationSetting({
  key: "app:settings:message",
  value: "Hello World",
  label: "production",
  contentType: "text/plain",
  tags: { environment: "prod" },
});

// 设置配置项(创建或更新)
await client.setConfigurationSetting({
  key: "app:settings:message",
  value: "Updated value",
  label: "production",
});

// 乐观并发更新
const existing = await client.getConfigurationSetting({ key: "myKey" });
existing.value = "new value";
await client.setConfigurationSetting(existing, { onlyIfUnchanged: true });

Read Settings

读取配置项

typescript
// Get single setting
const setting = await client.getConfigurationSetting({
  key: "app:settings:message",
  label: "production",  // optional
});
console.log(setting.value);

// List with filters
const settings = client.listConfigurationSettings({
  keyFilter: "app:*",
  labelFilter: "production",
});

for await (const setting of settings) {
  console.log(`${setting.key}: ${setting.value}`);
}
typescript
// 获取单个配置项
const setting = await client.getConfigurationSetting({
  key: "app:settings:message",
  label: "production",  // 可选
});
console.log(setting.value);

// 带过滤器的列表查询
const settings = client.listConfigurationSettings({
  keyFilter: "app:*",
  labelFilter: "production",
});

for await (const setting of settings) {
  console.log(`${setting.key}: ${setting.value}`);
}

Delete Settings

删除配置项

typescript
await client.deleteConfigurationSetting({
  key: "app:settings:message",
  label: "production",
});
typescript
await client.deleteConfigurationSetting({
  key: "app:settings:message",
  label: "production",
});

Lock/Unlock (Read-Only)

锁定/解锁(只读状态)

typescript
// Lock
await client.setReadOnly({ key: "myKey", label: "prod" }, true);

// Unlock
await client.setReadOnly({ key: "myKey", label: "prod" }, false);
typescript
// 锁定
await client.setReadOnly({ key: "myKey", label: "prod" }, true);

// 解锁
await client.setReadOnly({ key: "myKey", label: "prod" }, false);

App Configuration Provider

App Configuration Provider

Load Configuration

加载配置

typescript
import { load } from "@azure/app-configuration-provider";
import { DefaultAzureCredential } from "@azure/identity";

const appConfig = await load(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  new DefaultAzureCredential(),
  {
    selectors: [
      { keyFilter: "app:*", labelFilter: "production" },
    ],
    trimKeyPrefixes: ["app:"],
  }
);

// Map-style access
const value = appConfig.get("settings:message");

// Object-style access
const config = appConfig.constructConfigurationObject({ separator: ":" });
console.log(config.settings.message);
typescript
import { load } from "@azure/app-configuration-provider";
import { DefaultAzureCredential } from "@azure/identity";

const appConfig = await load(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  new DefaultAzureCredential(),
  {
    selectors: [
      { keyFilter: "app:*", labelFilter: "production" },
    ],
    trimKeyPrefixes: ["app:"],
  }
);

// 映射式访问
const value = appConfig.get("settings:message");

// 对象式访问
const config = appConfig.constructConfigurationObject({ separator: ":" });
console.log(config.settings.message);

Dynamic Refresh

动态刷新

typescript
const appConfig = await load(endpoint, credential, {
  selectors: [{ keyFilter: "app:*" }],
  refreshOptions: {
    enabled: true,
    refreshIntervalInMs: 30_000,  // 30 seconds
  },
});

// Trigger refresh (non-blocking)
appConfig.refresh();

// Listen for refresh events
const disposer = appConfig.onRefresh(() => {
  console.log("Configuration refreshed!");
});

// Express middleware pattern
app.use((req, res, next) => {
  appConfig.refresh();
  next();
});
typescript
const appConfig = await load(endpoint, credential, {
  selectors: [{ keyFilter: "app:*" }],
  refreshOptions: {
    enabled: true,
    refreshIntervalInMs: 30_000,  // 30秒
  },
});

// 触发刷新(非阻塞)
appConfig.refresh();

// 监听刷新事件
const disposer = appConfig.onRefresh(() => {
  console.log("配置已刷新!");
});

// Express中间件模式
app.use((req, res, next) => {
  appConfig.refresh();
  next();
});

Key Vault References

Key Vault引用

typescript
const appConfig = await load(endpoint, credential, {
  selectors: [{ keyFilter: "app:*" }],
  keyVaultOptions: {
    credential: new DefaultAzureCredential(),
    secretRefreshIntervalInMs: 7200_000,  // 2 hours
  },
});

// Secrets are automatically resolved
const dbPassword = appConfig.get("database:password");
typescript
const appConfig = await load(endpoint, credential, {
  selectors: [{ keyFilter: "app:*" }],
  keyVaultOptions: {
    credential: new DefaultAzureCredential(),
    secretRefreshIntervalInMs: 7200_000,  // 2小时
  },
});

// 密钥会自动解析
const dbPassword = appConfig.get("database:password");

Feature Flags

功能标志

Create Feature Flag (Low-Level)

创建功能标志(底层方式)

typescript
import {
  featureFlagPrefix,
  featureFlagContentType,
  FeatureFlagValue,
  ConfigurationSetting,
} from "@azure/app-configuration";

const flag: ConfigurationSetting<FeatureFlagValue> = {
  key: `${featureFlagPrefix}Beta`,
  contentType: featureFlagContentType,
  value: {
    id: "Beta",
    enabled: true,
    description: "Beta feature",
    conditions: {
      clientFilters: [
        {
          name: "Microsoft.Targeting",
          parameters: {
            Audience: {
              Users: ["user@example.com"],
              Groups: [{ Name: "beta-testers", RolloutPercentage: 50 }],
              DefaultRolloutPercentage: 0,
            },
          },
        },
      ],
    },
  },
};

await client.addConfigurationSetting(flag);
typescript
import {
  featureFlagPrefix,
  featureFlagContentType,
  FeatureFlagValue,
  ConfigurationSetting,
} from "@azure/app-configuration";

const flag: ConfigurationSetting<FeatureFlagValue> = {
  key: `${featureFlagPrefix}Beta`,
  contentType: featureFlagContentType,
  value: {
    id: "Beta",
    enabled: true,
    description: "Beta feature",
    conditions: {
      clientFilters: [
        {
          name: "Microsoft.Targeting",
          parameters: {
            Audience: {
              Users: ["user@example.com"],
              Groups: [{ Name: "beta-testers", RolloutPercentage: 50 }],
              DefaultRolloutPercentage: 0,
            },
          },
        },
      ],
    },
  },
};

await client.addConfigurationSetting(flag);

Load and Evaluate Feature Flags

加载并评估功能标志

typescript
import { load } from "@azure/app-configuration-provider";
import {
  ConfigurationMapFeatureFlagProvider,
  FeatureManager,
} from "@microsoft/feature-management";

const appConfig = await load(endpoint, credential, {
  featureFlagOptions: {
    enabled: true,
    selectors: [{ keyFilter: "*" }],
    refresh: {
      enabled: true,
      refreshIntervalInMs: 30_000,
    },
  },
});

const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
const featureManager = new FeatureManager(featureProvider);

// Simple check
const isEnabled = await featureManager.isEnabled("Beta");

// With targeting context
const isEnabledForUser = await featureManager.isEnabled("Beta", {
  userId: "user@example.com",
  groups: ["beta-testers"],
});
typescript
import { load } from "@azure/app-configuration-provider";
import {
  ConfigurationMapFeatureFlagProvider,
  FeatureManager,
} from "@microsoft/feature-management";

const appConfig = await load(endpoint, credential, {
  featureFlagOptions: {
    enabled: true,
    selectors: [{ keyFilter: "*" }],
    refresh: {
      enabled: true,
      refreshIntervalInMs: 30_000,
    },
  },
});

const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
const featureManager = new FeatureManager(featureProvider);

// 简单检查
const isEnabled = await featureManager.isEnabled("Beta");

// 结合目标上下文检查
const isEnabledForUser = await featureManager.isEnabled("Beta", {
  userId: "user@example.com",
  groups: ["beta-testers"],
});

Snapshots

快照

typescript
// Create snapshot
const snapshot = await client.beginCreateSnapshotAndWait({
  name: "release-v1.0",
  retentionPeriod: 2592000,  // 30 days
  filters: [{ keyFilter: "app:*", labelFilter: "production" }],
});

// Get snapshot
const snap = await client.getSnapshot("release-v1.0");

// List settings in snapshot
const settings = client.listConfigurationSettingsForSnapshot("release-v1.0");
for await (const setting of settings) {
  console.log(`${setting.key}: ${setting.value}`);
}

// Archive/recover
await client.archiveSnapshot("release-v1.0");
await client.recoverSnapshot("release-v1.0");

// Load from snapshot (provider)
const config = await load(endpoint, credential, {
  selectors: [{ snapshotName: "release-v1.0" }],
});
typescript
// 创建快照
const snapshot = await client.beginCreateSnapshotAndWait({
  name: "release-v1.0",
  retentionPeriod: 2592000,  // 30天
  filters: [{ keyFilter: "app:*", labelFilter: "production" }],
});

// 获取快照
const snap = await client.getSnapshot("release-v1.0");

// 列出快照中的配置项
const settings = client.listConfigurationSettingsForSnapshot("release-v1.0");
for await (const setting of settings) {
  console.log(`${setting.key}: ${setting.value}`);
}

// 归档/恢复快照
await client.archiveSnapshot("release-v1.0");
await client.recoverSnapshot("release-v1.0");

// 从快照加载配置(Provider方式)
const config = await load(endpoint, credential, {
  selectors: [{ snapshotName: "release-v1.0" }],
});

Labels

标签

typescript
// Create settings with labels
await client.setConfigurationSetting({
  key: "database:host",
  value: "dev-db.example.com",
  label: "development",
});

await client.setConfigurationSetting({
  key: "database:host",
  value: "prod-db.example.com",
  label: "production",
});

// Filter by label
const prodSettings = client.listConfigurationSettings({
  keyFilter: "*",
  labelFilter: "production",
});

// No label (null label)
const noLabelSettings = client.listConfigurationSettings({
  labelFilter: "\0",
});

// List available labels
for await (const label of client.listLabels()) {
  console.log(label.name);
}
typescript
// 创建带标签的配置项
await client.setConfigurationSetting({
  key: "database:host",
  value: "dev-db.example.com",
  label: "development",
});

await client.setConfigurationSetting({
  key: "database:host",
  value: "prod-db.example.com",
  label: "production",
});

// 按标签过滤
const prodSettings = client.listConfigurationSettings({
  keyFilter: "*",
  labelFilter: "production",
});

// 无标签(空标签)
const noLabelSettings = client.listConfigurationSettings({
  labelFilter: "\0",
});

// 列出可用标签
for await (const label of client.listLabels()) {
  console.log(label.name);
}

Key Types

密钥类型

typescript
import {
  AppConfigurationClient,
  ConfigurationSetting,
  FeatureFlagValue,
  SecretReferenceValue,
  featureFlagPrefix,
  featureFlagContentType,
  secretReferenceContentType,
  ListConfigurationSettingsOptions,
} from "@azure/app-configuration";

import { load } from "@azure/app-configuration-provider";

import {
  FeatureManager,
  ConfigurationMapFeatureFlagProvider,
} from "@microsoft/feature-management";
typescript
import {
  AppConfigurationClient,
  ConfigurationSetting,
  FeatureFlagValue,
  SecretReferenceValue,
  featureFlagPrefix,
  featureFlagContentType,
  secretReferenceContentType,
  ListConfigurationSettingsOptions,
} from "@azure/app-configuration";

import { load } from "@azure/app-configuration-provider";

import {
  FeatureManager,
  ConfigurationMapFeatureFlagProvider,
} from "@microsoft/feature-management";

Best Practices

最佳实践

  1. Use provider for apps -
    @azure/app-configuration-provider
    for runtime config
  2. Use low-level for management -
    @azure/app-configuration
    for CRUD operations
  3. Enable refresh - For dynamic configuration updates
  4. Use labels - Separate configurations by environment
  5. Use snapshots - For immutable release configurations
  6. Sentinel pattern - Use a sentinel key to trigger full refresh
  7. RBAC roles -
    App Configuration Data Reader
    for read-only access
  1. 为应用使用Provider - 使用
    @azure/app-configuration-provider
    处理运行时配置
  2. 使用底层SDK进行管理操作 - 使用
    @azure/app-configuration
    执行CRUD操作
  3. 启用刷新功能 - 用于动态更新配置
  4. 使用标签 - 按环境分离配置
  5. 使用快照 - 用于不可变的发布配置
  6. 哨兵模式 - 使用哨兵密钥触发全量刷新
  7. RBAC角色 - 为只读访问使用
    App Configuration Data Reader
    角色