Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sdk/appconfiguration/app-configuration/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Features Added

- Support snapshot referece.
Copy link
Preview

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'referece' to 'reference'.

Suggested change
- Support snapshot referece.
- Support snapshot reference.

Copilot uses AI. Check for mistakes.

- New types for SnapshotReference - `ConfigurationSetting<SnapshotReferenceValue>` and `ConfigurationSetting<SecretReferenceValue>`
- Upon using `getConfigurationSetting`(or add/update), use `parseSnapshotReference` methods to access the properties(to translate `ConfigurationSetting` into the types above).
Comment on lines +8 to +9
Copy link
Preview

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second type should be ConfigurationSetting<SnapshotReferenceValue> instead of ConfigurationSetting<SecretReferenceValue> as this is documenting snapshot reference support, not secret reference.

Suggested change
- New types for SnapshotReference - `ConfigurationSetting<SnapshotReferenceValue>` and `ConfigurationSetting<SecretReferenceValue>`
- Upon using `getConfigurationSetting`(or add/update), use `parseSnapshotReference` methods to access the properties(to translate `ConfigurationSetting` into the types above).
- New type for SnapshotReference - `ConfigurationSetting<SnapshotReferenceValue>`
- Upon using `getConfigurationSetting`(or add/update), use `parseSnapshotReference` methods to access the properties (to translate `ConfigurationSetting` into the type above).

Copilot uses AI. Check for mistakes.

- Helper method `isSnapshotReference` checks the contentType and return boolean values.

### Breaking Changes

### Bugs Fixed
Expand Down
2 changes: 1 addition & 1 deletion sdk/appconfiguration/app-configuration/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "js",
"TagPrefix": "js/appconfiguration/app-configuration",
"Tag": "js/appconfiguration/app-configuration_bdaf29d71a"
"Tag": "js/appconfiguration/app-configuration_257c4f0dd5"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface AddConfigurationSettingOptions extends OperationOptions {
}

// @public
export type AddConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue = string> = ConfigurationSettingParam<T>;
export type AddConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string> = ConfigurationSettingParam<T>;

// @public
export interface AddConfigurationSettingResponse extends ConfigurationSetting, SyncTokenHeaderField, HttpResponseField<SyncTokenHeaderField> {
Expand All @@ -27,7 +27,7 @@ export interface AddConfigurationSettingResponse extends ConfigurationSetting, S
export class AppConfigurationClient {
constructor(connectionString: string, options?: AppConfigurationClientOptions);
constructor(endpoint: string, tokenCredential: TokenCredential, options?: AppConfigurationClientOptions);
addConfigurationSetting(configurationSetting: AddConfigurationSettingParam | AddConfigurationSettingParam<FeatureFlagValue> | AddConfigurationSettingParam<SecretReferenceValue>, options?: AddConfigurationSettingOptions): Promise<AddConfigurationSettingResponse>;
addConfigurationSetting(configurationSetting: AddConfigurationSettingParam | AddConfigurationSettingParam<FeatureFlagValue> | AddConfigurationSettingParam<SecretReferenceValue> | AddConfigurationSettingParam<SnapshotReferenceValue>, options?: AddConfigurationSettingOptions): Promise<AddConfigurationSettingResponse>;
archiveSnapshot(name: string, options?: UpdateSnapshotOptions): Promise<UpdateSnapshotResponse>;
beginCreateSnapshot(snapshot: SnapshotInfo, options?: CreateSnapshotOptions): Promise<SimplePollerLike<OperationState<CreateSnapshotResponse>, CreateSnapshotResponse>>;
beginCreateSnapshotAndWait(snapshot: SnapshotInfo, options?: CreateSnapshotOptions): Promise<CreateSnapshotResponse>;
Expand All @@ -40,7 +40,7 @@ export class AppConfigurationClient {
listRevisions(options?: ListRevisionsOptions): PagedAsyncIterableIterator<ConfigurationSetting, ListRevisionsPage, PageSettings>;
listSnapshots(options?: ListSnapshotsOptions): PagedAsyncIterableIterator<ConfigurationSnapshot, ListSnapshotsPage, PageSettings>;
recoverSnapshot(name: string, options?: UpdateSnapshotOptions): Promise<UpdateSnapshotResponse>;
setConfigurationSetting(configurationSetting: SetConfigurationSettingParam | SetConfigurationSettingParam<FeatureFlagValue> | SetConfigurationSettingParam<SecretReferenceValue>, options?: SetConfigurationSettingOptions): Promise<SetConfigurationSettingResponse>;
setConfigurationSetting(configurationSetting: SetConfigurationSettingParam | SetConfigurationSettingParam<FeatureFlagValue> | SetConfigurationSettingParam<SecretReferenceValue> | SetConfigurationSettingParam<SnapshotReferenceValue>, options?: SetConfigurationSettingOptions): Promise<SetConfigurationSettingResponse>;
setReadOnly(id: ConfigurationSettingId, readOnly: boolean, options?: SetReadOnlyOptions): Promise<SetReadOnlyResponse>;
updateSyncToken(syncToken: string): void;
}
Expand All @@ -52,7 +52,7 @@ export interface AppConfigurationClientOptions extends CommonClientOptions {
}

// @public
export type ConfigurationSetting<T extends string | FeatureFlagValue | SecretReferenceValue = string> = ConfigurationSettingParam<T> & {
export type ConfigurationSetting<T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string> = ConfigurationSettingParam<T> & {
isReadOnly: boolean;
lastModified?: Date;
};
Expand All @@ -65,7 +65,7 @@ export interface ConfigurationSettingId {
}

// @public
export type ConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue = string> = ConfigurationSettingId & {
export type ConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string> = ConfigurationSettingId & {
contentType?: string;
tags?: {
[propertyName: string]: string;
Expand Down Expand Up @@ -198,6 +198,9 @@ export function isFeatureFlag(setting: ConfigurationSetting): setting is Configu
// @public
export function isSecretReference(setting: ConfigurationSetting): setting is ConfigurationSetting & Required<Pick<ConfigurationSetting, "value">>;

// @public
export function isSnapshotReference(setting: ConfigurationSetting): setting is ConfigurationSetting & Required<Pick<ConfigurationSetting, "value">>;

// @public
export enum KnownAppConfigAudience {
AzureChina = "https://appconfig.azure.cn",
Expand Down Expand Up @@ -302,6 +305,9 @@ export function parseFeatureFlag(setting: ConfigurationSetting): ConfigurationSe
// @public
export function parseSecretReference(setting: ConfigurationSetting): ConfigurationSetting<SecretReferenceValue>;

// @public
export function parseSnapshotReference(setting: ConfigurationSetting): ConfigurationSetting<SnapshotReferenceValue>;

// @public
export interface RetryOptions {
maxRetries?: number;
Expand All @@ -321,7 +327,7 @@ export interface SetConfigurationSettingOptions extends HttpOnlyIfUnchangedField
}

// @public
export type SetConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue = string> = ConfigurationSettingParam<T>;
export type SetConfigurationSettingParam<T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string> = ConfigurationSettingParam<T>;

// @public
export interface SetConfigurationSettingResponse extends ConfigurationSetting, SyncTokenHeaderField, HttpResponseField<SyncTokenHeaderField> {
Expand Down Expand Up @@ -354,6 +360,14 @@ export interface SnapshotInfo {
};
}

// @public
export const snapshotReferenceContentType = "application/json; profile=\"https://azconfig.io/mime-profiles/snapshot-ref\"; charset=utf-8";

// @public
export interface SnapshotReferenceValue {
snapshotName: string;
}

// @public
export interface SnapshotResponse extends ConfigurationSnapshot, SyncTokenHeaderField {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import {
import { AppConfiguration } from "./generated/src/appConfiguration.js";
import type { FeatureFlagValue } from "./featureFlag.js";
import type { SecretReferenceValue } from "./secretReference.js";
import type { SnapshotReferenceValue } from "./snapshotReference.js";
import { appConfigKeyCredentialPolicy } from "./appConfigCredential.js";
import { tracingClient } from "./internal/tracing.js";
import { logger } from "./logger.js";
Expand Down Expand Up @@ -225,7 +226,8 @@ export class AppConfigurationClient {
configurationSetting:
| AddConfigurationSettingParam
| AddConfigurationSettingParam<FeatureFlagValue>
| AddConfigurationSettingParam<SecretReferenceValue>,
| AddConfigurationSettingParam<SecretReferenceValue>
| AddConfigurationSettingParam<SnapshotReferenceValue>,
options: AddConfigurationSettingOptions = {},
): Promise<AddConfigurationSettingResponse> {
return tracingClient.withSpan(
Expand Down Expand Up @@ -655,7 +657,8 @@ export class AppConfigurationClient {
configurationSetting:
| SetConfigurationSettingParam
| SetConfigurationSettingParam<FeatureFlagValue>
| SetConfigurationSettingParam<SecretReferenceValue>,
| SetConfigurationSettingParam<SecretReferenceValue>
| SetConfigurationSettingParam<SnapshotReferenceValue>,
options: SetConfigurationSettingOptions = {},
): Promise<SetConfigurationSettingResponse> {
return tracingClient.withSpan(
Expand Down
6 changes: 6 additions & 0 deletions sdk/appconfiguration/app-configuration/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ export {
secretReferenceContentType,
SecretReferenceValue,
} from "./secretReference.js";
export {
isSnapshotReference,
parseSnapshotReference,
snapshotReferenceContentType,
SnapshotReferenceValue,
} from "./snapshotReference.js";
21 changes: 20 additions & 1 deletion sdk/appconfiguration/app-configuration/src/internal/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import type {
} from "../generated/src/models/index.js";
import type { SecretReferenceValue } from "../secretReference.js";
import { SecretReferenceHelper, secretReferenceContentType } from "../secretReference.js";
import type { SnapshotReferenceValue } from "../snapshotReference.js";
import { SnapshotReferenceHelper, snapshotReferenceContentType } from "../snapshotReference.js";
import { isDefined } from "@azure/core-util";
import { logger } from "../logger.js";
import type { OperationOptions } from "@azure/core-client";
Expand Down Expand Up @@ -299,6 +301,19 @@ function isConfigSettingWithSecretReferenceValue(
);
}

/**
* @internal
*/
function isConfigSettingWithSnapshotReferenceValue(
setting: any,
): setting is ConfigurationSetting<SnapshotReferenceValue> {
return (
setting.contentType === snapshotReferenceContentType &&
isDefined(setting.value) &&
typeof setting.value !== "string"
);
}

/**
* @internal
*/
Expand Down Expand Up @@ -326,7 +341,8 @@ export function serializeAsConfigurationSettingParam(
setting:
| ConfigurationSettingParam
| ConfigurationSettingParam<FeatureFlagValue>
| ConfigurationSettingParam<SecretReferenceValue>,
| ConfigurationSettingParam<SecretReferenceValue>
| ConfigurationSettingParam<SnapshotReferenceValue>,
): ConfigurationSettingParam {
if (isSimpleConfigSetting(setting)) {
return setting as ConfigurationSettingParam;
Expand All @@ -338,6 +354,9 @@ export function serializeAsConfigurationSettingParam(
if (isConfigSettingWithSecretReferenceValue(setting)) {
return SecretReferenceHelper.toConfigurationSettingParam(setting);
}
if (isConfigSettingWithSnapshotReferenceValue(setting)) {
return SnapshotReferenceHelper.toConfigurationSettingParam(setting);
}
} catch (error: any) {
return setting as ConfigurationSettingParam;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,12 @@ export type JsonFeatureFlagValue = {
export interface JsonSecretReferenceValue {
uri: string;
}

// snapshot reference

/**
* @internal
*/
export interface JsonSnapshotReferenceValue {
snapshot_name: string;
}
9 changes: 5 additions & 4 deletions sdk/appconfiguration/app-configuration/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { CompatResponse } from "@azure/core-http-compat";
import type { FeatureFlagValue } from "./featureFlag.js";
import type { CommonClientOptions, OperationOptions } from "@azure/core-client";
import type { SecretReferenceValue } from "./secretReference.js";
import type { SnapshotReferenceValue } from "./snapshotReference.js";
import type {
SnapshotComposition,
ConfigurationSettingsFilter,
Expand Down Expand Up @@ -73,7 +74,7 @@ export interface ConfigurationSettingId {
* Necessary fields for updating or creating a new configuration setting
*/
export type ConfigurationSettingParam<
T extends string | FeatureFlagValue | SecretReferenceValue = string,
T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string,
> = ConfigurationSettingId & {
/**
* The content type of the setting's value
Expand Down Expand Up @@ -103,7 +104,7 @@ export type ConfigurationSettingParam<
* its etag, whether it is currently readOnly and when it was last modified.
*/
export type ConfigurationSetting<
T extends string | FeatureFlagValue | SecretReferenceValue = string,
T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string,
> = ConfigurationSettingParam<T> & {
/**
* Whether or not the setting is read-only
Expand Down Expand Up @@ -150,14 +151,14 @@ export interface HttpResponseField<HeadersT> {
* Parameters for adding a new configuration setting
*/
export type AddConfigurationSettingParam<
T extends string | FeatureFlagValue | SecretReferenceValue = string,
T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string,
> = ConfigurationSettingParam<T>;

/**
* Parameters for creating or updating a new configuration setting
*/
export type SetConfigurationSettingParam<
T extends string | FeatureFlagValue | SecretReferenceValue = string,
T extends string | FeatureFlagValue | SecretReferenceValue | SnapshotReferenceValue = string,
> = ConfigurationSettingParam<T>;

/**
Expand Down
91 changes: 91 additions & 0 deletions sdk/appconfiguration/app-configuration/src/snapshotReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import type { ConfigurationSetting, ConfigurationSettingParam } from "./models.js";
import type { JsonSnapshotReferenceValue } from "./internal/jsonModels.js";
import { logger } from "./logger.js";

/**
* content-type for the snapshot reference.
*/
export const snapshotReferenceContentType =
'application/json; profile="https://azconfig.io/mime-profiles/snapshot-ref"; charset=utf-8';

/**
* Necessary fields for updating or creating a new snapshot reference.
*/
export interface SnapshotReferenceValue {
/**
* snapshot name.
*/
snapshotName: string;
}

/**
* @internal
*/
export const SnapshotReferenceHelper = {
/**
* Takes the SnapshotReference (JSON) and returns a ConfigurationSetting (with the props encodeed in the value).
Copy link
Preview

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'encodeed' to 'encoded'.

Suggested change
* Takes the SnapshotReference (JSON) and returns a ConfigurationSetting (with the props encodeed in the value).
* Takes the SnapshotReference (JSON) and returns a ConfigurationSetting (with the props encoded in the value).

Copilot uses AI. Check for mistakes.

*/
toConfigurationSettingParam: (
snapshotReference: ConfigurationSettingParam<SnapshotReferenceValue>,
): ConfigurationSettingParam => {
logger.info("Encoding SnapshotReference value in a ConfigurationSetting:", snapshotReference);
if (!snapshotReference.value) {
logger.error(`SnapshotReference has an unexpected value`, snapshotReference);
throw new TypeError(`SnapshotReference has an unexpected value - ${snapshotReference.value}`);
}

const jsonSnapshotReferenceValue: JsonSnapshotReferenceValue = {
snapshot_name: snapshotReference.value.snapshotName,
};

const configSetting = {
...snapshotReference,
value: JSON.stringify(jsonSnapshotReferenceValue),
};
return configSetting;
},
};

/**
* Takes the ConfigurationSetting as input and returns the ConfigurationSetting<SnapshotReferenceValue> by parsing the value string.
*/
export function parseSnapshotReference(
setting: ConfigurationSetting,
): ConfigurationSetting<SnapshotReferenceValue> {
logger.info(
"[parseSnapshotReference] Parsing the value to return the SnapshotReferenceValue",
setting,
);
if (!isSnapshotReference(setting)) {
logger.error("Invalid SnapshotReference input", setting);
throw TypeError(
`Setting with key ${setting.key} is not a valid SnapshotReference, make sure to have the correct content-type and a valid non-null value.`,
);
}

const jsonSnapshotReferenceValue = JSON.parse(setting.value) as JsonSnapshotReferenceValue;

const snapshotReference: ConfigurationSetting<SnapshotReferenceValue> = {
...setting,
value: { snapshotName: jsonSnapshotReferenceValue.snapshot_name },
};
return snapshotReference;
}

/**
* Lets you know if the ConfigurationSetting is a snapshot reference.
*
* [Checks if the content type is snapshotReferenceContentType `"application/json; profile=\"https://azconfig.io/mime-profiles/snapshot-ref\"; charset=utf-8"`]
*/
export function isSnapshotReference(
setting: ConfigurationSetting,
): setting is ConfigurationSetting & Required<Pick<ConfigurationSetting, "value">> {
return (
setting &&
setting.contentType === snapshotReferenceContentType &&
typeof setting.value === "string"
);
}
Loading