diff --git a/sdk/core/abort-controller/src/index.ts b/sdk/core/abort-controller/src/index.ts index 92eef87ac829..c3ec7d65e8a4 100644 --- a/sdk/core/abort-controller/src/index.ts +++ b/sdk/core/abort-controller/src/index.ts @@ -1,9 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -declare global { - interface Event {} -} - export { AbortError } from "./AbortError.js"; export type { AbortSignalLike } from "./AbortSignalLike.js"; diff --git a/sdk/core/core-amqp/src/util/utils.ts b/sdk/core/core-amqp/src/util/utils.ts index c33a4db7332a..4981f7fae354 100644 --- a/sdk/core/core-amqp/src/util/utils.ts +++ b/sdk/core/core-amqp/src/util/utils.ts @@ -7,31 +7,6 @@ import type { AbortSignalLike } from "@azure/abort-controller"; import type { WebSocketImpl } from "rhea-promise"; import { delay as wrapperDelay } from "@azure/core-util"; -/** - * @internal - * - * Describes the options that can be provided to create an async lock. - */ -export interface AsyncLockOptions { - /** - * The max timeout. Default is: 0 (never timeout). - */ - timeout?: number; - /** - * Maximum pending tasks. Default is: 1000. - */ - maxPending?: number; - /** - * Whether lock can reenter in the same domain. - * Default is: false. - */ - domainReentrant?: boolean; - /** - * Your implementation of the promise. Default is: global promise. - */ - Promise?: any; -} - /** * Options to configure the channelling of the AMQP connection over Web Sockets. */ @@ -72,7 +47,7 @@ export type ParsedOutput = { [P in keyof T]: T[P] }; * @returns ParsedOutput. */ export function parseConnectionString(connectionString: string): ParsedOutput { - const output: { [k: string]: string } = {}; + const output: Record = {}; const parts = connectionString.trim().split(";"); for (let part of parts) { @@ -100,7 +75,7 @@ export function parseConnectionString(connectionString: string): ParsedOutput output[key] = value; } - return output as any; + return output as ParsedOutput; } /** @@ -108,56 +83,6 @@ export function parseConnectionString(connectionString: string): ParsedOutput */ export const defaultCancellableLock: CancellableAsyncLock = new CancellableAsyncLockImpl(); -/** - * @internal - * - * Describes a Timeout class that can wait for the specified amount of time and then resolve/reject - * the promise with the given value. - */ -export class Timeout { - private _timer?: number | NodeJS.Timeout; - - set(t: number, value?: T): Promise { - return new Promise((resolve, reject) => { - this.clear(); - const callback: (args: any) => void = value ? () => reject(new Error(`${value}`)) : resolve; - this._timer = setTimeout(callback, t); - }); - } - - clear(): void { - if (this._timer) { - clearTimeout(this._timer); - } - } - - wrap(promise: Promise, t: number, value?: T): Promise { - const wrappedPromise = this._promiseFinally(promise, () => this.clear()); - const timer = this.set(t, value); - return Promise.race([wrappedPromise, timer]); - } - - private _promiseFinally(promise: Promise, fn: (...args: any[]) => void): Promise { - const success = (result: T): T => { - fn(); - return result; - }; - const error = (e: Error): Promise => { - fn(); - return Promise.reject(e); - }; - return Promise.resolve(promise).then(success, error); - } - - static set(t: number, value?: T): Promise { - return new Timeout().set(t, value); - } - - static wrap(promise: Promise, t: number, value?: T): Promise { - return new Timeout().wrap(promise, t, value); - } -} - /** * A wrapper for setTimeout that resolves a promise after t milliseconds. * @param delayInMs - The number of milliseconds to be delayed. @@ -190,67 +115,6 @@ export function isLoopbackAddress(address: string): boolean { return /^(.*:\/\/)?(127\.[\d.]+|[0:]+1|localhost)/.test(address.toLowerCase()); } -/** - * @internal - * - * Generates a random number between the given interval - * @param min - Min number of the range (inclusive). - * @param max - Max number of the range (inclusive). - */ -export function randomNumberFromInterval(min: number, max: number): number { - return Math.floor(Math.random() * (max - min + 1) + min); -} - -/** - * @internal - * - * Type declaration for a Function type where T is the input to the function and V is the output - * of the function. - */ -export type Func = (a: T) => V; - -/** - * @internal - * - * Executes an array of promises sequentially. Inspiration of this method is here: - * https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html. An awesome blog on promises! - * - * @param promiseFactories - An array of promise factories(A function that return a promise) - * - * @param kickstart - Input to the first promise that is used to kickstart the promise chain. - * If not provided then the promise chain starts with undefined. - * - * @returns A chain of resolved or rejected promises - */ -export function executePromisesSequentially( - promiseFactories: Array, - kickstart?: unknown, -): Promise { - let result = Promise.resolve(kickstart); - promiseFactories.forEach((promiseFactory) => { - result = result.then(promiseFactory); - }); - return result; -} - -/** - * @internal - * - * Determines whether the given connection string is an iothub connection string. - * @param connectionString - The connection string. - * @returns boolean. - */ -export function isIotHubConnectionString(connectionString: string): boolean { - const cs = String(connectionString); - - let result: boolean = false; - const model: any = parseConnectionString(cs); - if (model && model.HostName && model.SharedAccessKey && model.SharedAccessKeyName) { - result = true; - } - return result; -} - /** * @internal */ diff --git a/sdk/core/core-auth/src/tokenCredential.ts b/sdk/core/core-auth/src/tokenCredential.ts index 395b1126aba5..c65ff4ab6c2e 100644 --- a/sdk/core/core-auth/src/tokenCredential.ts +++ b/sdk/core/core-auth/src/tokenCredential.ts @@ -107,24 +107,6 @@ export interface AccessToken { tokenType?: "Bearer" | "pop"; } -/** - * @internal - * @param accessToken - Access token - * @returns Whether a token is bearer type or not - */ -export function isBearerToken(accessToken: AccessToken): boolean { - return !accessToken.tokenType || accessToken.tokenType === "Bearer"; -} - -/** - * @internal - * @param accessToken - Access token - * @returns Whether a token is Pop token or not - */ -export function isPopToken(accessToken: AccessToken): boolean { - return accessToken.tokenType === "pop"; -} - /** * Tests an object to determine whether it implements TokenCredential. * diff --git a/sdk/core/core-client-rest/CHANGELOG.md b/sdk/core/core-client-rest/CHANGELOG.md index 437c8245a865..a1259f97d707 100644 --- a/sdk/core/core-client-rest/CHANGELOG.md +++ b/sdk/core/core-client-rest/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 2.6.1 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 2.6.0 (2026-04-07) ### Features Added diff --git a/sdk/core/core-client-rest/package.json b/sdk/core/core-client-rest/package.json index ffd3ff866091..1bbcceb192c4 100644 --- a/sdk/core/core-client-rest/package.json +++ b/sdk/core/core-client-rest/package.json @@ -1,6 +1,6 @@ { "name": "@azure-rest/core-client", - "version": "2.6.0", + "version": "2.6.1", "description": "Core library for interfacing with Azure Rest Clients", "sdk-type": "client", "type": "module", diff --git a/sdk/core/core-client-rest/src/apiVersionPolicy.ts b/sdk/core/core-client-rest/src/apiVersionPolicy.ts index 56cb7b898cf8..17de24802caa 100644 --- a/sdk/core/core-client-rest/src/apiVersionPolicy.ts +++ b/sdk/core/core-client-rest/src/apiVersionPolicy.ts @@ -19,9 +19,7 @@ export function apiVersionPolicy(options: ClientOptions): PipelinePolicy { // Append one if there is no apiVesion and we have one at client options const url = new URL(req.url); if (!url.searchParams.get("api-version") && options.apiVersion) { - req.url = `${req.url}${ - Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" - }api-version=${options.apiVersion}`; + req.url = `${req.url}${url.searchParams.size > 0 ? "&" : "?"}api-version=${options.apiVersion}`; } return next(req); diff --git a/sdk/core/core-client-rest/src/clientHelpers.ts b/sdk/core/core-client-rest/src/clientHelpers.ts index 30dac33d0c63..7513f3334361 100644 --- a/sdk/core/core-client-rest/src/clientHelpers.ts +++ b/sdk/core/core-client-rest/src/clientHelpers.ts @@ -1,10 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { HttpClient, Pipeline } from "@azure/core-rest-pipeline"; +import type { Pipeline } from "@azure/core-rest-pipeline"; import { bearerTokenAuthenticationPolicy, - createDefaultHttpClient, createPipelineFromOptions, } from "@azure/core-rest-pipeline"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; @@ -14,8 +13,6 @@ import type { ClientOptions } from "./common.js"; import { apiVersionPolicy } from "./apiVersionPolicy.js"; import { keyCredentialAuthenticationPolicy } from "./keyCredentialAuthenticationPolicy.js"; -let cachedHttpClient: HttpClient | undefined; - /** * Optional parameters for adding a credential policy to the pipeline. */ @@ -77,14 +74,11 @@ export function createDefaultPipeline( return pipeline; } -function isKeyCredential(credential: any): credential is KeyCredential { - return (credential as KeyCredential).key !== undefined; -} - -export function getCachedDefaultHttpsClient(): HttpClient { - if (!cachedHttpClient) { - cachedHttpClient = createDefaultHttpClient(); - } - - return cachedHttpClient; +function isKeyCredential(credential: unknown): credential is KeyCredential { + return ( + typeof credential === "object" && + credential !== null && + "key" in credential && + typeof credential.key === "string" + ); } diff --git a/sdk/core/core-client-rest/src/keyCredentialAuthenticationPolicy.ts b/sdk/core/core-client-rest/src/keyCredentialAuthenticationPolicy.ts index 06bc0916881e..c168ee349172 100644 --- a/sdk/core/core-client-rest/src/keyCredentialAuthenticationPolicy.ts +++ b/sdk/core/core-client-rest/src/keyCredentialAuthenticationPolicy.ts @@ -20,7 +20,7 @@ export function keyCredentialAuthenticationPolicy( ): PipelinePolicy { return { name: keyCredentialAuthenticationPolicyName, - async sendRequest(request: PipelineRequest, next: SendRequest): Promise { + sendRequest(request: PipelineRequest, next: SendRequest): Promise { request.headers.set(apiKeyHeaderName, credential.key); return next(request); }, diff --git a/sdk/core/core-client-rest/src/restError.ts b/sdk/core/core-client-rest/src/restError.ts index a2f59f9afa1a..e4f022ffe6a9 100644 --- a/sdk/core/core-client-rest/src/restError.ts +++ b/sdk/core/core-client-rest/src/restError.ts @@ -22,8 +22,8 @@ export function createRestError( response?: PathUncheckedResponse, ): RestError { if (typeof messageOrResponse === "string") { - return tspCreateRestError(messageOrResponse, response! as TspPathUncheckedResponse); + return tspCreateRestError(messageOrResponse, response as unknown as TspPathUncheckedResponse); } else { - return tspCreateRestError(messageOrResponse as TspPathUncheckedResponse); + return tspCreateRestError(messageOrResponse as unknown as TspPathUncheckedResponse); } } diff --git a/sdk/core/core-client-rest/test/internal/clientHelpers.spec.ts b/sdk/core/core-client-rest/test/internal/clientHelpers.spec.ts index 43efcd8504f0..71a2c7afa1b7 100644 --- a/sdk/core/core-client-rest/test/internal/clientHelpers.spec.ts +++ b/sdk/core/core-client-rest/test/internal/clientHelpers.spec.ts @@ -69,6 +69,16 @@ describe("clientHelpers", () => { ); }); + it("should not treat a non-string key property as a KeyCredential", () => { + const pipeline = createDefaultPipeline(mockBaseUrl, { key: 123 } as any); + const policies = pipeline.getOrderedPolicies(); + + assert.isUndefined( + policies.find((p) => p.name === keyCredentialAuthenticationPolicyName), + "pipeline should not have keyCredentialAuthenticationPolicyName for non-string key", + ); + }); + it("should create a default pipeline with TokenCredential", () => { const mockCredential: TokenCredential = { getToken: async () => ({ expiresOnTimestamp: 0, token: "mockToken" }), diff --git a/sdk/core/core-client/src/authorizeRequestOnTenantChallenge.ts b/sdk/core/core-client/src/authorizeRequestOnTenantChallenge.ts index 30901569a05c..279bc0d2e9b4 100644 --- a/sdk/core/core-client/src/authorizeRequestOnTenantChallenge.ts +++ b/sdk/core/core-client/src/authorizeRequestOnTenantChallenge.ts @@ -95,8 +95,7 @@ function buildScopes( } const challengeScopes = new URL(challengeInfo.resource_id); - challengeScopes.pathname = Constants.DefaultScope; - let scope = challengeScopes.toString(); + let scope = new URL(Constants.DefaultScope, challengeScopes.origin).toString(); if (scope === "https://disk.azure.com/.default") { // the extra slash is required by the service scope = "https://disk.azure.com//.default"; diff --git a/sdk/core/core-client/src/serializationPolicy.ts b/sdk/core/core-client/src/serializationPolicy.ts index ff1cd846b770..345e376fcad4 100644 --- a/sdk/core/core-client/src/serializationPolicy.ts +++ b/sdk/core/core-client/src/serializationPolicy.ts @@ -48,7 +48,7 @@ export function serializationPolicy(options: SerializationPolicyOptions = {}): P return { name: serializationPolicyName, - async sendRequest(request: OperationRequest, next: SendRequest): Promise { + sendRequest(request: OperationRequest, next: SendRequest): Promise { const operationInfo = getOperationRequestInfo(request); const operationSpec = operationInfo?.operationSpec; const operationArguments = operationInfo?.operationArguments; diff --git a/sdk/core/core-client/src/serviceClient.ts b/sdk/core/core-client/src/serviceClient.ts index 1182dc6f28c7..8a1ad4940e3d 100644 --- a/sdk/core/core-client/src/serviceClient.ts +++ b/sdk/core/core-client/src/serviceClient.ts @@ -120,7 +120,7 @@ export class ServiceClient { /** * Send the provided httpRequest. */ - async sendRequest(request: PipelineRequest): Promise { + sendRequest(request: PipelineRequest): Promise { return this.pipeline.sendRequest(this._httpClient, request); } @@ -255,7 +255,7 @@ function getCredentialScopes(options: ServiceClientOptions): string | string[] | return `${options.baseUri}/.default`; } - if (options.credential && !options.credentialScopes) { + if (options.credential) { throw new Error( `When using credentials, the ServiceClientOptions must contain either a endpoint or a credentialScopes. Unable to create a bearerTokenAuthenticationPolicy`, ); diff --git a/sdk/core/core-http-compat/CHANGELOG.md b/sdk/core/core-http-compat/CHANGELOG.md index 1d218de73ac3..cbdd9903d58b 100644 --- a/sdk/core/core-http-compat/CHANGELOG.md +++ b/sdk/core/core-http-compat/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 2.4.1 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 2.4.0 (2026-04-07) ### Features Added diff --git a/sdk/core/core-http-compat/package.json b/sdk/core/core-http-compat/package.json index 0ceb0bbb018a..ee8e03a0f707 100644 --- a/sdk/core/core-http-compat/package.json +++ b/sdk/core/core-http-compat/package.json @@ -1,6 +1,6 @@ { "name": "@azure/core-http-compat", - "version": "2.4.0", + "version": "2.4.1", "description": "Core HTTP Compatibility Library to bridge the gap between Core V1 & V2 packages.", "sdk-type": "client", "type": "module", diff --git a/sdk/core/core-http-compat/src/policies/disableKeepAlivePolicy.ts b/sdk/core/core-http-compat/src/policies/disableKeepAlivePolicy.ts index 1b8ed23181b9..e4f43a860a20 100644 --- a/sdk/core/core-http-compat/src/policies/disableKeepAlivePolicy.ts +++ b/sdk/core/core-http-compat/src/policies/disableKeepAlivePolicy.ts @@ -14,7 +14,7 @@ export const disableKeepAlivePolicyName = "DisableKeepAlivePolicy"; export function createDisableKeepAlivePolicy(): PipelinePolicy { return { name: disableKeepAlivePolicyName, - async sendRequest(request: PipelineRequest, next: SendRequest): Promise { + sendRequest(request: PipelineRequest, next: SendRequest): Promise { request.disableKeepAlive = true; return next(request); }, diff --git a/sdk/core/core-http-compat/src/util.ts b/sdk/core/core-http-compat/src/util.ts index 1e274d67e9e6..29c35605869c 100644 --- a/sdk/core/core-http-compat/src/util.ts +++ b/sdk/core/core-http-compat/src/util.ts @@ -15,6 +15,22 @@ type CompatWebResourceLike = WebResourceLike & { [originalRequestSymbol]?: Pipel // cloned but we need to retrieve the OperationSpec and OperationArguments from the // original request. const originalClientRequestSymbol = Symbol.for("@azure/core-client original request"); +const passThroughProps = new Set([ + "url", + "method", + "withCredentials", + "timeout", + "requestId", + "abortSignal", + "body", + "formData", + "onDownloadProgress", + "onUploadProgress", + "proxySettings", + "streamResponseStatusCodes", + "agent", + "requestOverrides", +]); type PipelineRequestWithOriginal = PipelineRequest & { [originalClientRequestSymbol]?: PipelineRequest; }; @@ -110,24 +126,8 @@ export function toWebResourceLike( if (prop === "keepAlive") { request.disableKeepAlive = !value; } - const passThroughProps = [ - "url", - "method", - "withCredentials", - "timeout", - "requestId", - "abortSignal", - "body", - "formData", - "onDownloadProgress", - "onUploadProgress", - "proxySettings", - "streamResponseStatusCodes", - "agent", - "requestOverrides", - ]; - - if (typeof prop === "string" && passThroughProps.includes(prop)) { + + if (typeof prop === "string" && passThroughProps.has(prop)) { (request as any)[prop] = value; } @@ -233,7 +233,7 @@ export interface HttpHeadersLike { /** * A collection of HTTP header key/value pairs. */ -export class HttpHeaders implements HttpHeadersLike { +class HttpHeaders implements HttpHeadersLike { private readonly _headersMap: { [headerKey: string]: HttpHeader }; constructor(rawHeaders?: RawHttpHeaders) { diff --git a/sdk/core/core-lro/src/http/operation.ts b/sdk/core/core-lro/src/http/operation.ts index 420dc1989b2a..c2d7ce1bade0 100644 --- a/sdk/core/core-lro/src/http/operation.ts +++ b/sdk/core/core-lro/src/http/operation.ts @@ -332,7 +332,7 @@ export async function pollHttpOperation, * The expansion here is intentional because `lro` could be an object that * references an inner this, so we need to preserve a reference to it. */ - poll: async (location: string, inputOptions?: { abortSignal?: AbortSignalLike }) => + poll: (location: string, inputOptions?: { abortSignal?: AbortSignalLike }) => lro.sendPollRequest(location, inputOptions), setErrorAsResult, }); diff --git a/sdk/core/core-paging/src/getPagedAsyncIterator.ts b/sdk/core/core-paging/src/getPagedAsyncIterator.ts index c7877a5fb26f..6a81bc1e60f1 100644 --- a/sdk/core/core-paging/src/getPagedAsyncIterator.ts +++ b/sdk/core/core-paging/src/getPagedAsyncIterator.ts @@ -28,7 +28,7 @@ export function getPagedAsyncIterator< return this; }, byPage: - pagedResult?.byPage ?? + pagedResult.byPage ?? (((settings?: PageSettings) => { const { continuationToken, maxPageSize } = settings ?? {}; return getPageAsyncIterator(pagedResult, { diff --git a/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts index d67931ec28b5..a7d8d1bddd7b 100644 --- a/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts @@ -282,7 +282,7 @@ export function bearerTokenAuthenticationPolicy( // If we get another CAE Claim, we will handle it by default and return whatever value we receive for this if (isChallengeResponse(response)) { - claims = getCaeChallengeClaims(response.headers.get("WWW-Authenticate") as string); + claims = getCaeChallengeClaims(response.headers.get("WWW-Authenticate") ?? ""); if (claims) { let parsedClaim: string; try { diff --git a/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts index deeee450ba8a..cb6bfafc3bc7 100644 --- a/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts @@ -18,10 +18,8 @@ export function ndJsonPolicy(): PipelinePolicy { async sendRequest(request: PipelineRequest, next: SendRequest): Promise { // There currently isn't a good way to bypass the serializer if (typeof request.body === "string" && request.body.startsWith("[")) { - const body = JSON.parse(request.body); - if (Array.isArray(body)) { - request.body = body.map((item) => JSON.stringify(item) + "\n").join(""); - } + const body: unknown[] = JSON.parse(request.body); + request.body = body.map((item) => JSON.stringify(item) + "\n").join(""); } return next(request); }, diff --git a/sdk/core/core-rest-pipeline/src/util/tokenCycler.ts b/sdk/core/core-rest-pipeline/src/util/tokenCycler.ts index 31c7d8711997..0fee0d6ce4bd 100644 --- a/sdk/core/core-rest-pipeline/src/util/tokenCycler.ts +++ b/sdk/core/core-rest-pipeline/src/util/tokenCycler.ts @@ -133,14 +133,17 @@ export function createTokenCycler( * window and not already refreshing) */ get shouldRefresh(): boolean { + if (token === null) { + return true; + } if (cycler.isRefreshing) { return false; } - if (token?.refreshAfterTimestamp && token.refreshAfterTimestamp < Date.now()) { + if (token.refreshAfterTimestamp && token.refreshAfterTimestamp < Date.now()) { return true; } - return (token?.expiresOnTimestamp ?? 0) - options.refreshWindowInMs < Date.now(); + return token.expiresOnTimestamp - options.refreshWindowInMs < Date.now(); }, /** * Produces true if the cycler MUST refresh (null or nearly-expired diff --git a/sdk/core/core-tracing/CHANGELOG.md b/sdk/core/core-tracing/CHANGELOG.md index 72afb2c2363a..122d38b2c6f4 100644 --- a/sdk/core/core-tracing/CHANGELOG.md +++ b/sdk/core/core-tracing/CHANGELOG.md @@ -10,6 +10,8 @@ ### Other Changes +- Deprecated `Resolved` type alias in favor of the built-in TypeScript `Awaited` type. + ## 1.3.1 (2025-09-11) ### Other Changes diff --git a/sdk/core/core-tracing/review/core-tracing-node.api.md b/sdk/core/core-tracing/review/core-tracing-node.api.md index 1536c449544f..4e938fa3a010 100644 --- a/sdk/core/core-tracing/review/core-tracing-node.api.md +++ b/sdk/core/core-tracing/review/core-tracing-node.api.md @@ -45,10 +45,8 @@ export type OptionsWithTracingContext = T extends { - then(onfulfilled: infer F): any; -} ? F extends (value: infer V) => any ? Resolved : never : T; +// @public @deprecated +export type Resolved = Awaited; // @public export type SpanStatus = SpanStatusSuccess | SpanStatusError; @@ -77,7 +75,7 @@ export interface TracingClient { withContext ReturnType>(context: TracingContext, callback: Callback, ...callbackArgs: CallbackArgs): ReturnType; withSpan) => ReturnType>(name: string, operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions): Promise>>; + }, Callback extends (updatedOptions: Options, span: Omit) => ReturnType>(name: string, operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions): Promise>>; } // @public diff --git a/sdk/core/core-tracing/src/interfaces.ts b/sdk/core/core-tracing/src/interfaces.ts index 7da11e7bfcb0..45f91283a222 100644 --- a/sdk/core/core-tracing/src/interfaces.ts +++ b/sdk/core/core-tracing/src/interfaces.ts @@ -2,14 +2,11 @@ // Licensed under the MIT License. /** - * A narrower version of TypeScript 4.5's Awaited type which Recursively - * unwraps the "awaited type", emulating the behavior of `await`. + * Recursively unwraps the "awaited type", emulating the behavior of `await`. + * + * @deprecated Use the built-in TypeScript {@link Awaited} type instead. */ -export type Resolved = T extends { then(onfulfilled: infer F): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped - ? F extends (value: infer V) => any // if the argument to `then` is callable, extracts the first argument - ? Resolved // recursively unwrap the value - : never // the argument to `then` was not callable - : T; // non-object or non-thenable +export type Resolved = Awaited; /** * Represents a client that can integrate with the currently configured {@link Instrumenter}. @@ -61,7 +58,7 @@ export interface TracingClient { operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions, - ): Promise>>; + ): Promise>>; /** * Starts a given span but does not set it as the active span. * diff --git a/sdk/core/core-tracing/src/tracingClient.ts b/sdk/core/core-tracing/src/tracingClient.ts index 3e9603dbd6f7..05dbd42b0860 100644 --- a/sdk/core/core-tracing/src/tracingClient.ts +++ b/sdk/core/core-tracing/src/tracingClient.ts @@ -4,7 +4,6 @@ import type { OperationTracingOptions, OptionsWithTracingContext, - Resolved, TracingClient, TracingClientOptions, TracingContext, @@ -33,8 +32,8 @@ export function createTracingClient(options: TracingClientOptions): TracingClien } { const startSpanResult = getInstrumenter().startSpan(name, { ...spanOptions, - packageName: packageName, - packageVersion: packageVersion, + packageName, + packageVersion, tracingContext: operationOptions?.tracingOptions?.tracingContext, }); let tracingContext = startSpanResult.tracingContext; @@ -64,14 +63,14 @@ export function createTracingClient(options: TracingClientOptions): TracingClien operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions, - ): Promise>> { + ): Promise>> { const { span, updatedOptions } = startSpan(name, operationOptions, spanOptions); try { const result = await withContext(updatedOptions.tracingOptions.tracingContext, () => - Promise.resolve(callback(updatedOptions, span)), + callback(updatedOptions, span), ); span.setStatus({ status: "success" }); - return result as ReturnType; + return result as Awaited>; } catch (err: any) { span.setStatus({ status: "error", error: err }); throw err; diff --git a/sdk/core/core-util/src/delay.ts b/sdk/core/core-util/src/delay.ts index ab8ae56e4b6e..c5df4880ed21 100644 --- a/sdk/core/core-util/src/delay.ts +++ b/sdk/core/core-util/src/delay.ts @@ -3,7 +3,6 @@ import type { AbortOptions } from "./aborterUtils.js"; import { createAbortablePromise } from "./createAbortablePromise.js"; -import { getRandomIntegerInclusive } from "@typespec/ts-http-runtime/internal/util"; const StandardAbortMessage = "The delay was aborted."; @@ -32,29 +31,3 @@ export function delay(timeInMs: number, options?: DelayOptions): Promise { }, ); } - -/** - * Calculates the delay interval for retry attempts using exponential delay with jitter. - * @param retryAttempt - The current retry attempt number. - * @param config - The exponential retry configuration. - * @returns An object containing the calculated retry delay. - */ -export function calculateRetryDelay( - retryAttempt: number, - config: { - retryDelayInMs: number; - maxRetryDelayInMs: number; - }, -): { retryAfterInMs: number } { - // Exponentially increase the delay each time - const exponentialDelay = config.retryDelayInMs * Math.pow(2, retryAttempt); - - // Don't let the delay exceed the maximum - const clampedDelay = Math.min(config.maxRetryDelayInMs, exponentialDelay); - - // Allow the final value to have some "jitter" (within 50% of the delay size) so - // that retries across multiple clients don't occur simultaneously. - const retryAfterInMs = clampedDelay / 2 + getRandomIntegerInclusive(0, clampedDelay / 2); - - return { retryAfterInMs }; -} diff --git a/sdk/core/core-xml/CHANGELOG.md b/sdk/core/core-xml/CHANGELOG.md index d31395a498b6..d5a9afa43216 100644 --- a/sdk/core/core-xml/CHANGELOG.md +++ b/sdk/core/core-xml/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 1.5.2 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 1.5.1 (2026-04-07) ### Other Changes diff --git a/sdk/core/core-xml/package.json b/sdk/core/core-xml/package.json index b00c7ae956ee..051a039a4874 100644 --- a/sdk/core/core-xml/package.json +++ b/sdk/core/core-xml/package.json @@ -1,6 +1,6 @@ { "name": "@azure/core-xml", - "version": "1.5.1", + "version": "1.5.2", "description": "Core library for interacting with XML payloads", "sdk-type": "client", "type": "module", diff --git a/sdk/core/core-xml/src/xml.ts b/sdk/core/core-xml/src/xml.ts index 05569fb802ef..7f02106b6cb5 100644 --- a/sdk/core/core-xml/src/xml.ts +++ b/sdk/core/core-xml/src/xml.ts @@ -106,7 +106,8 @@ export async function parseXML(str: string, opts: XmlOptions = {}): Promise } if (!opts.includeRoot) { - for (const key of Object.keys(parsedXml)) { + const key = Object.keys(parsedXml)[0]; + if (key !== undefined) { const value = parsedXml[key]; return typeof value === "object" ? { ...value } : value; }