diff --git a/sdk/keyvault/generate.ts b/sdk/keyvault/generate.ts new file mode 100644 index 000000000000..8e745b15c748 --- /dev/null +++ b/sdk/keyvault/generate.ts @@ -0,0 +1,86 @@ +#!/usr/bin/env node + +const { execSync } = require("child_process"); +const fs = require("fs"); +const path = require("path"); + +// Helper to execute shell commands and log output +function execCommand(command) { + try { + execSync(command, { stdio: "inherit" }); + } catch (error) { + console.error(`Command failed: ${command}`); + process.exit(1); + } +} + +console.log("Setting up the environment..."); + +// Workaround for src-folder support in emitter: +// End state: src/generated/* contains generated code (instead of src/generated/src/*) + +// Step 1: Remove all files in src/generated/* +execCommand("rm -rf src/generated/*"); + +// Step 2: Copy tsp-location.yaml to src/generated +execCommand("cp tsp-location.yaml src/generated"); + +// Step 3: Run tsp-client command +// emitter-option as a workaround for https://github.com/Azure/azure-rest-api-specs/issues/31610 +execCommand(`tsp-client update -d -o src/generated --emitter-options generateMetadata=false`); +// execCommand( +// "tsp-client update -d -o src/generated --tsp-config ~/workspace/azure-rest-api-specs/specification/keyvault/Security.KeyVault.Keys/tspconfig.yaml --local-spec-repo ~/workspace/azure-rest-api-specs/specification/keyvault/Security.KeyVault.Keys --repo ~/workspace/azure-rest-api-specs --commit 9561bad7d2eed94cc91aa6164d3721b8aa8699fe --emitter-options generateMetadata=false" +// ); + +// Step 4: Move generated/src/* files to generated until src-folder is supported +execCommand("mv src/generated/src/* src/generated/"); + +// Step 5: Remove generated/src +execCommand("rm -rf src/generated/src"); + +// Step 6: Remove tsp-location.yaml from generated folder +execCommand("rm src/generated/tsp-location.yaml"); + +// Step 7: Read and update package.json +console.log("Updating package.json dependencies..."); +const packageJsonPath = path.resolve("./package.json"); +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); + +// Remove dependency on @azure/core-client and add @azure-rest/core-client +delete packageJson.dependencies["@azure/core-client"]; +packageJson.dependencies["@azure-rest/core-client"] = "^2.0.0"; + +// Write updated package.json back to disk +fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8"); + +// Generated code changes +// Workaround for https://github.com/Azure/autorest.typescript/pull/2135/files +const modelsPath = path.resolve("./src/generated/models/models.ts"); +let modelsContent = fs.readFileSync(modelsPath, "utf8"); +modelsContent = modelsContent + .replace( + /created: !item\["created"\] \? item\["created"\] : new Date\(item\["created"\]\),/g, + 'created: !item["created"] ? item["created"] : new Date(item["created"] * 1000),' + ) + .replace( + /updated: !item\["updated"\] \? item\["updated"\] : new Date\(item\["updated"\]\),/g, + 'updated: !item["updated"] ? item["updated"] : new Date(item["updated"] * 1000),' + ) + .replace( + /notBefore: !item\["nbf"\] \? item\["nbf"\] : new Date\(item\["nbf"\]\),/g, + 'notBefore: !item["nbf"] ? item["nbf"] : new Date(item["nbf"] * 1000),' + ) + .replace( + /expires: !item\["exp"\] \? item\["exp"\] : new Date\(item\["exp"\]\),/g, + 'expires: !item["exp"] ? item["exp"] : new Date(item["exp"] * 1000),' + ) + .replace( + /nbf: !item\["notBefore"\] \? item\["notBefore"\] : item\["notBefore"\].getTime\(\),/g, + 'nbf: !item["notBefore"] ? item["notBefore"] : item["notBefore"].getTime() / 1000,' + ) + .replace( + /exp: !item\["expires"\] \? item\["expires"\] : item\["expires"\].getTime\(\),/g, + 'exp: !item["expires"] ? item["expires"] : item["expires"].getTime() / 1000,' + ); + +fs.writeFileSync(modelsPath, modelsContent, "utf8"); diff --git a/sdk/keyvault/keyvault-secrets/assets.json b/sdk/keyvault/keyvault-secrets/assets.json index 44c71e5137c0..472309c51db0 100644 --- a/sdk/keyvault/keyvault-secrets/assets.json +++ b/sdk/keyvault/keyvault-secrets/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "js", "TagPrefix": "js/keyvault/keyvault-secrets", - "Tag": "js/keyvault/keyvault-secrets_41e131fba8" + "Tag": "js/keyvault/keyvault-secrets_946a3d52fe" } diff --git a/sdk/keyvault/keyvault-secrets/package.json b/sdk/keyvault/keyvault-secrets/package.json index d99b8051e92e..6e32030f22c9 100644 --- a/sdk/keyvault/keyvault-secrets/package.json +++ b/sdk/keyvault/keyvault-secrets/package.json @@ -55,7 +55,7 @@ "test:node": "npm run clean && npm run build:test && npm run unit-test:node", "unit-test": "npm run unit-test:node && npm run unit-test:browser", "unit-test:browser": "echo skipped", - "unit-test:node": "dev-tool run test:vitest", + "unit-test:node": "dev-tool run test:vitest -- --test-timeout 250000", "update-snippets": "echo skipped" }, "sideEffects": false, @@ -92,9 +92,9 @@ } }, "dependencies": { + "@azure-rest/core-client": "^2.0.0", "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", "@azure/core-http-compat": "^2.0.1", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.1.1", diff --git a/sdk/keyvault/keyvault-secrets/review/keyvault-secrets.api.md b/sdk/keyvault/keyvault-secrets/review/keyvault-secrets.api.md index daaffa7d8c05..e4750b8838e2 100644 --- a/sdk/keyvault/keyvault-secrets/review/keyvault-secrets.api.md +++ b/sdk/keyvault/keyvault-secrets/review/keyvault-secrets.api.md @@ -5,12 +5,12 @@ ```ts import { AzureLogger } from '@azure/logger'; -import type * as coreClient from '@azure/core-client'; +import type * as coreClient from '@azure-rest/core-client'; import type { ExtendedCommonClientOptions } from '@azure/core-http-compat'; import { PagedAsyncIterableIterator } from '@azure/core-paging'; import { PageSettings } from '@azure/core-paging'; import { PollerLike } from '@azure/core-lro'; -import { PollOperationState } from '@azure/core-lro'; +import type { PollOperationState } from '@azure/core-lro'; import type { TokenCredential } from '@azure/core-auth'; // @public diff --git a/sdk/keyvault/keyvault-secrets/src/generated/api/index.ts b/sdk/keyvault/keyvault-secrets/src/generated/api/index.ts new file mode 100644 index 000000000000..388b0cb02e58 --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/api/index.ts @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { + createKeyVault, + KeyVaultContext, + KeyVaultClientOptionalParams, +} from "./keyVaultContext.js"; +export { + setSecret, + deleteSecret, + updateSecret, + getSecret, + getSecrets, + getSecretVersions, + getDeletedSecrets, + getDeletedSecret, + purgeDeletedSecret, + recoverDeletedSecret, + backupSecret, + restoreSecret, +} from "./operations.js"; +export { + SetSecretOptionalParams, + DeleteSecretOptionalParams, + UpdateSecretOptionalParams, + GetSecretOptionalParams, + GetSecretsOptionalParams, + GetSecretVersionsOptionalParams, + GetDeletedSecretsOptionalParams, + GetDeletedSecretOptionalParams, + PurgeDeletedSecretOptionalParams, + RecoverDeletedSecretOptionalParams, + BackupSecretOptionalParams, + RestoreSecretOptionalParams, +} from "./options.js"; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/api/keyVaultContext.ts b/sdk/keyvault/keyvault-secrets/src/generated/api/keyVaultContext.ts new file mode 100644 index 000000000000..026b0d3d1f3b --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/api/keyVaultContext.ts @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { logger } from "../logger.js"; +import { KnownVersions } from "../models/models.js"; +import { Client, ClientOptions, getClient } from "@azure-rest/core-client"; +import { TokenCredential } from "@azure/core-auth"; + +/** + * The key vault client performs cryptographic key operations and vault operations + * against the Key Vault service. + */ +export interface KeyVaultContext extends Client {} + +/** Optional parameters for the client. */ +export interface KeyVaultClientOptionalParams extends ClientOptions { + /** The API version to use for this operation. */ + /** Known values of {@link KnownVersions} that the service accepts. */ + apiVersion?: string; +} + +/** + * The key vault client performs cryptographic key operations and vault operations + * against the Key Vault service. + */ +export function createKeyVault( + vaultBaseUrl: string, + credential: TokenCredential, + options: KeyVaultClientOptionalParams = {}, +): KeyVaultContext { + const endpointUrl = options.endpoint ?? options.baseUrl ?? `${vaultBaseUrl}`; + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentInfo = `azsdk-js-keyvault-secrets/1.0.0-beta.1`; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-api ${userAgentInfo}` + : `azsdk-js-api ${userAgentInfo}`; + const { apiVersion: _, ...updatedOptions } = { + ...options, + userAgentOptions: { userAgentPrefix }, + loggingOptions: { logger: options.loggingOptions?.logger ?? logger.info }, + credentials: { + scopes: options.credentials?.scopes ?? [ + "https://vault.azure.net/.default", + ], + }, + }; + const clientContext = getClient(endpointUrl, credential, updatedOptions); + clientContext.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + const apiVersion = options.apiVersion ?? "7.6-preview.1"; + clientContext.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version")) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } + + return next(req); + }, + }); + return clientContext; +} diff --git a/sdk/keyvault/keyvault-secrets/src/generated/api/operations.ts b/sdk/keyvault/keyvault-secrets/src/generated/api/operations.ts new file mode 100644 index 000000000000..cf511cd6c057 --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/api/operations.ts @@ -0,0 +1,515 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + BackupSecretOptionalParams, + KeyVaultContext as Client, + DeleteSecretOptionalParams, + GetDeletedSecretOptionalParams, + GetDeletedSecretsOptionalParams, + GetSecretOptionalParams, + GetSecretsOptionalParams, + GetSecretVersionsOptionalParams, + PurgeDeletedSecretOptionalParams, + RecoverDeletedSecretOptionalParams, + RestoreSecretOptionalParams, + SetSecretOptionalParams, + UpdateSecretOptionalParams, +} from "./index.js"; +import { + SecretSetParameters, + secretSetParametersSerializer, + SecretBundle, + secretBundleDeserializer, + DeletedSecretBundle, + deletedSecretBundleDeserializer, + SecretUpdateParameters, + secretUpdateParametersSerializer, + _SecretListResult, + _secretListResultDeserializer, + SecretItem, + _DeletedSecretListResult, + _deletedSecretListResultDeserializer, + DeletedSecretItem, + BackupSecretResult, + backupSecretResultDeserializer, + SecretRestoreParameters, + secretRestoreParametersSerializer, +} from "../models/models.js"; +import { + PagedAsyncIterableIterator, + buildPagedAsyncIterator, +} from "../static-helpers/pagingHelpers.js"; +import { + StreamableMethod, + PathUncheckedResponse, + createRestError, + operationOptionsToRequestParameters, +} from "@azure-rest/core-client"; + +export function _setSecretSend( + context: Client, + secretName: string, + parameters: SecretSetParameters, + options: SetSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}", secretName) + .put({ + ...operationOptionsToRequestParameters(options), + body: secretSetParametersSerializer(parameters), + }); +} + +export async function _setSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return secretBundleDeserializer(result.body); +} + +/** + * The SET operation adds a secret to the Azure Key Vault. If the named secret + * already exists, Azure Key Vault creates a new version of that secret. This + * operation requires the secrets/set permission. + */ +export async function setSecret( + context: Client, + secretName: string, + parameters: SecretSetParameters, + options: SetSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _setSecretSend(context, secretName, parameters, options); + return _setSecretDeserialize(result); +} + +export function _deleteSecretSend( + context: Client, + secretName: string, + options: DeleteSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}", secretName) + .delete({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _deleteSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return deletedSecretBundleDeserializer(result.body); +} + +/** + * The DELETE operation applies to any secret stored in Azure Key Vault. DELETE + * cannot be applied to an individual version of a secret. This operation requires + * the secrets/delete permission. + */ +export async function deleteSecret( + context: Client, + secretName: string, + options: DeleteSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _deleteSecretSend(context, secretName, options); + return _deleteSecretDeserialize(result); +} + +export function _updateSecretSend( + context: Client, + secretName: string, + secretVersion: string, + parameters: SecretUpdateParameters, + options: UpdateSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}/{secret-version}", secretName, secretVersion) + .patch({ + ...operationOptionsToRequestParameters(options), + body: secretUpdateParametersSerializer(parameters), + }); +} + +export async function _updateSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return secretBundleDeserializer(result.body); +} + +/** + * The UPDATE operation changes specified attributes of an existing stored secret. + * Attributes that are not specified in the request are left unchanged. The value + * of a secret itself cannot be changed. This operation requires the secrets/set + * permission. + */ +export async function updateSecret( + context: Client, + secretName: string, + secretVersion: string, + parameters: SecretUpdateParameters, + options: UpdateSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _updateSecretSend( + context, + secretName, + secretVersion, + parameters, + options, + ); + return _updateSecretDeserialize(result); +} + +export function _getSecretSend( + context: Client, + secretName: string, + secretVersion: string, + options: GetSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}/{secret-version}", secretName, secretVersion) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _getSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return secretBundleDeserializer(result.body); +} + +/** + * The GET operation is applicable to any secret stored in Azure Key Vault. This + * operation requires the secrets/get permission. + */ +export async function getSecret( + context: Client, + secretName: string, + secretVersion: string, + options: GetSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _getSecretSend( + context, + secretName, + secretVersion, + options, + ); + return _getSecretDeserialize(result); +} + +export function _getSecretsSend( + context: Client, + options: GetSecretsOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets") + .get({ + ...operationOptionsToRequestParameters(options), + queryParameters: { maxresults: options?.maxresults }, + }); +} + +export async function _getSecretsDeserialize( + result: PathUncheckedResponse, +): Promise<_SecretListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _secretListResultDeserializer(result.body); +} + +/** + * The Get Secrets operation is applicable to the entire vault. However, only the + * base secret identifier and its attributes are provided in the response. + * Individual secret versions are not listed in the response. This operation + * requires the secrets/list permission. + */ +export function getSecrets( + context: Client, + options: GetSecretsOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => _getSecretsSend(context, options), + _getSecretsDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} + +export function _getSecretVersionsSend( + context: Client, + secretName: string, + options: GetSecretVersionsOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}/versions", secretName) + .get({ + ...operationOptionsToRequestParameters(options), + queryParameters: { maxresults: options?.maxresults }, + }); +} + +export async function _getSecretVersionsDeserialize( + result: PathUncheckedResponse, +): Promise<_SecretListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _secretListResultDeserializer(result.body); +} + +/** + * The full secret identifier and attributes are provided in the response. No + * values are returned for the secrets. This operations requires the secrets/list + * permission. + */ +export function getSecretVersions( + context: Client, + secretName: string, + options: GetSecretVersionsOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => _getSecretVersionsSend(context, secretName, options), + _getSecretVersionsDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} + +export function _getDeletedSecretsSend( + context: Client, + options: GetDeletedSecretsOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/deletedsecrets") + .get({ + ...operationOptionsToRequestParameters(options), + queryParameters: { maxresults: options?.maxresults }, + }); +} + +export async function _getDeletedSecretsDeserialize( + result: PathUncheckedResponse, +): Promise<_DeletedSecretListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _deletedSecretListResultDeserializer(result.body); +} + +/** + * The Get Deleted Secrets operation returns the secrets that have been deleted + * for a vault enabled for soft-delete. This operation requires the secrets/list + * permission. + */ +export function getDeletedSecrets( + context: Client, + options: GetDeletedSecretsOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => _getDeletedSecretsSend(context, options), + _getDeletedSecretsDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} + +export function _getDeletedSecretSend( + context: Client, + secretName: string, + options: GetDeletedSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/deletedsecrets/{secret-name}", secretName) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _getDeletedSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return deletedSecretBundleDeserializer(result.body); +} + +/** + * The Get Deleted Secret operation returns the specified deleted secret along + * with its attributes. This operation requires the secrets/get permission. + */ +export async function getDeletedSecret( + context: Client, + secretName: string, + options: GetDeletedSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _getDeletedSecretSend(context, secretName, options); + return _getDeletedSecretDeserialize(result); +} + +export function _purgeDeletedSecretSend( + context: Client, + secretName: string, + options: PurgeDeletedSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/deletedsecrets/{secret-name}", secretName) + .delete({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _purgeDeletedSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["204"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return; +} + +/** + * The purge deleted secret operation removes the secret permanently, without the + * possibility of recovery. This operation can only be enabled on a soft-delete + * enabled vault. This operation requires the secrets/purge permission. + */ +export async function purgeDeletedSecret( + context: Client, + secretName: string, + options: PurgeDeletedSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _purgeDeletedSecretSend(context, secretName, options); + return _purgeDeletedSecretDeserialize(result); +} + +export function _recoverDeletedSecretSend( + context: Client, + secretName: string, + options: RecoverDeletedSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/deletedsecrets/{secret-name}/recover", secretName) + .post({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _recoverDeletedSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return secretBundleDeserializer(result.body); +} + +/** + * Recovers the deleted secret in the specified vault. This operation can only be + * performed on a soft-delete enabled vault. This operation requires the + * secrets/recover permission. + */ +export async function recoverDeletedSecret( + context: Client, + secretName: string, + options: RecoverDeletedSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _recoverDeletedSecretSend(context, secretName, options); + return _recoverDeletedSecretDeserialize(result); +} + +export function _backupSecretSend( + context: Client, + secretName: string, + options: BackupSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/{secret-name}/backup", secretName) + .post({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _backupSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return backupSecretResultDeserializer(result.body); +} + +/** + * Requests that a backup of the specified secret be downloaded to the client. All + * versions of the secret will be downloaded. This operation requires the + * secrets/backup permission. + */ +export async function backupSecret( + context: Client, + secretName: string, + options: BackupSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _backupSecretSend(context, secretName, options); + return _backupSecretDeserialize(result); +} + +export function _restoreSecretSend( + context: Client, + parameters: SecretRestoreParameters, + options: RestoreSecretOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/secrets/restore") + .post({ + ...operationOptionsToRequestParameters(options), + body: secretRestoreParametersSerializer(parameters), + }); +} + +export async function _restoreSecretDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return secretBundleDeserializer(result.body); +} + +/** + * Restores a backed up secret, and all its versions, to a vault. This operation + * requires the secrets/restore permission. + */ +export async function restoreSecret( + context: Client, + parameters: SecretRestoreParameters, + options: RestoreSecretOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _restoreSecretSend(context, parameters, options); + return _restoreSecretDeserialize(result); +} diff --git a/sdk/keyvault/keyvault-secrets/src/generated/api/options.ts b/sdk/keyvault/keyvault-secrets/src/generated/api/options.ts new file mode 100644 index 000000000000..91653bf02ce0 --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/api/options.ts @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { OperationOptions } from "@azure-rest/core-client"; + +/** Optional parameters. */ +export interface SetSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface DeleteSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface UpdateSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface GetSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface GetSecretsOptionalParams extends OperationOptions { + /** + * Maximum number of results to return in a page. If not specified the service + * will return up to 25 results. + */ + maxresults?: number; +} + +/** Optional parameters. */ +export interface GetSecretVersionsOptionalParams extends OperationOptions { + /** + * Maximum number of results to return in a page. If not specified the service + * will return up to 25 results. + */ + maxresults?: number; +} + +/** Optional parameters. */ +export interface GetDeletedSecretsOptionalParams extends OperationOptions { + /** + * Maximum number of results to return in a page. If not specified the service + * will return up to 25 results. + */ + maxresults?: number; +} + +/** Optional parameters. */ +export interface GetDeletedSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface PurgeDeletedSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface RecoverDeletedSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface BackupSecretOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface RestoreSecretOptionalParams extends OperationOptions {} diff --git a/sdk/keyvault/keyvault-secrets/src/generated/helpers/serializerHelpers.ts b/sdk/keyvault/keyvault-secrets/src/generated/helpers/serializerHelpers.ts new file mode 100644 index 000000000000..4baaac77c8be --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/helpers/serializerHelpers.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export function serializeRecord< + T extends string | number | boolean | Date | null, + R, +>(item: Record): Record; +export function serializeRecord( + item: Record, + serializer: (item: T) => R, +): Record; +export function serializeRecord( + item: Record, + serializer?: (item: T) => R, +): Record { + return Object.keys(item).reduce( + (acc, key) => { + if (isSupportedRecordType(item[key])) { + acc[key] = item[key] as any; + } else if (serializer) { + const value = item[key]; + if (value !== undefined) { + acc[key] = serializer(value); + } + } else { + console.warn(`Don't know how to serialize ${item[key]}`); + acc[key] = item[key] as any; + } + return acc; + }, + {} as Record, + ); +} + +function isSupportedRecordType(t: any) { + return ( + ["number", "string", "boolean", "null"].includes(typeof t) || + t instanceof Date + ); +} diff --git a/sdk/keyvault/keyvault-secrets/src/generated/index.ts b/sdk/keyvault/keyvault-secrets/src/generated/index.ts index 90cbc3efaa01..1ea8e32bd36f 100644 --- a/sdk/keyvault/keyvault-secrets/src/generated/index.ts +++ b/sdk/keyvault/keyvault-secrets/src/generated/index.ts @@ -1,10 +1,42 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is regenerated. - */ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + PageSettings, + ContinuablePage, + PagedAsyncIterableIterator, +} from "./static-helpers/pagingHelpers.js"; -export * from "./models/index.js"; export { KeyVaultClient } from "./keyVaultClient.js"; +export { + SecretSetParameters, + SecretAttributes, + SecretBundle, + KeyVaultError, + ErrorModel, + DeletedSecretBundle, + SecretUpdateParameters, + SecretItem, + DeletedSecretItem, + BackupSecretResult, + SecretRestoreParameters, + KnownVersions, + KnownDeletionRecoveryLevel, + DeletionRecoveryLevel, +} from "./models/index.js"; +export { + KeyVaultClientOptionalParams, + SetSecretOptionalParams, + DeleteSecretOptionalParams, + UpdateSecretOptionalParams, + GetSecretOptionalParams, + GetSecretsOptionalParams, + GetSecretVersionsOptionalParams, + GetDeletedSecretsOptionalParams, + GetDeletedSecretOptionalParams, + PurgeDeletedSecretOptionalParams, + RecoverDeletedSecretOptionalParams, + BackupSecretOptionalParams, + RestoreSecretOptionalParams, +} from "./api/index.js"; +export { PageSettings, ContinuablePage, PagedAsyncIterableIterator }; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/keyVaultClient.ts b/sdk/keyvault/keyvault-secrets/src/generated/keyVaultClient.ts index 7a530ebe438d..97fc78674782 100644 --- a/sdk/keyvault/keyvault-secrets/src/generated/keyVaultClient.ts +++ b/sdk/keyvault/keyvault-secrets/src/generated/keyVaultClient.ts @@ -1,668 +1,224 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is regenerated. - */ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. -import * as coreClient from "@azure/core-client"; -import * as coreHttpCompat from "@azure/core-http-compat"; -import * as coreRestPipeline from "@azure/core-rest-pipeline"; -import * as Parameters from "./models/parameters.js"; -import * as Mappers from "./models/mappers.js"; import { - ApiVersion75, + createKeyVault, + KeyVaultContext, KeyVaultClientOptionalParams, + setSecret, + deleteSecret, + updateSecret, + getSecret, + getSecrets, + getSecretVersions, + getDeletedSecrets, + getDeletedSecret, + purgeDeletedSecret, + recoverDeletedSecret, + backupSecret, + restoreSecret, SetSecretOptionalParams, - SetSecretResponse, DeleteSecretOptionalParams, - DeleteSecretResponse, UpdateSecretOptionalParams, - UpdateSecretResponse, GetSecretOptionalParams, - GetSecretResponse, GetSecretsOptionalParams, - GetSecretsResponse, GetSecretVersionsOptionalParams, - GetSecretVersionsResponse, GetDeletedSecretsOptionalParams, - GetDeletedSecretsResponse, GetDeletedSecretOptionalParams, - GetDeletedSecretResponse, PurgeDeletedSecretOptionalParams, RecoverDeletedSecretOptionalParams, - RecoverDeletedSecretResponse, BackupSecretOptionalParams, - BackupSecretResponse, RestoreSecretOptionalParams, - RestoreSecretResponse, - GetSecretsNextOptionalParams, - GetSecretsNextResponse, - GetSecretVersionsNextOptionalParams, - GetSecretVersionsNextResponse, - GetDeletedSecretsNextOptionalParams, - GetDeletedSecretsNextResponse -} from "./models/index.js"; - -/** @internal */ -export class KeyVaultClient extends coreHttpCompat.ExtendedServiceClient { - apiVersion: ApiVersion75; - - /** - * Initializes a new instance of the KeyVaultClient class. - * @param apiVersion Api Version - * @param options The parameter options +} from "./api/index.js"; +import { + SecretSetParameters, + SecretBundle, + DeletedSecretBundle, + SecretUpdateParameters, + SecretItem, + DeletedSecretItem, + BackupSecretResult, + SecretRestoreParameters, +} from "./models/models.js"; +import { PagedAsyncIterableIterator } from "./static-helpers/pagingHelpers.js"; +import { Pipeline } from "@azure/core-rest-pipeline"; +import { TokenCredential } from "@azure/core-auth"; + +export { KeyVaultClientOptionalParams } from "./api/keyVaultContext.js"; + +export class KeyVaultClient { + private _client: KeyVaultContext; + /** The pipeline used by this client to make requests */ + public readonly pipeline: Pipeline; + + /** + * The key vault client performs cryptographic key operations and vault operations + * against the Key Vault service. */ constructor( - apiVersion: ApiVersion75, - options?: KeyVaultClientOptionalParams + vaultBaseUrl: string, + credential: TokenCredential, + options: KeyVaultClientOptionalParams = {}, ) { - if (apiVersion === undefined) { - throw new Error("'apiVersion' cannot be null"); - } - - // Initializing default values for options - if (!options) { - options = {}; - } - const defaults: KeyVaultClientOptionalParams = { - requestContentType: "application/json; charset=utf-8" - }; - - const packageDetails = `azsdk-js-keyvault-secrets/4.9.1`; - const userAgentPrefix = - options.userAgentOptions && options.userAgentOptions.userAgentPrefix - ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}` - : `${packageDetails}`; - - const optionsWithDefaults = { - ...defaults, + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-client` + : `azsdk-js-client`; + this._client = createKeyVault(vaultBaseUrl, credential, { ...options, - userAgentOptions: { - userAgentPrefix - }, - baseUri: options.endpoint ?? options.baseUri ?? "{vaultBaseUrl}" - }; - super(optionsWithDefaults); - - if (options?.pipeline && options.pipeline.getOrderedPolicies().length > 0) { - const pipelinePolicies: coreRestPipeline.PipelinePolicy[] = options.pipeline.getOrderedPolicies(); - const bearerTokenAuthenticationPolicyFound = pipelinePolicies.some( - (pipelinePolicy) => - pipelinePolicy.name === - coreRestPipeline.bearerTokenAuthenticationPolicyName - ); - if (!bearerTokenAuthenticationPolicyFound) { - this.pipeline.removePolicy({ - name: coreRestPipeline.bearerTokenAuthenticationPolicyName - }); - this.pipeline.addPolicy( - coreRestPipeline.bearerTokenAuthenticationPolicy({ - scopes: `${optionsWithDefaults.baseUri}/.default`, - challengeCallbacks: { - authorizeRequestOnChallenge: - coreClient.authorizeRequestOnClaimChallenge - } - }) - ); - } - } - // Parameter assignments - this.apiVersion = apiVersion; + userAgentOptions: { userAgentPrefix }, + }); + this.pipeline = this._client.pipeline; } /** - * The SET operation adds a secret to the Azure Key Vault. If the named secret already exists, Azure - * Key Vault creates a new version of that secret. This operation requires the secrets/set permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. The value you provide may be copied globally for the - * purpose of running the service. The value provided should not include personally identifiable or - * sensitive information. - * @param value The value of the secret. - * @param options The options parameters. + * The SET operation adds a secret to the Azure Key Vault. If the named secret + * already exists, Azure Key Vault creates a new version of that secret. This + * operation requires the secrets/set permission. */ setSecret( - vaultBaseUrl: string, secretName: string, - value: string, - options?: SetSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, value, options }, - setSecretOperationSpec - ); + parameters: SecretSetParameters, + options: SetSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return setSecret(this._client, secretName, parameters, options); } /** - * The DELETE operation applies to any secret stored in Azure Key Vault. DELETE cannot be applied to an - * individual version of a secret. This operation requires the secrets/delete permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param options The options parameters. + * The DELETE operation applies to any secret stored in Azure Key Vault. DELETE + * cannot be applied to an individual version of a secret. This operation requires + * the secrets/delete permission. */ deleteSecret( - vaultBaseUrl: string, secretName: string, - options?: DeleteSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - deleteSecretOperationSpec - ); + options: DeleteSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return deleteSecret(this._client, secretName, options); } /** - * The UPDATE operation changes specified attributes of an existing stored secret. Attributes that are - * not specified in the request are left unchanged. The value of a secret itself cannot be changed. - * This operation requires the secrets/set permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param secretVersion The version of the secret. - * @param options The options parameters. + * The UPDATE operation changes specified attributes of an existing stored secret. + * Attributes that are not specified in the request are left unchanged. The value + * of a secret itself cannot be changed. This operation requires the secrets/set + * permission. */ updateSecret( - vaultBaseUrl: string, secretName: string, secretVersion: string, - options?: UpdateSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, secretVersion, options }, - updateSecretOperationSpec + parameters: SecretUpdateParameters, + options: UpdateSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return updateSecret( + this._client, + secretName, + secretVersion, + parameters, + options, ); } /** - * The GET operation is applicable to any secret stored in Azure Key Vault. This operation requires the - * secrets/get permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param secretVersion The version of the secret. This URI fragment is optional. If not specified, the - * latest version of the secret is returned. - * @param options The options parameters. + * The GET operation is applicable to any secret stored in Azure Key Vault. This + * operation requires the secrets/get permission. */ getSecret( - vaultBaseUrl: string, secretName: string, secretVersion: string, - options?: GetSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, secretVersion, options }, - getSecretOperationSpec - ); + options: GetSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return getSecret(this._client, secretName, secretVersion, options); } /** - * The Get Secrets operation is applicable to the entire vault. However, only the base secret - * identifier and its attributes are provided in the response. Individual secret versions are not - * listed in the response. This operation requires the secrets/list permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param options The options parameters. + * The Get Secrets operation is applicable to the entire vault. However, only the + * base secret identifier and its attributes are provided in the response. + * Individual secret versions are not listed in the response. This operation + * requires the secrets/list permission. */ getSecrets( - vaultBaseUrl: string, - options?: GetSecretsOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, options }, - getSecretsOperationSpec - ); + options: GetSecretsOptionalParams = { requestOptions: {} }, + ): PagedAsyncIterableIterator { + return getSecrets(this._client, options); } /** - * The full secret identifier and attributes are provided in the response. No values are returned for - * the secrets. This operations requires the secrets/list permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param options The options parameters. + * The full secret identifier and attributes are provided in the response. No + * values are returned for the secrets. This operations requires the secrets/list + * permission. */ getSecretVersions( - vaultBaseUrl: string, secretName: string, - options?: GetSecretVersionsOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - getSecretVersionsOperationSpec - ); + options: GetSecretVersionsOptionalParams = { requestOptions: {} }, + ): PagedAsyncIterableIterator { + return getSecretVersions(this._client, secretName, options); } /** - * The Get Deleted Secrets operation returns the secrets that have been deleted for a vault enabled for - * soft-delete. This operation requires the secrets/list permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param options The options parameters. + * The Get Deleted Secrets operation returns the secrets that have been deleted + * for a vault enabled for soft-delete. This operation requires the secrets/list + * permission. */ getDeletedSecrets( - vaultBaseUrl: string, - options?: GetDeletedSecretsOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, options }, - getDeletedSecretsOperationSpec - ); + options: GetDeletedSecretsOptionalParams = { requestOptions: {} }, + ): PagedAsyncIterableIterator { + return getDeletedSecrets(this._client, options); } /** - * The Get Deleted Secret operation returns the specified deleted secret along with its attributes. - * This operation requires the secrets/get permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param options The options parameters. + * The Get Deleted Secret operation returns the specified deleted secret along + * with its attributes. This operation requires the secrets/get permission. */ getDeletedSecret( - vaultBaseUrl: string, secretName: string, - options?: GetDeletedSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - getDeletedSecretOperationSpec - ); + options: GetDeletedSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return getDeletedSecret(this._client, secretName, options); } /** - * The purge deleted secret operation removes the secret permanently, without the possibility of - * recovery. This operation can only be enabled on a soft-delete enabled vault. This operation requires - * the secrets/purge permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param options The options parameters. + * The purge deleted secret operation removes the secret permanently, without the + * possibility of recovery. This operation can only be enabled on a soft-delete + * enabled vault. This operation requires the secrets/purge permission. */ purgeDeletedSecret( - vaultBaseUrl: string, secretName: string, - options?: PurgeDeletedSecretOptionalParams + options: PurgeDeletedSecretOptionalParams = { requestOptions: {} }, ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - purgeDeletedSecretOperationSpec - ); + return purgeDeletedSecret(this._client, secretName, options); } /** - * Recovers the deleted secret in the specified vault. This operation can only be performed on a - * soft-delete enabled vault. This operation requires the secrets/recover permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the deleted secret. - * @param options The options parameters. + * Recovers the deleted secret in the specified vault. This operation can only be + * performed on a soft-delete enabled vault. This operation requires the + * secrets/recover permission. */ recoverDeletedSecret( - vaultBaseUrl: string, secretName: string, - options?: RecoverDeletedSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - recoverDeletedSecretOperationSpec - ); + options: RecoverDeletedSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return recoverDeletedSecret(this._client, secretName, options); } /** - * Requests that a backup of the specified secret be downloaded to the client. All versions of the - * secret will be downloaded. This operation requires the secrets/backup permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param options The options parameters. + * Requests that a backup of the specified secret be downloaded to the client. All + * versions of the secret will be downloaded. This operation requires the + * secrets/backup permission. */ backupSecret( - vaultBaseUrl: string, secretName: string, - options?: BackupSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, options }, - backupSecretOperationSpec - ); + options: BackupSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return backupSecret(this._client, secretName, options); } /** - * Restores a backed up secret, and all its versions, to a vault. This operation requires the - * secrets/restore permission. - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretBundleBackup The backup blob associated with a secret bundle. - * @param options The options parameters. + * Restores a backed up secret, and all its versions, to a vault. This operation + * requires the secrets/restore permission. */ restoreSecret( - vaultBaseUrl: string, - secretBundleBackup: Uint8Array, - options?: RestoreSecretOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretBundleBackup, options }, - restoreSecretOperationSpec - ); - } - - /** - * GetSecretsNext - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param nextLink The nextLink from the previous successful call to the GetSecrets method. - * @param options The options parameters. - */ - getSecretsNext( - vaultBaseUrl: string, - nextLink: string, - options?: GetSecretsNextOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, nextLink, options }, - getSecretsNextOperationSpec - ); - } - - /** - * GetSecretVersionsNext - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param secretName The name of the secret. - * @param nextLink The nextLink from the previous successful call to the GetSecretVersions method. - * @param options The options parameters. - */ - getSecretVersionsNext( - vaultBaseUrl: string, - secretName: string, - nextLink: string, - options?: GetSecretVersionsNextOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, secretName, nextLink, options }, - getSecretVersionsNextOperationSpec - ); - } - - /** - * GetDeletedSecretsNext - * @param vaultBaseUrl The vault name, for example https://myvault.vault.azure.net. - * @param nextLink The nextLink from the previous successful call to the GetDeletedSecrets method. - * @param options The options parameters. - */ - getDeletedSecretsNext( - vaultBaseUrl: string, - nextLink: string, - options?: GetDeletedSecretsNextOptionalParams - ): Promise { - return this.sendOperationRequest( - { vaultBaseUrl, nextLink, options }, - getDeletedSecretsNextOperationSpec - ); + parameters: SecretRestoreParameters, + options: RestoreSecretOptionalParams = { requestOptions: {} }, + ): Promise { + return restoreSecret(this._client, parameters, options); } } -// Operation Specifications -const serializer = coreClient.createSerializer(Mappers, /* isXml */ false); - -const setSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}", - httpMethod: "PUT", - responses: { - 200: { - bodyMapper: Mappers.SecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - requestBody: { - parameterPath: { - value: ["value"], - tags: ["options", "tags"], - contentType: ["options", "contentType"], - secretAttributes: ["options", "secretAttributes"] - }, - mapper: { ...Mappers.SecretSetParameters, required: true } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName], - headerParameters: [Parameters.contentType, Parameters.accept], - mediaType: "json", - serializer -}; -const deleteSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}", - httpMethod: "DELETE", - responses: { - 200: { - bodyMapper: Mappers.DeletedSecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const updateSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}/{secret-version}", - httpMethod: "PATCH", - responses: { - 200: { - bodyMapper: Mappers.SecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - requestBody: { - parameterPath: { - contentType: ["options", "contentType"], - secretAttributes: ["options", "secretAttributes"], - tags: ["options", "tags"] - }, - mapper: { ...Mappers.SecretUpdateParameters, required: true } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [ - Parameters.vaultBaseUrl, - Parameters.secretName1, - Parameters.secretVersion - ], - headerParameters: [Parameters.contentType, Parameters.accept], - mediaType: "json", - serializer -}; -const getSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}/{secret-version}", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.SecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [ - Parameters.vaultBaseUrl, - Parameters.secretName1, - Parameters.secretVersion - ], - headerParameters: [Parameters.accept], - serializer -}; -const getSecretsOperationSpec: coreClient.OperationSpec = { - path: "/secrets", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.SecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [Parameters.vaultBaseUrl], - headerParameters: [Parameters.accept], - serializer -}; -const getSecretVersionsOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}/versions", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.SecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const getDeletedSecretsOperationSpec: coreClient.OperationSpec = { - path: "/deletedsecrets", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.DeletedSecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [Parameters.vaultBaseUrl], - headerParameters: [Parameters.accept], - serializer -}; -const getDeletedSecretOperationSpec: coreClient.OperationSpec = { - path: "/deletedsecrets/{secret-name}", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.DeletedSecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const purgeDeletedSecretOperationSpec: coreClient.OperationSpec = { - path: "/deletedsecrets/{secret-name}", - httpMethod: "DELETE", - responses: { - 204: {}, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const recoverDeletedSecretOperationSpec: coreClient.OperationSpec = { - path: "/deletedsecrets/{secret-name}/recover", - httpMethod: "POST", - responses: { - 200: { - bodyMapper: Mappers.SecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const backupSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/{secret-name}/backup", - httpMethod: "POST", - responses: { - 200: { - bodyMapper: Mappers.BackupSecretResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl, Parameters.secretName1], - headerParameters: [Parameters.accept], - serializer -}; -const restoreSecretOperationSpec: coreClient.OperationSpec = { - path: "/secrets/restore", - httpMethod: "POST", - responses: { - 200: { - bodyMapper: Mappers.SecretBundle - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - requestBody: { - parameterPath: { secretBundleBackup: ["secretBundleBackup"] }, - mapper: { ...Mappers.SecretRestoreParameters, required: true } - }, - queryParameters: [Parameters.apiVersion], - urlParameters: [Parameters.vaultBaseUrl], - headerParameters: [Parameters.contentType, Parameters.accept], - mediaType: "json", - serializer -}; -const getSecretsNextOperationSpec: coreClient.OperationSpec = { - path: "{nextLink}", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.SecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [Parameters.vaultBaseUrl, Parameters.nextLink], - headerParameters: [Parameters.accept], - serializer -}; -const getSecretVersionsNextOperationSpec: coreClient.OperationSpec = { - path: "{nextLink}", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.SecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [ - Parameters.vaultBaseUrl, - Parameters.secretName1, - Parameters.nextLink - ], - headerParameters: [Parameters.accept], - serializer -}; -const getDeletedSecretsNextOperationSpec: coreClient.OperationSpec = { - path: "{nextLink}", - httpMethod: "GET", - responses: { - 200: { - bodyMapper: Mappers.DeletedSecretListResult - }, - default: { - bodyMapper: Mappers.KeyVaultError - } - }, - queryParameters: [Parameters.apiVersion, Parameters.maxresults], - urlParameters: [Parameters.vaultBaseUrl, Parameters.nextLink], - headerParameters: [Parameters.accept], - serializer -}; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/logger.ts b/sdk/keyvault/keyvault-secrets/src/generated/logger.ts new file mode 100644 index 000000000000..1e440642ca9f --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("keyvault-secrets"); diff --git a/sdk/keyvault/keyvault-secrets/src/generated/models/index.ts b/sdk/keyvault/keyvault-secrets/src/generated/models/index.ts index 163f78c652de..83ffeb66e1f4 100644 --- a/sdk/keyvault/keyvault-secrets/src/generated/models/index.ts +++ b/sdk/keyvault/keyvault-secrets/src/generated/models/index.ts @@ -1,402 +1,19 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is regenerated. - */ - -import * as coreClient from "@azure/core-client"; -import * as coreHttpCompat from "@azure/core-http-compat"; - -/** The secret set parameters. */ -export interface SecretSetParameters { - /** The value of the secret. */ - value: string; - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; - /** Type of the secret value such as a password. */ - contentType?: string; - /** The secret management attributes. */ - secretAttributes?: SecretAttributes; -} - -/** The object attributes managed by the KeyVault service. */ -export interface Attributes { - /** Determines whether the object is enabled. */ - enabled?: boolean; - /** Not before date in UTC. */ - notBefore?: Date; - /** Expiry date in UTC. */ - expires?: Date; - /** - * Creation time in UTC. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly created?: Date; - /** - * Last updated time in UTC. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly updated?: Date; -} - -/** A secret consisting of a value, id and its attributes. */ -export interface SecretBundle { - /** The secret value. */ - value?: string; - /** The secret id. */ - id?: string; - /** The content type of the secret. */ - contentType?: string; - /** The secret management attributes. */ - attributes?: SecretAttributes; - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; - /** - * If this is a secret backing a KV certificate, then this field specifies the corresponding key backing the KV certificate. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly kid?: string; - /** - * True if the secret's lifetime is managed by key vault. If this is a secret backing a certificate, then managed will be true. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly managed?: boolean; -} - -/** The key vault error exception. */ -export interface KeyVaultError { - /** - * The key vault server error. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly error?: ErrorModel; -} - -/** The key vault server error. */ -export interface ErrorModel { - /** - * The error code. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly code?: string; - /** - * The error message. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly message?: string; - /** - * The key vault server error. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly innerError?: ErrorModel; -} - -/** The secret update parameters. */ -export interface SecretUpdateParameters { - /** Type of the secret value such as a password. */ - contentType?: string; - /** The secret management attributes. */ - secretAttributes?: SecretAttributes; - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; -} - -/** The secret list result. */ -export interface SecretListResult { - /** - * A response message containing a list of secrets in the key vault along with a link to the next page of secrets. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly value?: SecretItem[]; - /** - * The URL to get the next set of secrets. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly nextLink?: string; -} - -/** The secret item containing secret metadata. */ -export interface SecretItem { - /** Secret identifier. */ - id?: string; - /** The secret management attributes. */ - attributes?: SecretAttributes; - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; - /** Type of the secret value such as a password. */ - contentType?: string; - /** - * True if the secret's lifetime is managed by key vault. If this is a key backing a certificate, then managed will be true. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly managed?: boolean; -} - -/** The deleted secret list result */ -export interface DeletedSecretListResult { - /** - * A response message containing a list of the deleted secrets in the vault along with a link to the next page of deleted secrets - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly value?: DeletedSecretItem[]; - /** - * The URL to get the next set of deleted secrets. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly nextLink?: string; -} - -/** The backup secret result, containing the backup blob. */ -export interface BackupSecretResult { - /** - * The backup blob containing the backed up secret. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly value?: Uint8Array; -} - -/** The secret restore parameters. */ -export interface SecretRestoreParameters { - /** The backup blob associated with a secret bundle. */ - secretBundleBackup: Uint8Array; -} - -/** Properties of the key backing a certificate. */ -export interface SecretProperties { - /** The media type (MIME type). */ - contentType?: string; -} - -/** The secret management attributes. */ -export type SecretAttributes = Attributes & { - /** - * softDelete data retention days. Value should be >=7 and <=90 when softDelete enabled, otherwise 0. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly recoverableDays?: number; - /** - * Reflects the deletion recovery level currently in effect for secrets in the current vault. If it contains 'Purgeable', the secret can be permanently deleted by a privileged user; otherwise, only the system can purge the secret, at the end of the retention interval. - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly recoveryLevel?: DeletionRecoveryLevel; -}; - -/** A Deleted Secret consisting of its previous id, attributes and its tags, as well as information on when it will be purged. */ -export type DeletedSecretBundle = SecretBundle & { - /** The url of the recovery object, used to identify and recover the deleted secret. */ - recoveryId?: string; - /** - * The time when the secret is scheduled to be purged, in UTC - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly scheduledPurgeDate?: Date; - /** - * The time when the secret was deleted, in UTC - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly deletedDate?: Date; -}; - -/** The deleted secret item containing metadata about the deleted secret. */ -export type DeletedSecretItem = SecretItem & { - /** The url of the recovery object, used to identify and recover the deleted secret. */ - recoveryId?: string; - /** - * The time when the secret is scheduled to be purged, in UTC - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly scheduledPurgeDate?: Date; - /** - * The time when the secret was deleted, in UTC - * NOTE: This property will not be serialized. It can only be populated by the server. - */ - readonly deletedDate?: Date; -}; - -/** Known values of {@link ApiVersion75} that the service accepts. */ -export enum KnownApiVersion75 { - /** Api Version '7.5' */ - Seven5 = "7.5" -} - -/** - * Defines values for ApiVersion75. \ - * {@link KnownApiVersion75} can be used interchangeably with ApiVersion75, - * this enum contains the known values that the service supports. - * ### Known values supported by the service - * **7.5**: Api Version '7.5' - */ -export type ApiVersion75 = string; - -/** Known values of {@link DeletionRecoveryLevel} that the service accepts. */ -export enum KnownDeletionRecoveryLevel { - /** Denotes a vault state in which deletion is an irreversible operation, without the possibility for recovery. This level corresponds to no protection being available against a Delete operation; the data is irretrievably lost upon accepting a Delete operation at the entity level or higher (vault, resource group, subscription etc.) */ - Purgeable = "Purgeable", - /** Denotes a vault state in which deletion is recoverable, and which also permits immediate and permanent deletion (i.e. purge). This level guarantees the recoverability of the deleted entity during the retention interval (90 days), unless a Purge operation is requested, or the subscription is cancelled. System wil permanently delete it after 90 days, if not recovered */ - RecoverablePurgeable = "Recoverable+Purgeable", - /** Denotes a vault state in which deletion is recoverable without the possibility for immediate and permanent deletion (i.e. purge). This level guarantees the recoverability of the deleted entity during the retention interval(90 days) and while the subscription is still available. System wil permanently delete it after 90 days, if not recovered */ - Recoverable = "Recoverable", - /** Denotes a vault and subscription state in which deletion is recoverable within retention interval (90 days), immediate and permanent deletion (i.e. purge) is not permitted, and in which the subscription itself cannot be permanently canceled. System wil permanently delete it after 90 days, if not recovered */ - RecoverableProtectedSubscription = "Recoverable+ProtectedSubscription", - /** Denotes a vault state in which deletion is recoverable, and which also permits immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays < 90). This level guarantees the recoverability of the deleted entity during the retention interval, unless a Purge operation is requested, or the subscription is cancelled. */ - CustomizedRecoverablePurgeable = "CustomizedRecoverable+Purgeable", - /** Denotes a vault state in which deletion is recoverable without the possibility for immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays < 90).This level guarantees the recoverability of the deleted entity during the retention interval and while the subscription is still available. */ - CustomizedRecoverable = "CustomizedRecoverable", - /** Denotes a vault and subscription state in which deletion is recoverable, immediate and permanent deletion (i.e. purge) is not permitted, and in which the subscription itself cannot be permanently canceled when 7<= SoftDeleteRetentionInDays < 90. This level guarantees the recoverability of the deleted entity during the retention interval, and also reflects the fact that the subscription itself cannot be cancelled. */ - CustomizedRecoverableProtectedSubscription = "CustomizedRecoverable+ProtectedSubscription" -} - -/** - * Defines values for DeletionRecoveryLevel. \ - * {@link KnownDeletionRecoveryLevel} can be used interchangeably with DeletionRecoveryLevel, - * this enum contains the known values that the service supports. - * ### Known values supported by the service - * **Purgeable**: Denotes a vault state in which deletion is an irreversible operation, without the possibility for recovery. This level corresponds to no protection being available against a Delete operation; the data is irretrievably lost upon accepting a Delete operation at the entity level or higher (vault, resource group, subscription etc.) \ - * **Recoverable+Purgeable**: Denotes a vault state in which deletion is recoverable, and which also permits immediate and permanent deletion (i.e. purge). This level guarantees the recoverability of the deleted entity during the retention interval (90 days), unless a Purge operation is requested, or the subscription is cancelled. System wil permanently delete it after 90 days, if not recovered \ - * **Recoverable**: Denotes a vault state in which deletion is recoverable without the possibility for immediate and permanent deletion (i.e. purge). This level guarantees the recoverability of the deleted entity during the retention interval(90 days) and while the subscription is still available. System wil permanently delete it after 90 days, if not recovered \ - * **Recoverable+ProtectedSubscription**: Denotes a vault and subscription state in which deletion is recoverable within retention interval (90 days), immediate and permanent deletion (i.e. purge) is not permitted, and in which the subscription itself cannot be permanently canceled. System wil permanently delete it after 90 days, if not recovered \ - * **CustomizedRecoverable+Purgeable**: Denotes a vault state in which deletion is recoverable, and which also permits immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays < 90). This level guarantees the recoverability of the deleted entity during the retention interval, unless a Purge operation is requested, or the subscription is cancelled. \ - * **CustomizedRecoverable**: Denotes a vault state in which deletion is recoverable without the possibility for immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays < 90).This level guarantees the recoverability of the deleted entity during the retention interval and while the subscription is still available. \ - * **CustomizedRecoverable+ProtectedSubscription**: Denotes a vault and subscription state in which deletion is recoverable, immediate and permanent deletion (i.e. purge) is not permitted, and in which the subscription itself cannot be permanently canceled when 7<= SoftDeleteRetentionInDays < 90. This level guarantees the recoverability of the deleted entity during the retention interval, and also reflects the fact that the subscription itself cannot be cancelled. - */ -export type DeletionRecoveryLevel = string; - -/** Optional parameters. */ -export interface SetSecretOptionalParams extends coreClient.OperationOptions { - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; - /** Type of the secret value such as a password. */ - contentType?: string; - /** The secret management attributes. */ - secretAttributes?: SecretAttributes; -} - -/** Contains response data for the setSecret operation. */ -export type SetSecretResponse = SecretBundle; - -/** Optional parameters. */ -export interface DeleteSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Contains response data for the deleteSecret operation. */ -export type DeleteSecretResponse = DeletedSecretBundle; - -/** Optional parameters. */ -export interface UpdateSecretOptionalParams - extends coreClient.OperationOptions { - /** Type of the secret value such as a password. */ - contentType?: string; - /** The secret management attributes. */ - secretAttributes?: SecretAttributes; - /** Application specific metadata in the form of key-value pairs. */ - tags?: { [propertyName: string]: string }; -} - -/** Contains response data for the updateSecret operation. */ -export type UpdateSecretResponse = SecretBundle; - -/** Optional parameters. */ -export interface GetSecretOptionalParams extends coreClient.OperationOptions {} - -/** Contains response data for the getSecret operation. */ -export type GetSecretResponse = SecretBundle; - -/** Optional parameters. */ -export interface GetSecretsOptionalParams extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified, the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getSecrets operation. */ -export type GetSecretsResponse = SecretListResult; - -/** Optional parameters. */ -export interface GetSecretVersionsOptionalParams - extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified, the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getSecretVersions operation. */ -export type GetSecretVersionsResponse = SecretListResult; - -/** Optional parameters. */ -export interface GetDeletedSecretsOptionalParams - extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getDeletedSecrets operation. */ -export type GetDeletedSecretsResponse = DeletedSecretListResult; - -/** Optional parameters. */ -export interface GetDeletedSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Contains response data for the getDeletedSecret operation. */ -export type GetDeletedSecretResponse = DeletedSecretBundle; - -/** Optional parameters. */ -export interface PurgeDeletedSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Optional parameters. */ -export interface RecoverDeletedSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Contains response data for the recoverDeletedSecret operation. */ -export type RecoverDeletedSecretResponse = SecretBundle; - -/** Optional parameters. */ -export interface BackupSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Contains response data for the backupSecret operation. */ -export type BackupSecretResponse = BackupSecretResult; - -/** Optional parameters. */ -export interface RestoreSecretOptionalParams - extends coreClient.OperationOptions {} - -/** Contains response data for the restoreSecret operation. */ -export type RestoreSecretResponse = SecretBundle; - -/** Optional parameters. */ -export interface GetSecretsNextOptionalParams - extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified, the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getSecretsNext operation. */ -export type GetSecretsNextResponse = SecretListResult; - -/** Optional parameters. */ -export interface GetSecretVersionsNextOptionalParams - extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified, the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getSecretVersionsNext operation. */ -export type GetSecretVersionsNextResponse = SecretListResult; - -/** Optional parameters. */ -export interface GetDeletedSecretsNextOptionalParams - extends coreClient.OperationOptions { - /** Maximum number of results to return in a page. If not specified the service will return up to 25 results. */ - maxresults?: number; -} - -/** Contains response data for the getDeletedSecretsNext operation. */ -export type GetDeletedSecretsNextResponse = DeletedSecretListResult; - -/** Optional parameters. */ -export interface KeyVaultClientOptionalParams - extends coreHttpCompat.ExtendedServiceClientOptions { - /** Overrides client endpoint. */ - endpoint?: string; -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { + SecretSetParameters, + SecretAttributes, + SecretBundle, + KeyVaultError, + ErrorModel, + DeletedSecretBundle, + SecretUpdateParameters, + SecretItem, + DeletedSecretItem, + BackupSecretResult, + SecretRestoreParameters, + KnownVersions, + KnownDeletionRecoveryLevel, + DeletionRecoveryLevel, +} from "./models.js"; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/models/mappers.ts b/sdk/keyvault/keyvault-secrets/src/generated/models/mappers.ts deleted file mode 100644 index cacfcf0afd93..000000000000 --- a/sdk/keyvault/keyvault-secrets/src/generated/models/mappers.ts +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is regenerated. - */ - -import * as coreClient from "@azure/core-client"; - -export const SecretSetParameters: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretSetParameters", - modelProperties: { - value: { - serializedName: "value", - required: true, - type: { - name: "String" - } - }, - tags: { - serializedName: "tags", - type: { - name: "Dictionary", - value: { type: { name: "String" } } - } - }, - contentType: { - serializedName: "contentType", - type: { - name: "String" - } - }, - secretAttributes: { - serializedName: "attributes", - type: { - name: "Composite", - className: "SecretAttributes" - } - } - } - } -}; - -export const Attributes: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "Attributes", - modelProperties: { - enabled: { - serializedName: "enabled", - type: { - name: "Boolean" - } - }, - notBefore: { - serializedName: "nbf", - type: { - name: "UnixTime" - } - }, - expires: { - serializedName: "exp", - type: { - name: "UnixTime" - } - }, - created: { - serializedName: "created", - readOnly: true, - type: { - name: "UnixTime" - } - }, - updated: { - serializedName: "updated", - readOnly: true, - type: { - name: "UnixTime" - } - } - } - } -}; - -export const SecretBundle: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretBundle", - modelProperties: { - value: { - serializedName: "value", - type: { - name: "String" - } - }, - id: { - serializedName: "id", - type: { - name: "String" - } - }, - contentType: { - serializedName: "contentType", - type: { - name: "String" - } - }, - attributes: { - serializedName: "attributes", - type: { - name: "Composite", - className: "SecretAttributes" - } - }, - tags: { - serializedName: "tags", - type: { - name: "Dictionary", - value: { type: { name: "String" } } - } - }, - kid: { - serializedName: "kid", - readOnly: true, - type: { - name: "String" - } - }, - managed: { - serializedName: "managed", - readOnly: true, - type: { - name: "Boolean" - } - } - } - } -}; - -export const KeyVaultError: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "KeyVaultError", - modelProperties: { - error: { - serializedName: "error", - type: { - name: "Composite", - className: "ErrorModel" - } - } - } - } -}; - -export const ErrorModel: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "ErrorModel", - modelProperties: { - code: { - serializedName: "code", - readOnly: true, - type: { - name: "String" - } - }, - message: { - serializedName: "message", - readOnly: true, - type: { - name: "String" - } - }, - innerError: { - serializedName: "innererror", - type: { - name: "Composite", - className: "ErrorModel" - } - } - } - } -}; - -export const SecretUpdateParameters: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretUpdateParameters", - modelProperties: { - contentType: { - serializedName: "contentType", - type: { - name: "String" - } - }, - secretAttributes: { - serializedName: "attributes", - type: { - name: "Composite", - className: "SecretAttributes" - } - }, - tags: { - serializedName: "tags", - type: { - name: "Dictionary", - value: { type: { name: "String" } } - } - } - } - } -}; - -export const SecretListResult: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretListResult", - modelProperties: { - value: { - serializedName: "value", - readOnly: true, - type: { - name: "Sequence", - element: { - type: { - name: "Composite", - className: "SecretItem" - } - } - } - }, - nextLink: { - serializedName: "nextLink", - readOnly: true, - type: { - name: "String" - } - } - } - } -}; - -export const SecretItem: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretItem", - modelProperties: { - id: { - serializedName: "id", - type: { - name: "String" - } - }, - attributes: { - serializedName: "attributes", - type: { - name: "Composite", - className: "SecretAttributes" - } - }, - tags: { - serializedName: "tags", - type: { - name: "Dictionary", - value: { type: { name: "String" } } - } - }, - contentType: { - serializedName: "contentType", - type: { - name: "String" - } - }, - managed: { - serializedName: "managed", - readOnly: true, - type: { - name: "Boolean" - } - } - } - } -}; - -export const DeletedSecretListResult: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "DeletedSecretListResult", - modelProperties: { - value: { - serializedName: "value", - readOnly: true, - type: { - name: "Sequence", - element: { - type: { - name: "Composite", - className: "DeletedSecretItem" - } - } - } - }, - nextLink: { - serializedName: "nextLink", - readOnly: true, - type: { - name: "String" - } - } - } - } -}; - -export const BackupSecretResult: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "BackupSecretResult", - modelProperties: { - value: { - serializedName: "value", - readOnly: true, - type: { - name: "Base64Url" - } - } - } - } -}; - -export const SecretRestoreParameters: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretRestoreParameters", - modelProperties: { - secretBundleBackup: { - serializedName: "value", - required: true, - type: { - name: "Base64Url" - } - } - } - } -}; - -export const SecretProperties: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretProperties", - modelProperties: { - contentType: { - serializedName: "contentType", - type: { - name: "String" - } - } - } - } -}; - -export const SecretAttributes: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "SecretAttributes", - modelProperties: { - ...Attributes.type.modelProperties, - recoverableDays: { - serializedName: "recoverableDays", - readOnly: true, - type: { - name: "Number" - } - }, - recoveryLevel: { - serializedName: "recoveryLevel", - readOnly: true, - type: { - name: "String" - } - } - } - } -}; - -export const DeletedSecretBundle: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "DeletedSecretBundle", - modelProperties: { - ...SecretBundle.type.modelProperties, - recoveryId: { - serializedName: "recoveryId", - type: { - name: "String" - } - }, - scheduledPurgeDate: { - serializedName: "scheduledPurgeDate", - readOnly: true, - type: { - name: "UnixTime" - } - }, - deletedDate: { - serializedName: "deletedDate", - readOnly: true, - type: { - name: "UnixTime" - } - } - } - } -}; - -export const DeletedSecretItem: coreClient.CompositeMapper = { - type: { - name: "Composite", - className: "DeletedSecretItem", - modelProperties: { - ...SecretItem.type.modelProperties, - recoveryId: { - serializedName: "recoveryId", - type: { - name: "String" - } - }, - scheduledPurgeDate: { - serializedName: "scheduledPurgeDate", - readOnly: true, - type: { - name: "UnixTime" - } - }, - deletedDate: { - serializedName: "deletedDate", - readOnly: true, - type: { - name: "UnixTime" - } - } - } - } -}; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/models/models.ts b/sdk/keyvault/keyvault-secrets/src/generated/models/models.ts new file mode 100644 index 000000000000..6de8ec66b341 --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/models/models.ts @@ -0,0 +1,495 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { uint8ArrayToString, stringToUint8Array } from "@azure/core-util"; + +/** The secret set parameters. */ +export interface SecretSetParameters { + /** The value of the secret. */ + value: string; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; + /** Type of the secret value such as a password. */ + contentType?: string; + /** The secret management attributes. */ + secretAttributes?: SecretAttributes; +} + +export function secretSetParametersSerializer(item: SecretSetParameters): any { + return { + value: item["value"], + tags: item["tags"], + contentType: item["contentType"], + attributes: !item["secretAttributes"] + ? item["secretAttributes"] + : secretAttributesSerializer(item["secretAttributes"]), + }; +} + +/** The secret management attributes. */ +export interface SecretAttributes { + /** Determines whether the object is enabled. */ + enabled?: boolean; + /** Not before date in UTC. */ + notBefore?: Date; + /** Expiry date in UTC. */ + expires?: Date; + /** Creation time in UTC. */ + readonly created?: Date; + /** Last updated time in UTC. */ + readonly updated?: Date; + /** + * softDelete data retention days. Value should be >=7 and <=90 when softDelete + * enabled, otherwise 0. + */ + readonly recoverableDays?: number; + /** + * Reflects the deletion recovery level currently in effect for secrets in the + * current vault. If it contains 'Purgeable', the secret can be permanently + * deleted by a privileged user; otherwise, only the system can purge the secret, + * at the end of the retention interval. + */ + readonly recoveryLevel?: string; +} + +export function secretAttributesSerializer(item: SecretAttributes): any { + return { + enabled: item["enabled"], + nbf: !item["notBefore"] ? item["notBefore"] : item["notBefore"].getTime() / 1000, + exp: !item["expires"] ? item["expires"] : item["expires"].getTime() / 1000, + }; +} + +export function secretAttributesDeserializer(item: any): SecretAttributes { + return { + enabled: item["enabled"], + notBefore: !item["nbf"] ? item["nbf"] : new Date(item["nbf"] * 1000), + expires: !item["exp"] ? item["exp"] : new Date(item["exp"] * 1000), + created: !item["created"] ? item["created"] : new Date(item["created"] * 1000), + updated: !item["updated"] ? item["updated"] : new Date(item["updated"] * 1000), + recoverableDays: item["recoverableDays"], + recoveryLevel: item["recoveryLevel"], + }; +} + +/** A secret consisting of a value, id and its attributes. */ +export interface SecretBundle { + /** The secret value. */ + value?: string; + /** The secret id. */ + id?: string; + /** The content type of the secret. */ + contentType?: string; + /** The secret management attributes. */ + attributes?: SecretAttributes; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; + /** + * If this is a secret backing a KV certificate, then this field specifies the + * corresponding key backing the KV certificate. + */ + readonly kid?: string; + /** + * True if the secret's lifetime is managed by key vault. If this is a secret + * backing a certificate, then managed will be true. + */ + readonly managed?: boolean; +} + +export function secretBundleDeserializer(item: any): SecretBundle { + return { + value: item["value"], + id: item["id"], + contentType: item["contentType"], + attributes: !item["attributes"] + ? item["attributes"] + : secretAttributesDeserializer(item["attributes"]), + tags: item["tags"], + kid: item["kid"], + managed: item["managed"], + }; +} + +/** The key vault error exception. */ +export interface KeyVaultError { + /** The key vault server error. */ + readonly error?: ErrorModel; +} + +export function keyVaultErrorDeserializer(item: any): KeyVaultError { + return { + error: !item["error"] ? item["error"] : errorDeserializer(item["error"]), + }; +} + +/** The key vault server error. */ +export interface ErrorModel { + /** The error code. */ + readonly code?: string; + /** The error message. */ + readonly message?: string; + /** The key vault server error. */ + readonly innerError?: ErrorModel; +} + +export function errorDeserializer(item: any): ErrorModel { + return { + code: item["code"], + message: item["message"], + innerError: !item["innererror"] + ? item["innererror"] + : errorDeserializer(item["innererror"]), + }; +} + +/** + * A Deleted Secret consisting of its previous id, attributes and its tags, as + * well as information on when it will be purged. + */ +export interface DeletedSecretBundle { + /** The secret value. */ + value?: string; + /** The secret id. */ + id?: string; + /** The content type of the secret. */ + contentType?: string; + /** The secret management attributes. */ + attributes?: SecretAttributes; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; + /** + * If this is a secret backing a KV certificate, then this field specifies the + * corresponding key backing the KV certificate. + */ + readonly kid?: string; + /** + * True if the secret's lifetime is managed by key vault. If this is a secret + * backing a certificate, then managed will be true. + */ + readonly managed?: boolean; + /** The url of the recovery object, used to identify and recover the deleted secret. */ + recoveryId?: string; + /** The time when the secret is scheduled to be purged, in UTC */ + readonly scheduledPurgeDate?: Date; + /** The time when the secret was deleted, in UTC */ + readonly deletedDate?: Date; +} + +export function deletedSecretBundleDeserializer( + item: any, +): DeletedSecretBundle { + return { + value: item["value"], + id: item["id"], + contentType: item["contentType"], + attributes: !item["attributes"] + ? item["attributes"] + : secretAttributesDeserializer(item["attributes"]), + tags: item["tags"], + kid: item["kid"], + managed: item["managed"], + recoveryId: item["recoveryId"], + scheduledPurgeDate: !item["scheduledPurgeDate"] + ? item["scheduledPurgeDate"] + : new Date(item["scheduledPurgeDate"]), + deletedDate: !item["deletedDate"] + ? item["deletedDate"] + : new Date(item["deletedDate"]), + }; +} + +/** The secret update parameters. */ +export interface SecretUpdateParameters { + /** Type of the secret value such as a password. */ + contentType?: string; + /** The secret management attributes. */ + secretAttributes?: SecretAttributes; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; +} + +export function secretUpdateParametersSerializer( + item: SecretUpdateParameters, +): any { + return { + contentType: item["contentType"], + attributes: !item["secretAttributes"] + ? item["secretAttributes"] + : secretAttributesSerializer(item["secretAttributes"]), + tags: item["tags"], + }; +} + +/** The secret list result. */ +export interface _SecretListResult { + /** + * A response message containing a list of secrets in the key vault along with a link to the next page of + * secrets. + */ + readonly value?: SecretItem[]; + /** The URL to get the next set of secrets. */ + readonly nextLink?: string; +} + +export function _secretListResultDeserializer(item: any): _SecretListResult { + return { + value: !item["value"] + ? item["value"] + : secretItemArrayDeserializer(item["value"]), + nextLink: item["nextLink"], + }; +} + +export function secretItemArrayDeserializer(result: Array): any[] { + return result.map((item) => { + return secretItemDeserializer(item); + }); +} + +/** The secret item containing secret metadata. */ +export interface SecretItem { + /** Secret identifier. */ + id?: string; + /** The secret management attributes. */ + attributes?: SecretAttributes; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; + /** Type of the secret value such as a password. */ + contentType?: string; + /** + * True if the secret's lifetime is managed by key vault. If this is a key backing + * a certificate, then managed will be true. + */ + readonly managed?: boolean; +} + +export function secretItemDeserializer(item: any): SecretItem { + return { + id: item["id"], + attributes: !item["attributes"] + ? item["attributes"] + : secretAttributesDeserializer(item["attributes"]), + tags: item["tags"], + contentType: item["contentType"], + managed: item["managed"], + }; +} + +/** The deleted secret list result */ +export interface _DeletedSecretListResult { + /** + * A response message containing a list of deleted secrets in the key vault along with a link to the next page of + * deleted secrets. + */ + readonly value?: DeletedSecretItem[]; + /** The URL to get the next set of deleted secrets. */ + readonly nextLink?: string; +} + +export function _deletedSecretListResultDeserializer( + item: any, +): _DeletedSecretListResult { + return { + value: !item["value"] + ? item["value"] + : deletedSecretItemArrayDeserializer(item["value"]), + nextLink: item["nextLink"], + }; +} + +export function deletedSecretItemArrayDeserializer( + result: Array, +): any[] { + return result.map((item) => { + return deletedSecretItemDeserializer(item); + }); +} + +/** The deleted secret item containing metadata about the deleted secret. */ +export interface DeletedSecretItem { + /** Secret identifier. */ + id?: string; + /** The secret management attributes. */ + attributes?: SecretAttributes; + /** Application specific metadata in the form of key-value pairs. */ + tags?: Record; + /** Type of the secret value such as a password. */ + contentType?: string; + /** + * True if the secret's lifetime is managed by key vault. If this is a key backing + * a certificate, then managed will be true. + */ + readonly managed?: boolean; + /** The url of the recovery object, used to identify and recover the deleted secret. */ + recoveryId?: string; + /** The time when the secret is scheduled to be purged, in UTC */ + readonly scheduledPurgeDate?: Date; + /** The time when the secret was deleted, in UTC */ + readonly deletedDate?: Date; +} + +export function deletedSecretItemDeserializer(item: any): DeletedSecretItem { + return { + id: item["id"], + attributes: !item["attributes"] + ? item["attributes"] + : secretAttributesDeserializer(item["attributes"]), + tags: item["tags"], + contentType: item["contentType"], + managed: item["managed"], + recoveryId: item["recoveryId"], + scheduledPurgeDate: !item["scheduledPurgeDate"] + ? item["scheduledPurgeDate"] + : new Date(item["scheduledPurgeDate"]), + deletedDate: !item["deletedDate"] + ? item["deletedDate"] + : new Date(item["deletedDate"]), + }; +} + +/** The backup secret result, containing the backup blob. */ +export interface BackupSecretResult { + /** The backup blob containing the backed up secret. */ + readonly value?: Uint8Array; +} + +export function backupSecretResultDeserializer(item: any): BackupSecretResult { + return { + value: !item["value"] + ? item["value"] + : typeof item["value"] === "string" + ? stringToUint8Array(item["value"], "base64url") + : item["value"], + }; +} + +/** The secret restore parameters. */ +export interface SecretRestoreParameters { + /** The backup blob associated with a secret bundle. */ + secretBundleBackup: Uint8Array; +} + +export function secretRestoreParametersSerializer( + item: SecretRestoreParameters, +): any { + return { value: uint8ArrayToString(item["secretBundleBackup"], "base64url") }; +} + +/** The available API versions. */ +export enum KnownVersions { + /** The 7.5 API version. */ + "v7.5" = "7.5", + /** The 7.6-preview.1 API version. */ + "v7.6_preview.1" = "7.6-preview.1", +} + +/** + * Reflects the deletion recovery level currently in effect for secrets in the + * current vault. If it contains 'Purgeable', the secret can be permanently + * deleted by a privileged user; otherwise, only the system can purge the secret, + * at the end of the retention interval. + */ +export enum KnownDeletionRecoveryLevel { + /** + * Denotes a vault state in which deletion is an irreversible operation, without + * the possibility for recovery. This level corresponds to no protection being + * available against a Delete operation; the data is irretrievably lost upon + * accepting a Delete operation at the entity level or higher (vault, resource + * group, subscription etc.) + */ + Purgeable = "Purgeable", + /** + * Denotes a vault state in which deletion is recoverable, and which also permits + * immediate and permanent deletion (i.e. purge). This level guarantees the + * recoverability of the deleted entity during the retention interval (90 days), + * unless a Purge operation is requested, or the subscription is cancelled. System + * wil permanently delete it after 90 days, if not recovered + */ + RecoverablePurgeable = "Recoverable+Purgeable", + /** + * Denotes a vault state in which deletion is recoverable without the possibility + * for immediate and permanent deletion (i.e. purge). This level guarantees the + * recoverability of the deleted entity during the retention interval(90 days) and + * while the subscription is still available. System wil permanently delete it + * after 90 days, if not recovered + */ + Recoverable = "Recoverable", + /** + * Denotes a vault and subscription state in which deletion is recoverable within + * retention interval (90 days), immediate and permanent deletion (i.e. purge) is + * not permitted, and in which the subscription itself cannot be permanently + * canceled. System wil permanently delete it after 90 days, if not recovered + */ + RecoverableProtectedSubscription = "Recoverable+ProtectedSubscription", + /** + * Denotes a vault state in which deletion is recoverable, and which also permits + * immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays + * < 90). This level guarantees the recoverability of the deleted entity during + * the retention interval, unless a Purge operation is requested, or the + * subscription is cancelled. + */ + CustomizedRecoverablePurgeable = "CustomizedRecoverable+Purgeable", + /** + * Denotes a vault state in which deletion is recoverable without the possibility + * for immediate and permanent deletion (i.e. purge when 7<= + * SoftDeleteRetentionInDays < 90).This level guarantees the recoverability of the + * deleted entity during the retention interval and while the subscription is + * still available. + */ + CustomizedRecoverable = "CustomizedRecoverable", + /** + * Denotes a vault and subscription state in which deletion is recoverable, + * immediate and permanent deletion (i.e. purge) is not permitted, and in which + * the subscription itself cannot be permanently canceled when 7<= + * SoftDeleteRetentionInDays < 90. This level guarantees the recoverability of the + * deleted entity during the retention interval, and also reflects the fact that + * the subscription itself cannot be cancelled. + */ + CustomizedRecoverableProtectedSubscription = "CustomizedRecoverable+ProtectedSubscription", +} + +/** + * Reflects the deletion recovery level currently in effect for secrets in the + * current vault. If it contains 'Purgeable', the secret can be permanently + * deleted by a privileged user; otherwise, only the system can purge the secret, + * at the end of the retention interval. \ + * {@link KnownDeletionRecoveryLevel} can be used interchangeably with DeletionRecoveryLevel, + * this enum contains the known values that the service supports. + * ### Known values supported by the service + * **Purgeable**: Denotes a vault state in which deletion is an irreversible operation, without + * the possibility for recovery. This level corresponds to no protection being + * available against a Delete operation; the data is irretrievably lost upon + * accepting a Delete operation at the entity level or higher (vault, resource + * group, subscription etc.) \ + * **Recoverable+Purgeable**: Denotes a vault state in which deletion is recoverable, and which also permits + * immediate and permanent deletion (i.e. purge). This level guarantees the + * recoverability of the deleted entity during the retention interval (90 days), + * unless a Purge operation is requested, or the subscription is cancelled. System + * wil permanently delete it after 90 days, if not recovered \ + * **Recoverable**: Denotes a vault state in which deletion is recoverable without the possibility + * for immediate and permanent deletion (i.e. purge). This level guarantees the + * recoverability of the deleted entity during the retention interval(90 days) and + * while the subscription is still available. System wil permanently delete it + * after 90 days, if not recovered \ + * **Recoverable+ProtectedSubscription**: Denotes a vault and subscription state in which deletion is recoverable within + * retention interval (90 days), immediate and permanent deletion (i.e. purge) is + * not permitted, and in which the subscription itself cannot be permanently + * canceled. System wil permanently delete it after 90 days, if not recovered \ + * **CustomizedRecoverable+Purgeable**: Denotes a vault state in which deletion is recoverable, and which also permits + * immediate and permanent deletion (i.e. purge when 7<= SoftDeleteRetentionInDays + * < 90). This level guarantees the recoverability of the deleted entity during + * the retention interval, unless a Purge operation is requested, or the + * subscription is cancelled. \ + * **CustomizedRecoverable**: Denotes a vault state in which deletion is recoverable without the possibility + * for immediate and permanent deletion (i.e. purge when 7<= + * SoftDeleteRetentionInDays < 90).This level guarantees the recoverability of the + * deleted entity during the retention interval and while the subscription is + * still available. \ + * **CustomizedRecoverable+ProtectedSubscription**: Denotes a vault and subscription state in which deletion is recoverable, + * immediate and permanent deletion (i.e. purge) is not permitted, and in which + * the subscription itself cannot be permanently canceled when 7<= + * SoftDeleteRetentionInDays < 90. This level guarantees the recoverability of the + * deleted entity during the retention interval, and also reflects the fact that + * the subscription itself cannot be cancelled. + */ +export type DeletionRecoveryLevel = string; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/models/parameters.ts b/sdk/keyvault/keyvault-secrets/src/generated/models/parameters.ts deleted file mode 100644 index b973d0199c53..000000000000 --- a/sdk/keyvault/keyvault-secrets/src/generated/models/parameters.ts +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is regenerated. - */ - -import { - OperationParameter, - OperationURLParameter, - OperationQueryParameter -} from "@azure/core-client"; -import { - SecretSetParameters as SecretSetParametersMapper, - SecretUpdateParameters as SecretUpdateParametersMapper, - SecretRestoreParameters as SecretRestoreParametersMapper -} from "../models/mappers.js"; - -export const contentType: OperationParameter = { - parameterPath: ["options", "contentType"], - mapper: { - defaultValue: "application/json", - isConstant: true, - serializedName: "Content-Type", - type: { - name: "String" - } - } -}; - -export const accept: OperationParameter = { - parameterPath: "accept", - mapper: { - defaultValue: "application/json", - isConstant: true, - serializedName: "Accept", - type: { - name: "String" - } - } -}; - -export const value: OperationParameter = { - parameterPath: "value", - mapper: SecretSetParametersMapper -}; - -export const tags: OperationParameter = { - parameterPath: ["options", "tags"], - mapper: SecretSetParametersMapper -}; - -export const contentType1: OperationParameter = { - parameterPath: ["options", "contentType"], - mapper: SecretSetParametersMapper -}; - -export const secretAttributes: OperationParameter = { - parameterPath: ["options", "secretAttributes"], - mapper: SecretSetParametersMapper -}; - -export const vaultBaseUrl: OperationURLParameter = { - parameterPath: "vaultBaseUrl", - mapper: { - serializedName: "vaultBaseUrl", - required: true, - type: { - name: "String" - } - }, - skipEncoding: true -}; - -export const secretName: OperationURLParameter = { - parameterPath: "secretName", - mapper: { - constraints: { - Pattern: new RegExp("^[0-9a-zA-Z-]+$") - }, - serializedName: "secret-name", - required: true, - type: { - name: "String" - } - } -}; - -export const apiVersion: OperationQueryParameter = { - parameterPath: "apiVersion", - mapper: { - serializedName: "api-version", - required: true, - type: { - name: "String" - } - } -}; - -export const secretName1: OperationURLParameter = { - parameterPath: "secretName", - mapper: { - serializedName: "secret-name", - required: true, - type: { - name: "String" - } - } -}; - -export const contentType2: OperationParameter = { - parameterPath: ["options", "contentType"], - mapper: SecretUpdateParametersMapper -}; - -export const secretAttributes1: OperationParameter = { - parameterPath: ["options", "secretAttributes"], - mapper: SecretUpdateParametersMapper -}; - -export const tags1: OperationParameter = { - parameterPath: ["options", "tags"], - mapper: SecretUpdateParametersMapper -}; - -export const secretVersion: OperationURLParameter = { - parameterPath: "secretVersion", - mapper: { - serializedName: "secret-version", - required: true, - type: { - name: "String" - } - } -}; - -export const maxresults: OperationQueryParameter = { - parameterPath: ["options", "maxresults"], - mapper: { - constraints: { - InclusiveMaximum: 25, - InclusiveMinimum: 1 - }, - serializedName: "maxresults", - type: { - name: "Number" - } - } -}; - -export const secretBundleBackup: OperationParameter = { - parameterPath: "secretBundleBackup", - mapper: SecretRestoreParametersMapper -}; - -export const nextLink: OperationURLParameter = { - parameterPath: "nextLink", - mapper: { - serializedName: "nextLink", - required: true, - type: { - name: "String" - } - }, - skipEncoding: true -}; diff --git a/sdk/keyvault/keyvault-secrets/src/generated/static-helpers/pagingHelpers.ts b/sdk/keyvault/keyvault-secrets/src/generated/static-helpers/pagingHelpers.ts new file mode 100644 index 000000000000..dc35b0af242d --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/src/generated/static-helpers/pagingHelpers.ts @@ -0,0 +1,277 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + Client, + createRestError, + PathUncheckedResponse, +} from "@azure-rest/core-client"; +import { RestError } from "@azure/core-rest-pipeline"; + +/** + * Options for the byPage method + */ +export interface PageSettings { + /** + * A reference to a specific page to start iterating from. + */ + continuationToken?: string; +} + +/** + * An interface that describes a page of results. + */ +export type ContinuablePage = TPage & { + /** + * The token that keeps track of where to continue the iterator + */ + continuationToken?: string; +}; + +/** + * An interface that allows async iterable iteration both to completion and by page. + */ +export interface PagedAsyncIterableIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +> { + /** + * The next method, part of the iteration protocol + */ + next(): Promise>; + /** + * The connection to the async iterator, part of the iteration protocol + */ + [Symbol.asyncIterator](): PagedAsyncIterableIterator< + TElement, + TPage, + TPageSettings + >; + /** + * Return an AsyncIterableIterator that works a page at a time + */ + byPage: ( + settings?: TPageSettings, + ) => AsyncIterableIterator>; +} + +/** + * An interface that describes how to communicate with the service. + */ +export interface PagedResult< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +> { + /** + * Link to the first page of results. + */ + firstPageLink?: string; + /** + * A method that returns a page of results. + */ + getPage: ( + pageLink?: string, + ) => Promise<{ page: TPage; nextPageLink?: string } | undefined>; + /** + * a function to implement the `byPage` method on the paged async iterator. + */ + byPage?: ( + settings?: TPageSettings, + ) => AsyncIterableIterator>; + + /** + * A function to extract elements from a page. + */ + toElements?: (page: TPage) => TElement[]; +} + +/** + * Options for the paging helper + */ +export interface BuildPagedAsyncIteratorOptions { + itemName?: string; + nextLinkName?: string; +} + +/** + * Helper to paginate results in a generic way and return a PagedAsyncIterableIterator + */ +export function buildPagedAsyncIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, + TResponse extends PathUncheckedResponse = PathUncheckedResponse, +>( + client: Client, + getInitialResponse: () => PromiseLike, + processResponseBody: (result: TResponse) => PromiseLike, + expectedStatuses: string[], + options: BuildPagedAsyncIteratorOptions = {}, +): PagedAsyncIterableIterator { + const itemName = options.itemName ?? "value"; + const nextLinkName = options.nextLinkName ?? "nextLink"; + const pagedResult: PagedResult = { + getPage: async (pageLink?: string) => { + const result = + pageLink === undefined + ? await getInitialResponse() + : await client.pathUnchecked(pageLink).get(); + checkPagingRequest(result, expectedStatuses); + const results = await processResponseBody(result as TResponse); + const nextLink = getNextLink(results, nextLinkName); + const values = getElements(results, itemName) as TPage; + return { + page: values, + nextPageLink: nextLink, + }; + }, + byPage: (settings?: TPageSettings) => { + const { continuationToken } = settings ?? {}; + return getPageAsyncIterator(pagedResult, { + pageLink: continuationToken, + }); + }, + }; + return getPagedAsyncIterator(pagedResult); +} + +/** + * returns an async iterator that iterates over results. It also has a `byPage` + * method that returns pages of items at once. + * + * @param pagedResult - an object that specifies how to get pages. + * @returns a paged async iterator that iterates over results. + */ + +function getPagedAsyncIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +>( + pagedResult: PagedResult, +): PagedAsyncIterableIterator { + const iter = getItemAsyncIterator( + pagedResult, + ); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: + pagedResult?.byPage ?? + ((settings?: TPageSettings) => { + const { continuationToken } = settings ?? {}; + return getPageAsyncIterator(pagedResult, { + pageLink: continuationToken, + }); + }), + }; +} + +async function* getItemAsyncIterator< + TElement, + TPage, + TPageSettings extends PageSettings, +>( + pagedResult: PagedResult, +): AsyncIterableIterator { + const pages = getPageAsyncIterator(pagedResult); + for await (const page of pages) { + yield* page as unknown as TElement[]; + } +} + +async function* getPageAsyncIterator< + TElement, + TPage, + TPageSettings extends PageSettings, +>( + pagedResult: PagedResult, + options: { + pageLink?: string; + } = {}, +): AsyncIterableIterator> { + const { pageLink } = options; + let response = await pagedResult.getPage( + pageLink ?? pagedResult.firstPageLink, + ); + if (!response) { + return; + } + let result = response.page as ContinuablePage; + result.continuationToken = response.nextPageLink; + yield result; + while (response.nextPageLink) { + response = await pagedResult.getPage(response.nextPageLink); + if (!response) { + return; + } + result = response.page as ContinuablePage; + result.continuationToken = response.nextPageLink; + yield result; + } +} + +/** + * Gets for the value of nextLink in the body + */ +function getNextLink(body: unknown, nextLinkName?: string): string | undefined { + if (!nextLinkName) { + return undefined; + } + + const nextLink = (body as Record)[nextLinkName]; + + if ( + typeof nextLink !== "string" && + typeof nextLink !== "undefined" && + nextLink !== null + ) { + throw new RestError( + `Body Property ${nextLinkName} should be a string or undefined or null but got ${typeof nextLink}`, + ); + } + + if (nextLink === null) { + return undefined; + } + + return nextLink; +} + +/** + * Gets the elements of the current request in the body. + */ +function getElements(body: unknown, itemName: string): T[] { + const value = (body as Record)[itemName] as T[]; + if (!Array.isArray(value)) { + throw new RestError( + `Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`, + ); + } + + return value ?? []; +} + +/** + * Checks if a request failed + */ +function checkPagingRequest( + response: PathUncheckedResponse, + expectedStatuses: string[], +): void { + if (!expectedStatuses.includes(response.status)) { + throw createRestError( + `Pagination failed with unexpected statusCode ${response.status}`, + response, + ); + } +} diff --git a/sdk/keyvault/keyvault-secrets/src/index.ts b/sdk/keyvault/keyvault-secrets/src/index.ts index 0f310bfd5fed..76ba306343e9 100644 --- a/sdk/keyvault/keyvault-secrets/src/index.ts +++ b/sdk/keyvault/keyvault-secrets/src/index.ts @@ -7,19 +7,12 @@ import type { TokenCredential } from "@azure/core-auth"; import { logger } from "./log.js"; import { PageSettings, PagedAsyncIterableIterator } from "@azure/core-paging"; -import { PollOperationState, PollerLike } from "@azure/core-lro"; -import type { - DeletedSecretBundle, - GetSecretsOptionalParams, - SecretBundle, -} from "./generated/models/index.js"; -import { DeletionRecoveryLevel, KnownDeletionRecoveryLevel } from "./generated/models/index.js"; +import type { PollOperationState } from "@azure/core-lro"; +import { PollerLike } from "@azure/core-lro"; +import type { KeyVaultClientOptionalParams } from "./generated/keyVaultClient.js"; import { KeyVaultClient } from "./generated/keyVaultClient.js"; import { keyVaultAuthenticationPolicy } from "@azure/keyvault-common"; -import { DeleteSecretPoller } from "./lro/delete/poller.js"; -import { RecoverDeletedSecretPoller } from "./lro/recover/poller.js"; - import { BackupSecretOptions, BeginDeleteSecretOptions, @@ -40,9 +33,14 @@ import { SetSecretOptions, UpdateSecretPropertiesOptions, } from "./secretsModels.js"; +import { KnownDeletionRecoveryLevel, DeletionRecoveryLevel } from "./generated/index.js"; import { KeyVaultSecretIdentifier, parseKeyVaultSecretIdentifier } from "./identifier.js"; -import { getSecretFromSecretBundle } from "./transformations.js"; +import { getSecretFromSecretBundle, mapPagedAsyncIterable } from "./transformations.js"; import { tracingClient } from "./tracing.js"; +import { bearerTokenAuthenticationPolicyName } from "@azure/core-rest-pipeline"; +import { SDK_VERSION } from "./constants.js"; +import { DeleteSecretPoller } from "./lro/delete/poller.js"; +import { RecoverDeletedSecretPoller } from "./lro/recover/poller.js"; export { SecretClientOptions, @@ -116,11 +114,15 @@ export class SecretClient { ) { this.vaultUrl = vaultUrl; - const internalPipelineOptions = { + const internalPipelineOptions: KeyVaultClientOptionalParams = { ...pipelineOptions, + userAgentOptions: { + userAgentPrefix: `${pipelineOptions.userAgentOptions?.userAgentPrefix ?? ""} azsdk-js-keyvault-secrets/${SDK_VERSION}`, + }, + apiVersion: pipelineOptions.serviceVersion || LATEST_API_VERSION, loggingOptions: { logger: logger.info, - allowedHeaderNames: [ + additionalAllowedHeaderNames: [ "x-ms-keyvault-region", "x-ms-keyvault-network-info", "x-ms-keyvault-service-version", @@ -128,15 +130,21 @@ export class SecretClient { }, }; - this.client = new KeyVaultClient( - pipelineOptions.serviceVersion || LATEST_API_VERSION, - internalPipelineOptions, - ); - - // The authentication policy must come after the deserialization policy since the deserialization policy - // converts 401 responses to an Error, and we don't want to deal with that. - this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, pipelineOptions), { - afterPolicies: ["deserializationPolicy"], + this.client = new KeyVaultClient(this.vaultUrl, credential, internalPipelineOptions); + + // Key vault has its own authentication policy that needs to be added to the pipeline, replacing the default bearerTokenAuthenticationPolicy. + this.client.pipeline.removePolicy({ name: bearerTokenAuthenticationPolicyName }); + this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, pipelineOptions), {}); + // Workaround for: https://github.com/Azure/azure-sdk-for-js/issues/31843 + this.client.pipeline.addPolicy({ + name: "ContentTypePolicy", + sendRequest(request, next) { + const contentType = request.headers.get("Content-Type") ?? ""; + if (contentType.startsWith("application/json")) { + request.headers.set("Content-Type", "application/json"); + } + return next(request); + }, }); } @@ -160,27 +168,15 @@ export class SecretClient { value: string, options: SetSecretOptions = {}, ): Promise { - let unflattenedOptions = {}; + const { enabled, notBefore, expiresOn: expires, tags, ...remainingOptions } = options; - if (options) { - const { enabled, notBefore, expiresOn: expires, ...remainingOptions } = options; - unflattenedOptions = { - ...remainingOptions, - secretAttributes: { - enabled, - notBefore, - expires, - }, - }; - } return tracingClient.withSpan( "SecretClient.setSecret", - unflattenedOptions, + remainingOptions, async (updatedOptions) => { const response = await this.client.setSecret( - this.vaultUrl, secretName, - value, + { value, secretAttributes: { enabled, notBefore, expires }, tags }, updatedOptions, ); return getSecretFromSecretBundle(response); @@ -222,7 +218,6 @@ export class SecretClient { const poller = new DeleteSecretPoller({ name, client: this.client, - vaultUrl: this.vaultUrl, ...options, operationOptions: options, }); @@ -253,27 +248,16 @@ export class SecretClient { secretVersion: string, options: UpdateSecretPropertiesOptions = {}, ): Promise { - let unflattenedOptions = {}; - if (options) { - const { enabled, notBefore, expiresOn: expires, ...remainingOptions } = options; - unflattenedOptions = { - ...remainingOptions, - secretAttributes: { - enabled, - notBefore, - expires, - }, - }; - } + const { enabled, notBefore, expiresOn: expires, tags, ...remainingOptions } = options; return tracingClient.withSpan( "SecretClient.updateSecretProperties", - unflattenedOptions, + remainingOptions, async (updatedOptions) => { const response = await this.client.updateSecret( - this.vaultUrl, secretName, secretVersion, + { secretAttributes: { enabled, notBefore, expires }, tags }, updatedOptions, ); return getSecretFromSecretBundle(response).properties; @@ -297,7 +281,6 @@ export class SecretClient { public getSecret(secretName: string, options: GetSecretOptions = {}): Promise { return tracingClient.withSpan("SecretClient.getSecret", options, async (updatedOptions) => { const response = await this.client.getSecret( - this.vaultUrl, secretName, options && options.version ? options.version : "", updatedOptions, @@ -327,11 +310,7 @@ export class SecretClient { "SecretClient.getDeletedSecret", options, async (updatedOptions) => { - const response = await this.client.getDeletedSecret( - this.vaultUrl, - secretName, - updatedOptions, - ); + const response = await this.client.getDeletedSecret(secretName, updatedOptions); return getSecretFromSecretBundle(response); }, ); @@ -361,7 +340,7 @@ export class SecretClient { "SecretClient.purgeDeletedSecret", options, async (updatedOptions) => { - await this.client.purgeDeletedSecret(this.vaultUrl, secretName, updatedOptions); + await this.client.purgeDeletedSecret(secretName, updatedOptions); }, ); } @@ -403,7 +382,6 @@ export class SecretClient { const poller = new RecoverDeletedSecretPoller({ name, client: this.client, - vaultUrl: this.vaultUrl, ...options, operationOptions: options, }); @@ -431,7 +409,7 @@ export class SecretClient { options: BackupSecretOptions = {}, ): Promise { return tracingClient.withSpan("SecretClient.backupSecret", options, async (updatedOptions) => { - const response = await this.client.backupSecret(this.vaultUrl, secretName, updatedOptions); + const response = await this.client.backupSecret(secretName, updatedOptions); return response.value; }); @@ -460,88 +438,12 @@ export class SecretClient { "SecretClient.restoreSecretBackup", options, async (updatedOptions) => { - const response = await this.client.restoreSecret( - this.vaultUrl, - secretBundleBackup, - updatedOptions, - ); + const response = await this.client.restoreSecret({ secretBundleBackup }, updatedOptions); return getSecretFromSecretBundle(response).properties; }, ); } - /** - * Deals with the pagination of {@link listPropertiesOfSecretVersions}. - * @param name - The name of the KeyVault Secret. - * @param continuationState - An object that indicates the position of the paginated request. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listPropertiesOfSecretVersionsPage( - secretName: string, - continuationState: PageSettings, - options: ListPropertiesOfSecretVersionsOptions = {}, - ): AsyncIterableIterator { - if (continuationState.continuationToken == null) { - const optionsComplete: GetSecretsOptionalParams = { - maxresults: continuationState.maxPageSize, - ...options, - }; - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.listPropertiesOfSecretVersionsPage", - optionsComplete, - (updatedOptions) => - this.client.getSecretVersions(this.vaultUrl, secretName, updatedOptions), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map( - (bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle).properties, - ); - } - } - while (continuationState.continuationToken) { - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.listPropertiesOfSecretVersionsPage", - options, - (updatedOptions) => - this.client.getSecretVersionsNext( - this.vaultUrl, - secretName, - continuationState.continuationToken!, - updatedOptions, - ), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map( - (bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle).properties, - ); - } else { - break; - } - } - } - - /** - * Deals with the iteration of all the available results of {@link listPropertiesOfSecretVersions}. - * @param name - The name of the KeyVault Secret. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listPropertiesOfSecretVersionsAll( - secretName: string, - options: ListPropertiesOfSecretVersionsOptions = {}, - ): AsyncIterableIterator { - const f = {}; - - for await (const page of this.listPropertiesOfSecretVersionsPage(secretName, f, options)) { - for (const item of page) { - yield item; - } - } - } - /** * Iterates all versions of the given secret in the vault. The full secret identifier and attributes are provided * in the response. No values are returned for the secrets. This operations requires the secrets/list permission. @@ -561,84 +463,11 @@ export class SecretClient { secretName: string, options: ListPropertiesOfSecretVersionsOptions = {}, ): PagedAsyncIterableIterator { - const iter = this.listPropertiesOfSecretVersionsAll(secretName, options); - - return { - next() { - return iter.next(); - }, - [Symbol.asyncIterator]() { - return this; - }, - byPage: (settings: PageSettings = {}) => - this.listPropertiesOfSecretVersionsPage(secretName, settings, options), - }; - } - - /** - * Deals with the pagination of {@link listPropertiesOfSecrets}. - * @param continuationState - An object that indicates the position of the paginated request. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listPropertiesOfSecretsPage( - continuationState: PageSettings, - options: ListPropertiesOfSecretsOptions = {}, - ): AsyncIterableIterator { - if (continuationState.continuationToken == null) { - const optionsComplete: GetSecretsOptionalParams = { - maxresults: continuationState.maxPageSize, - ...options, - }; - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.listPropertiesOfSecretsPage", - optionsComplete, - (updatedOptions) => this.client.getSecrets(this.vaultUrl, updatedOptions), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map( - (bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle).properties, - ); - } - } - while (continuationState.continuationToken) { - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.listPropertiesOfSecretsPage", - options, - (updatedOptions) => - this.client.getSecretsNext( - this.vaultUrl, - continuationState.continuationToken!, - updatedOptions, - ), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map( - (bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle).properties, - ); - } else { - break; - } - } - } - - /** - * Deals with the iteration of all the available results of {@link listPropertiesOfSecrets}. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listPropertiesOfSecretsAll( - options: ListPropertiesOfSecretsOptions = {}, - ): AsyncIterableIterator { - const f = {}; - - for await (const page of this.listPropertiesOfSecretsPage(f, options)) { - for (const item of page) { - yield item; - } - } + return mapPagedAsyncIterable( + (updatedOptions) => this.client.getSecretVersions(secretName, updatedOptions), + options, + (item) => getSecretFromSecretBundle(item).properties, + ); } /** @@ -659,81 +488,11 @@ export class SecretClient { public listPropertiesOfSecrets( options: ListPropertiesOfSecretsOptions = {}, ): PagedAsyncIterableIterator { - const iter = this.listPropertiesOfSecretsAll(options); - - return { - next() { - return iter.next(); - }, - [Symbol.asyncIterator]() { - return this; - }, - byPage: (settings: PageSettings = {}) => this.listPropertiesOfSecretsPage(settings, options), - }; - } - - /** - * Deals with the pagination of {@link listDeletedSecrets}. - * @param continuationState - An object that indicates the position of the paginated request. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listDeletedSecretsPage( - continuationState: PageSettings, - options: ListDeletedSecretsOptions = {}, - ): AsyncIterableIterator { - if (continuationState.continuationToken == null) { - const optionsComplete: GetSecretsOptionalParams = { - maxresults: continuationState.maxPageSize, - ...options, - }; - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.listDeletedSecretsPage", - optionsComplete, - (updatedOptions) => this.client.getDeletedSecrets(this.vaultUrl, updatedOptions), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map((bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle), - ); - } - } - while (continuationState.continuationToken) { - const currentSetResponse = await tracingClient.withSpan( - "SecretClient.lisDeletedSecretsPage", - options, - (updatedOptions) => - this.client.getDeletedSecretsNext( - this.vaultUrl, - continuationState.continuationToken!, - updatedOptions, - ), - ); - continuationState.continuationToken = currentSetResponse.nextLink; - if (currentSetResponse.value) { - yield currentSetResponse.value.map((bundle: SecretBundle | DeletedSecretBundle) => - getSecretFromSecretBundle(bundle), - ); - } else { - break; - } - } - } - - /** - * Deals with the iteration of all the available results of {@link listDeletedSecrets}. - * @param options - Optional parameters for the underlying HTTP request. - */ - private async *listDeletedSecretsAll( - options: ListDeletedSecretsOptions = {}, - ): AsyncIterableIterator { - const f = {}; - - for await (const page of this.listDeletedSecretsPage(f, options)) { - for (const item of page) { - yield item; - } - } + return mapPagedAsyncIterable( + this.client.getSecrets.bind(this.client), + options, + (item) => getSecretFromSecretBundle(item).properties, + ); } /** @@ -753,16 +512,10 @@ export class SecretClient { public listDeletedSecrets( options: ListDeletedSecretsOptions = {}, ): PagedAsyncIterableIterator { - const iter = this.listDeletedSecretsAll(options); - - return { - next() { - return iter.next(); - }, - [Symbol.asyncIterator]() { - return this; - }, - byPage: (settings: PageSettings = {}) => this.listDeletedSecretsPage(settings, options), - }; + return mapPagedAsyncIterable( + this.client.getDeletedSecrets.bind(this.client), + options, + getSecretFromSecretBundle, + ); } } diff --git a/sdk/keyvault/keyvault-secrets/src/lro/delete/operation.ts b/sdk/keyvault/keyvault-secrets/src/lro/delete/operation.ts index 84f3724effa9..86b6a816a932 100644 --- a/sdk/keyvault/keyvault-secrets/src/lro/delete/operation.ts +++ b/sdk/keyvault/keyvault-secrets/src/lro/delete/operation.ts @@ -11,7 +11,7 @@ import type { KeyVaultSecretPollOperationState } from "../keyVaultSecretPoller.j import { KeyVaultSecretPollOperation } from "../keyVaultSecretPoller.js"; import type { KeyVaultClient } from "../../generated/keyVaultClient.js"; import { getSecretFromSecretBundle } from "../../transformations.js"; -import type { OperationOptions } from "@azure/core-client"; +import type { OperationOptions } from "@azure-rest/core-client"; import { tracingClient } from "../../tracing.js"; /** @@ -29,7 +29,6 @@ export class DeleteSecretPollOperation extends KeyVaultSecretPollOperation< > { constructor( public state: DeleteSecretPollOperationState, - private vaultUrl: string, private client: KeyVaultClient, private operationOptions: OperationOptions = {}, ) { @@ -45,7 +44,7 @@ export class DeleteSecretPollOperation extends KeyVaultSecretPollOperation< "DeleteSecretPoller.deleteSecret", options, async (updatedOptions) => { - const response = await this.client.deleteSecret(this.vaultUrl, name, updatedOptions); + const response = await this.client.deleteSecret(name, updatedOptions); return getSecretFromSecretBundle(response); }, ); @@ -63,7 +62,7 @@ export class DeleteSecretPollOperation extends KeyVaultSecretPollOperation< "DeleteSecretPoller.getDeletedSecret", options, async (updatedOptions) => { - const response = await this.client.getDeletedSecret(this.vaultUrl, name, updatedOptions); + const response = await this.client.getDeletedSecret(name, updatedOptions); return getSecretFromSecretBundle(response); }, ); diff --git a/sdk/keyvault/keyvault-secrets/src/lro/delete/poller.ts b/sdk/keyvault/keyvault-secrets/src/lro/delete/poller.ts index ebfb82a305f2..c86324f73476 100644 --- a/sdk/keyvault/keyvault-secrets/src/lro/delete/poller.ts +++ b/sdk/keyvault/keyvault-secrets/src/lro/delete/poller.ts @@ -15,7 +15,7 @@ export class DeleteSecretPoller extends KeyVaultSecretPoller< DeletedSecret > { constructor(options: KeyVaultSecretPollerOptions) { - const { vaultUrl, client, name, operationOptions, intervalInMs = 2000, resumeFrom } = options; + const { client, name, operationOptions, intervalInMs = 2000, resumeFrom } = options; let state: DeleteSecretPollOperationState | undefined; @@ -28,7 +28,6 @@ export class DeleteSecretPoller extends KeyVaultSecretPoller< ...state, name, }, - vaultUrl, client, operationOptions, ); diff --git a/sdk/keyvault/keyvault-secrets/src/lro/keyVaultSecretPoller.ts b/sdk/keyvault/keyvault-secrets/src/lro/keyVaultSecretPoller.ts index 5c534a3454cb..893d7dd03f30 100644 --- a/sdk/keyvault/keyvault-secrets/src/lro/keyVaultSecretPoller.ts +++ b/sdk/keyvault/keyvault-secrets/src/lro/keyVaultSecretPoller.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { OperationOptions } from "@azure/core-client"; +import type { OperationOptions } from "@azure-rest/core-client"; import type { PollOperation, PollOperationState } from "@azure/core-lro"; import { Poller } from "@azure/core-lro"; import type { KeyVaultClient } from "../generated/keyVaultClient.js"; @@ -11,7 +11,6 @@ import { delay } from "@azure/core-util"; * Common parameters to a Key Vault Secret Poller. */ export interface KeyVaultSecretPollerOptions { - vaultUrl: string; client: KeyVaultClient; name: string; operationOptions?: OperationOptions; diff --git a/sdk/keyvault/keyvault-secrets/src/lro/recover/operation.ts b/sdk/keyvault/keyvault-secrets/src/lro/recover/operation.ts index 6f8ff8176443..41705cfa7f2d 100644 --- a/sdk/keyvault/keyvault-secrets/src/lro/recover/operation.ts +++ b/sdk/keyvault/keyvault-secrets/src/lro/recover/operation.ts @@ -12,7 +12,7 @@ import type { KeyVaultSecretPollOperationState } from "../keyVaultSecretPoller.j import { KeyVaultSecretPollOperation } from "../keyVaultSecretPoller.js"; import type { KeyVaultClient } from "../../generated/keyVaultClient.js"; import { getSecretFromSecretBundle } from "../../transformations.js"; -import type { OperationOptions } from "@azure/core-client"; +import type { OperationOptions } from "@azure-rest/core-client"; import { tracingClient } from "../../tracing.js"; /** @@ -30,7 +30,6 @@ export class RecoverDeletedSecretPollOperation extends KeyVaultSecretPollOperati > { constructor( public state: RecoverDeletedSecretPollOperationState, - private vaultUrl: string, private client: KeyVaultClient, private options: OperationOptions = {}, ) { @@ -47,7 +46,6 @@ export class RecoverDeletedSecretPollOperation extends KeyVaultSecretPollOperati options, async (updatedOptions) => { const response = await this.client.getSecret( - this.vaultUrl, name, options && options.version ? options.version : "", updatedOptions, @@ -69,11 +67,7 @@ export class RecoverDeletedSecretPollOperation extends KeyVaultSecretPollOperati "RecoverDeletedSecretPoller.recoverDeletedSecret", options, async (updatedOptions) => { - const response = await this.client.recoverDeletedSecret( - this.vaultUrl, - name, - updatedOptions, - ); + const response = await this.client.recoverDeletedSecret(name, updatedOptions); return getSecretFromSecretBundle(response); }, ); diff --git a/sdk/keyvault/keyvault-secrets/src/lro/recover/poller.ts b/sdk/keyvault/keyvault-secrets/src/lro/recover/poller.ts index 441fc24d17ea..c39acf0ee602 100644 --- a/sdk/keyvault/keyvault-secrets/src/lro/recover/poller.ts +++ b/sdk/keyvault/keyvault-secrets/src/lro/recover/poller.ts @@ -15,7 +15,7 @@ export class RecoverDeletedSecretPoller extends KeyVaultSecretPoller< SecretProperties > { constructor(options: KeyVaultSecretPollerOptions) { - const { vaultUrl, client, name, operationOptions, intervalInMs = 2000, resumeFrom } = options; + const { client, name, operationOptions, intervalInMs = 2000, resumeFrom } = options; let state: RecoverDeletedSecretPollOperationState | undefined; @@ -28,7 +28,6 @@ export class RecoverDeletedSecretPoller extends KeyVaultSecretPoller< ...state, name, }, - vaultUrl, client, operationOptions, ); diff --git a/sdk/keyvault/keyvault-secrets/src/secretsModels.ts b/sdk/keyvault/keyvault-secrets/src/secretsModels.ts index 9863b8fd14b7..b533d1942263 100644 --- a/sdk/keyvault/keyvault-secrets/src/secretsModels.ts +++ b/sdk/keyvault/keyvault-secrets/src/secretsModels.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type * as coreClient from "@azure/core-client"; -import type { DeletionRecoveryLevel } from "./generated/models/index.js"; +import type * as coreClient from "@azure-rest/core-client"; import type { ExtendedCommonClientOptions } from "@azure/core-http-compat"; +import { DeletionRecoveryLevel } from "./generated/index.js"; /** * The latest supported KeyVault service API version diff --git a/sdk/keyvault/keyvault-secrets/src/transformations.ts b/sdk/keyvault/keyvault-secrets/src/transformations.ts index 96e77317ab05..096aedf49b47 100644 --- a/sdk/keyvault/keyvault-secrets/src/transformations.ts +++ b/sdk/keyvault/keyvault-secrets/src/transformations.ts @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import type { PagedAsyncIterableIterator, PageSettings } from "./generated/index.js"; import type { DeletedSecretBundle, SecretBundle } from "./generated/models/index.js"; import { parseKeyVaultSecretIdentifier } from "./identifier.js"; import type { DeletedSecret, KeyVaultSecret } from "./secretsModels.js"; +import type { OperationOptions } from "@azure-rest/core-client"; /** * @internal @@ -72,3 +74,48 @@ export function getSecretFromSecretBundle( return resultObject; } + +/** + * A helper supporting compatibility between modular and legacy paged async iterables. + * + * Provides the following compatibility: + * 1. Maps the values of the paged async iterable using the provided mapper function. + * 2. Supports `maxPageSize` operation on the paged async iterable. + * + * TODO: move this to keyvault-common once everything is merged + */ +export function mapPagedAsyncIterable< + TGenerated, + TPublic, + TOptions extends OperationOptions & { maxresults?: number }, +>( + operation: (options: TOptions) => PagedAsyncIterableIterator, + operationOptions: TOptions, + mapper: (x: TGenerated) => TPublic, +): PagedAsyncIterableIterator { + let iter: ReturnType | undefined = undefined; + return { + async next() { + iter ??= operation({ ...operationOptions, maxresults: undefined }); + const result = await iter.next(); + + return { + ...result, + value: result.value && mapper(result.value), + }; + }, + [Symbol.asyncIterator]() { + return this; + }, + async *byPage(settings?: TSettings) { + // Pass the maxPageSize value to the underlying page operation + const iteratorByPage = operation({ + ...operationOptions, + maxresults: settings?.maxPageSize, + }).byPage(settings); + for await (const page of iteratorByPage) { + yield page.map(mapper); + } + }, + }; +} diff --git a/sdk/keyvault/keyvault-secrets/test/internal/lroUnexpectedErrors.spec.ts b/sdk/keyvault/keyvault-secrets/test/internal/lroUnexpectedErrors.spec.ts index 237c0505b192..9bbcc4180430 100644 --- a/sdk/keyvault/keyvault-secrets/test/internal/lroUnexpectedErrors.spec.ts +++ b/sdk/keyvault/keyvault-secrets/test/internal/lroUnexpectedErrors.spec.ts @@ -6,8 +6,6 @@ import { RecoverDeletedSecretPoller } from "../../src/lro/recover/poller.js"; import { describe, it, assert } from "vitest"; describe("The LROs properly throw on unexpected errors", () => { - const vaultUrl = `https://keyVaultName.vault.azure.net`; - describe("delete LRO", () => { it("403 doesn't throw", async function () { const code = 403; @@ -23,7 +21,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new DeleteSecretPoller({ - vaultUrl, name: "name", client, }); @@ -47,7 +44,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new DeleteSecretPoller({ - vaultUrl, name: "name", client, }); @@ -73,7 +69,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new DeleteSecretPoller({ - vaultUrl, name: "name", client, }); @@ -105,7 +100,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new RecoverDeletedSecretPoller({ - vaultUrl, name: "name", client, }); @@ -129,7 +123,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new RecoverDeletedSecretPoller({ - vaultUrl, name: "name", client, }); @@ -155,7 +148,6 @@ describe("The LROs properly throw on unexpected errors", () => { }, }; const poller = new RecoverDeletedSecretPoller({ - vaultUrl, name: "name", client, }); diff --git a/sdk/keyvault/keyvault-secrets/test/internal/userAgent.spec.ts b/sdk/keyvault/keyvault-secrets/test/internal/userAgent.spec.ts index 861f2ab1c2d1..b4ff792544d3 100644 --- a/sdk/keyvault/keyvault-secrets/test/internal/userAgent.spec.ts +++ b/sdk/keyvault/keyvault-secrets/test/internal/userAgent.spec.ts @@ -3,20 +3,23 @@ import { SDK_VERSION } from "../../src/constants.js"; import { SecretClient } from "../../src/index.js"; -import type { TokenCredential } from "@azure/core-auth"; import { describe, it, assert } from "vitest"; describe("Secrets client's user agent (only in Node, because of fs)", () => { it("SDK_VERSION and user-agent should match", async function () { let userAgent: string | undefined; - const client = new SecretClient("https://myvault.vault.azure.net", {} as TokenCredential, { - httpClient: { - sendRequest: async (request) => { - userAgent = request.headers.get("user-agent") ?? request.headers.get("x-ms-useragent"); - throw new Error("only a test"); + const client = new SecretClient( + "https://myvault.vault.azure.net", + { getToken: () => Promise.resolve({ token: "my-token", expiresOnTimestamp: Date.now() }) }, + { + httpClient: { + sendRequest: async (request) => { + userAgent = request.headers.get("user-agent") ?? request.headers.get("x-ms-useragent"); + throw new Error("only a test"); + }, }, }, - }); + ); try { await client.getSecret("foo"); diff --git a/sdk/keyvault/keyvault-secrets/test/public/list.spec.ts b/sdk/keyvault/keyvault-secrets/test/public/list.spec.ts index 0922ff0c157c..c52471edf576 100644 --- a/sdk/keyvault/keyvault-secrets/test/public/list.spec.ts +++ b/sdk/keyvault/keyvault-secrets/test/public/list.spec.ts @@ -140,6 +140,7 @@ describe("Secret client - list secrets in various ways", () => { } let found = 0; for await (const page of client.listPropertiesOfSecrets().byPage({ maxPageSize: 1 })) { + assert.isAtMost(page.length, 1); for (const secretProperties of page) { // The vault might contain more secrets than the ones we inserted. if (!secretNames.includes(secretProperties.name)) continue; @@ -162,6 +163,7 @@ describe("Secret client - list secrets in various ways", () => { let found = 0; for await (const page of client.listDeletedSecrets().byPage({ maxPageSize: 1 })) { + assert.isAtMost(page.length, 1); for (const secret of page) { // The vault might contain more secrets than the ones we inserted. if (!secretNames.includes(secret.name)) continue; @@ -188,6 +190,7 @@ describe("Secret client - list secrets in various ways", () => { for await (const page of client .listPropertiesOfSecretVersions(secretName) .byPage({ maxPageSize: 1 })) { + assert.isAtMost(page.length, 1); for (const secretProperties of page) { const version = secretProperties.version!; const secret = await client.getSecret(secretName, { version }); @@ -209,6 +212,7 @@ describe("Secret client - list secrets in various ways", () => { for await (const page of client .listPropertiesOfSecretVersions(secretName) .byPage({ maxPageSize: 1 })) { + assert.isAtMost(page.length, 1); for (const secretProperties of page) { assert.equal( secretProperties.name, diff --git a/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/operation.ts b/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/operation.ts index b573228aaf24..2b5a8fbdec50 100644 --- a/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/operation.ts +++ b/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/operation.ts @@ -3,7 +3,7 @@ import type { AbortSignalLike } from "@azure/abort-controller"; import type { PollOperation, PollOperationState } from "@azure/core-lro"; -import type { OperationOptions } from "@azure/core-client"; +import type { OperationOptions } from "@azure-rest/core-client"; import type { SecretPollerOptions, SecretProperties } from "../../../../../src/index.js"; /** diff --git a/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/poller.ts b/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/poller.ts index 8f6cff81bbb3..0a3b4edf5ab3 100644 --- a/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/poller.ts +++ b/sdk/keyvault/keyvault-secrets/test/public/utils/lro/restore/poller.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { OperationOptions } from "@azure/core-client"; +import type { OperationOptions } from "@azure-rest/core-client"; import { delay } from "@azure/core-util"; import { Poller } from "@azure/core-lro"; import type { diff --git a/sdk/keyvault/keyvault-secrets/tsp-location.yaml b/sdk/keyvault/keyvault-secrets/tsp-location.yaml new file mode 100644 index 000000000000..9667b739cf01 --- /dev/null +++ b/sdk/keyvault/keyvault-secrets/tsp-location.yaml @@ -0,0 +1,3 @@ +directory: specification/keyvault/Security.KeyVault.Secrets/ +commit: 84a5e77596f6499df90493dacb828c480f26542e +repo: azure/azure-rest-api-specs