From 026b718a277635101aa26881fa97869c9d72bdb2 Mon Sep 17 00:00:00 2001 From: alexweininger Date: Thu, 19 Mar 2026 14:13:19 -0400 Subject: [PATCH 1/3] azure: Use BearerChallengePolicy from auth instead of local duplicate Replace AzExtBearerChallengePolicy and getDefaultScopeFromEndpoint in the azure package with imports from @microsoft/vscode-azext-azureauth. The telemetry properties (challenge, challengeSuccess) are preserved by wrapping the callback at the call site with try/catch for robustness. This adds @microsoft/vscode-azext-azureauth as a dependency of the azure package, consolidating the challenge policy logic in one place. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- azure/package.json | 1 + azure/src/createAzureClient.ts | 89 +++++++++++----------------------- 2 files changed, 30 insertions(+), 60 deletions(-) diff --git a/azure/package.json b/azure/package.json index bad7a0db3f..0ffbb7dc07 100644 --- a/azure/package.json +++ b/azure/package.json @@ -47,6 +47,7 @@ "@azure/core-client": "^1.10.1", "@azure/core-rest-pipeline": "^1.22.2", "@azure/logger": "^1.3.0", + "@microsoft/vscode-azext-azureauth": "^6.0.0-alpha.6", "@microsoft/vscode-azext-utils": "^4.0.4", "@microsoft/vscode-azureresources-api": "^3.1.0", "semver": "^7.7.4" diff --git a/azure/src/createAzureClient.ts b/azure/src/createAzureClient.ts index 15546186ea..f688a7fd0d 100644 --- a/azure/src/createAzureClient.ts +++ b/azure/src/createAzureClient.ts @@ -5,6 +5,7 @@ import { ServiceClient } from '@azure/core-client'; import { createHttpHeaders, createPipelineRequest, defaultRetryPolicy, Pipeline, PipelineOptions, PipelinePolicy, PipelineRequest, PipelineResponse, RestError, RetryPolicyOptions, SendRequest, userAgentPolicy } from '@azure/core-rest-pipeline'; +import { BearerChallengePolicy } from '@microsoft/vscode-azext-azureauth'; import { appendExtensionUserAgent, AzExtServiceClientCredentialsT2, AzExtTreeItem, IActionContext, ISubscriptionActionContext, ISubscriptionContext, parseError } from '@microsoft/vscode-azext-utils'; import { randomUUID } from 'crypto'; import { Agent as HttpsAgent } from 'https'; @@ -51,16 +52,26 @@ export function createAzureClient(clientContext: Intern }); context.telemetry.properties.subscriptionId = context.subscriptionId; + const handleChallenge = getChallengeHandlerFromCredential(context.createCredentialsForScopes); addAzExtPipeline( context, client.pipeline, context.environment.resourceManagerEndpointUrl, undefined, undefined, - new AzExtBearerChallengePolicy( - context, - getChallengeHandlerFromCredential(context.createCredentialsForScopes), - context.environment.resourceManagerEndpointUrl + new BearerChallengePolicy( + async (challenge) => { + context.telemetry.properties.challenge = 'true'; + try { + const token = await handleChallenge(challenge); + context.telemetry.properties.challengeSuccess = token ? 'true' : 'false'; + return token; + } catch { + context.telemetry.properties.challengeSuccess = 'false'; + return undefined; + } + }, + context.environment.resourceManagerEndpointUrl, ) ); return client; @@ -73,16 +84,26 @@ export function createAzureSubscriptionClient(clientCon }); context.telemetry.properties.subscriptionId = context.subscriptionId; + const handleChallenge = getChallengeHandlerFromCredential(context.createCredentialsForScopes); addAzExtPipeline( context, client.pipeline, context.environment.resourceManagerEndpointUrl, undefined, undefined, - new AzExtBearerChallengePolicy( - context, - getChallengeHandlerFromCredential(context.createCredentialsForScopes), - context.environment.resourceManagerEndpointUrl + new BearerChallengePolicy( + async (challenge) => { + context.telemetry.properties.challenge = 'true'; + try { + const token = await handleChallenge(challenge); + context.telemetry.properties.challengeSuccess = token ? 'true' : 'false'; + return token; + } catch { + context.telemetry.properties.challengeSuccess = 'false'; + return undefined; + } + }, + context.environment.resourceManagerEndpointUrl, ) ); return client; @@ -317,55 +338,3 @@ class AllowInsecureConnectionPolicy implements PipelinePolicy { return await next(request); } } - -/** - * Resolve a default scope from the Resource Manager endpoint or any provided endpoint. - * Example: https://management.azure.com/ -> https://management.azure.com/.default - */ -function getDefaultScopeFromEndpoint(endpoint?: string): string { - let base = endpoint ?? 'https://management.azure.com/'; - base = base.replace(/\/+$/, ''); - return `${base}/.default`; -} - -/** - * A custom bearer policy that pre-authorizes and then retries once on a 401 with a WWW-Authenticate challenge. - */ -class AzExtBearerChallengePolicy implements PipelinePolicy { - public readonly name = 'AzExtBearerChallengePolicy'; - private readonly challengeRetryHeader = 'x-azext-challenge-retry'; - - public constructor( - private readonly context: IActionContext, - private readonly getTokenForChallenge: (request: vscode.AuthenticationWwwAuthenticateRequest) => Promise, - private readonly endpoint?: string - ) { } - - public async sendRequest(request: PipelineRequest, next: SendRequest): Promise { - const initial = await next(request); - - // Only attempt a single retry on auth challenges - if ((initial.status === 401) && !request.headers.get(this.challengeRetryHeader)) { - const header = initial.headers.get('WWW-Authenticate') || initial.headers.get('www-authenticate'); - if (header) { - this.context.telemetry.properties.challenge = 'true'; - const scopes = [getDefaultScopeFromEndpoint(this.endpoint)]; - // Mark the request as having attempted a challenge so that if the pipeline - // (or other policies like a retry policy) replays the request when token - // fetching fails, we don't attempt the challenge again. - request.headers.set(this.challengeRetryHeader, '1'); - - const token = await this.getTokenForChallenge({ wwwAuthenticate: header, fallbackScopes: scopes }); - if (token) { - this.context.telemetry.properties.challengeSuccess = 'true'; - request.headers.set('Authorization', `Bearer ${token}`); - return await next(request); - } else { - this.context.telemetry.properties.challengeSuccess = 'false'; - } - } - } - - return initial; - } -} From b8eab2a571a58bd6789af9e16e8dccdee77b0bd8 Mon Sep 17 00:00:00 2001 From: alexweininger Date: Fri, 20 Mar 2026 11:07:03 -0400 Subject: [PATCH 2/3] Address PR feedback: rethrow errors, log details, extract helper - Extract createBearerChallengePolicy() helper to deduplicate policy creation between createAzureClient and createAzureSubscriptionClient - Rethrow errors from challenge handler instead of swallowing them - Log parseError(err).message to telemetry as challengeError on failure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- azure/src/createAzureClient.ts | 51 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/azure/src/createAzureClient.ts b/azure/src/createAzureClient.ts index f688a7fd0d..2457311fb9 100644 --- a/azure/src/createAzureClient.ts +++ b/azure/src/createAzureClient.ts @@ -45,6 +45,25 @@ function getChallengeHandlerFromCredential(createCredentialsForScopes: (request: return getTokenForChallenge; } +function createBearerChallengePolicy(context: ISubscriptionActionContext): BearerChallengePolicy { + const handleChallenge = getChallengeHandlerFromCredential(context.createCredentialsForScopes); + return new BearerChallengePolicy( + async (challenge) => { + context.telemetry.properties.challenge = 'true'; + try { + const token = await handleChallenge(challenge); + context.telemetry.properties.challengeSuccess = token ? 'true' : 'false'; + return token; + } catch (err) { + context.telemetry.properties.challengeSuccess = 'false'; + context.telemetry.properties.challengeError = parseError(err).message; + throw err; + } + }, + context.environment.resourceManagerEndpointUrl, + ); +} + export function createAzureClient(clientContext: InternalAzExtClientContext, clientType: types.AzExtClientType): T { const context = parseClientContext(clientContext); const client = new clientType(context.credentials, context.subscriptionId, { @@ -52,27 +71,13 @@ export function createAzureClient(clientContext: Intern }); context.telemetry.properties.subscriptionId = context.subscriptionId; - const handleChallenge = getChallengeHandlerFromCredential(context.createCredentialsForScopes); addAzExtPipeline( context, client.pipeline, context.environment.resourceManagerEndpointUrl, undefined, undefined, - new BearerChallengePolicy( - async (challenge) => { - context.telemetry.properties.challenge = 'true'; - try { - const token = await handleChallenge(challenge); - context.telemetry.properties.challengeSuccess = token ? 'true' : 'false'; - return token; - } catch { - context.telemetry.properties.challengeSuccess = 'false'; - return undefined; - } - }, - context.environment.resourceManagerEndpointUrl, - ) + createBearerChallengePolicy(context) ); return client; } @@ -84,27 +89,13 @@ export function createAzureSubscriptionClient(clientCon }); context.telemetry.properties.subscriptionId = context.subscriptionId; - const handleChallenge = getChallengeHandlerFromCredential(context.createCredentialsForScopes); addAzExtPipeline( context, client.pipeline, context.environment.resourceManagerEndpointUrl, undefined, undefined, - new BearerChallengePolicy( - async (challenge) => { - context.telemetry.properties.challenge = 'true'; - try { - const token = await handleChallenge(challenge); - context.telemetry.properties.challengeSuccess = token ? 'true' : 'false'; - return token; - } catch { - context.telemetry.properties.challengeSuccess = 'false'; - return undefined; - } - }, - context.environment.resourceManagerEndpointUrl, - ) + createBearerChallengePolicy(context) ); return client; } From 0f9d956ece6cbb74115c43603994ce0ef8443d4f Mon Sep 17 00:00:00 2001 From: alexweininger Date: Fri, 20 Mar 2026 11:14:41 -0400 Subject: [PATCH 3/3] azure: Install @microsoft/vscode-azext-azureauth@6.0.0-alpha.6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- azure/package-lock.json | 346 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 343 insertions(+), 3 deletions(-) diff --git a/azure/package-lock.json b/azure/package-lock.json index 2f6f594260..802ac4e039 100644 --- a/azure/package-lock.json +++ b/azure/package-lock.json @@ -20,6 +20,7 @@ "@azure/core-client": "^1.10.1", "@azure/core-rest-pipeline": "^1.22.2", "@azure/logger": "^1.3.0", + "@microsoft/vscode-azext-azureauth": "^6.0.0-alpha.6", "@microsoft/vscode-azext-utils": "^4.0.4", "@microsoft/vscode-azureresources-api": "^3.1.0", "semver": "^7.7.4" @@ -356,6 +357,40 @@ "node": ">=18.0.0" } }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/logger": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", @@ -372,8 +407,42 @@ "node_modules/@azure/ms-rest-azure-env": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==", - "peer": true + "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" + }, + "node_modules/@azure/msal-browser": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.6.1.tgz", + "integrity": "sha512-Ylmp8yngH7YRLV5mA1aF4CNS6WsJTPbVXaA0Tb1x1Gv/J3BM3hE4Q7nDaf7dRfU00FcxDBBudTjqlpH74ZSsgw==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.4.0.tgz", + "integrity": "sha512-twXt09PYtj1PffNNIAzQlrBd0DS91cdA6i1gAfzJ6BnPM4xNk5k9q/5xna7jLIjU3Jnp0slKYtucshGM8OGNAw==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.1.1.tgz", + "integrity": "sha512-71grXU6+5hl+3CL3joOxlj/AW6rmhthuTlG0fRqsTrhPArQBpZuUFzCIlKOGdcafLUa/i1hBdV78ZxJdlvRA+g==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.4.0", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=20" + } }, "node_modules/@bcoe/v8-coverage": { "version": "1.0.2", @@ -1188,6 +1257,21 @@ "@nevware21/ts-utils": ">= 0.10.4 < 2.x" } }, + "node_modules/@microsoft/vscode-azext-azureauth": { + "version": "6.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureauth/-/vscode-azext-azureauth-6.0.0-alpha.6.tgz", + "integrity": "sha512-6skZlUrr1k7yZNSnlVW9TYq76lwfQ8Pmr/l2FYDTlJomjEtOBsyX62yB8csDsnmuEUJD/nJoMbQqg5gvu8krzQ==", + "license": "MIT", + "dependencies": { + "@azure/arm-resources-subscriptions": "^2.1.0", + "@azure/core-rest-pipeline": "^1.22.2", + "@azure/identity": "^4.13.0", + "@azure/ms-rest-azure-env": "^2.0.0" + }, + "engines": { + "vscode": "^1.106.0" + } + }, "node_modules/@microsoft/vscode-azext-eng": { "version": "1.0.0-alpha.12", "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-eng/-/vscode-azext-eng-1.0.0-alpha.12.tgz", @@ -1994,6 +2078,27 @@ "dev": true, "license": "ISC" }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/c8": { "version": "10.1.3", "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", @@ -2330,6 +2435,46 @@ "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/diff": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", @@ -2402,6 +2547,15 @@ "dev": true, "license": "MIT" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -3067,6 +3221,21 @@ "node": ">=8" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3100,6 +3269,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", @@ -3156,6 +3343,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3259,6 +3461,28 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -3272,6 +3496,27 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3331,6 +3576,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3338,6 +3619,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3537,6 +3824,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3926,11 +4231,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -4388,6 +4704,15 @@ "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -4542,6 +4867,21 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",