GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

azure-appconfiguration-ts

Build applications using Azure App Configuration SDK for JavaScript (@azure/app-configuration). Use when working with configuration settings, feature flags, Key Vault references, dynamic refresh, or centralized configuration management.

Ciza · 0 points · 25 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-typescript_skills_azure-appconfiguration-ts-e58528d.zip · 2 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/azure-appconfiguration-ts
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Azure App Configuration SDK for TypeScript

Centralized configuration management with feature flags and dynamic refresh.

Installation

# Low-level CRUD SDK
npm install @azure/app-configuration @azure/identity

# High-level provider (recommended for apps)
npm install @azure/app-configuration-provider @azure/identity

# Feature flag management
npm install @microsoft/feature-management

Environment Variables

AZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io
# OR
AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production

Authentication

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

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();

const client = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  credential
);

// Connection string
const client2 = new AppConfigurationClient(
  process.env.AZURE_APPCONFIG_CONNECTION_STRING!
);

CRUD Operations

Create/Update Settings

// 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 });

Read Settings

// 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}`);
}

Delete Settings

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

Lock/Unlock (Read-Only)

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

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

App Configuration Provider

Load Configuration

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

const appConfig = await load(
  process.env.AZURE_APPCONFIG_ENDPOINT!,
  new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]}),
  {
    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);

Dynamic Refresh

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();
});

Key Vault References

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

// Secrets are automatically resolved
const dbPassword = appConfig.get("database:password");

Feature Flags

Create Feature Flag (Low-Level)

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

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"],
});

Snapshots

// 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" }],
});

Labels

// 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);
}

Key Types

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
Files (skills)
  • SKILL.md 8.7 KB
    ---
    name: azure-appconfiguration-ts
    description: Build applications using Azure App Configuration SDK for JavaScript (@azure/app-configuration). Use when working with configuration settings, feature flags, Key Vault references, dynamic refresh, or centralized configuration management.
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
      package: '@azure/app-configuration'
    ---
    
    # Azure App Configuration SDK for TypeScript
    
    Centralized configuration management with feature flags and dynamic refresh.
    
    ## Installation
    
    ```bash
    # Low-level CRUD SDK
    npm install @azure/app-configuration @azure/identity
    
    # High-level provider (recommended for apps)
    npm install @azure/app-configuration-provider @azure/identity
    
    # Feature flag management
    npm install @microsoft/feature-management
    ```
    
    ## Environment Variables
    
    ```bash
    AZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io
    # OR
    AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
    AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
    ```
    
    ## Authentication
    
    ```typescript
    import { AppConfigurationClient } from "@azure/app-configuration";
    import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
    // const credential = new ManagedIdentityCredential();
    
    const client = new AppConfigurationClient(
      process.env.AZURE_APPCONFIG_ENDPOINT!,
      credential
    );
    
    // Connection string
    const client2 = new AppConfigurationClient(
      process.env.AZURE_APPCONFIG_CONNECTION_STRING!
    );
    ```
    
    ## CRUD Operations
    
    ### 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 });
    ```
    
    ### 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}`);
    }
    ```
    
    ### Delete Settings
    
    ```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);
    ```
    
    ## 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({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]}),
      {
        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);
    ```
    
    ### 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();
    });
    ```
    
    ### Key Vault References
    
    ```typescript
    const appConfig = await load(endpoint, credential, {
      selectors: [{ keyFilter: "app:*" }],
      keyVaultOptions: {
        credential: new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]}),
        secretRefreshIntervalInMs: 7200_000,  // 2 hours
      },
    });
    
    // Secrets are automatically resolved
    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);
    ```
    
    ### 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"],
    });
    ```
    
    ## 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" }],
    });
    ```
    
    ## 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);
    }
    ```
    
    ## 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";
    ```
    
    ## 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
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related