From 61d64245bd259555c2026542a66b002d38868024 Mon Sep 17 00:00:00 2001 From: Sunil Pai Date: Fri, 28 Jun 2024 07:36:41 +0100 Subject: [PATCH] fix: use account id for listing zones Fixes https://github.com/cloudflare/workers-sdk/issues/4944 Trying. to fetch `/zones` fails when it spans more than 500 zones. The fix to use an account id when doing so. This patch passes the account id to the zones call, threading it through all the functions that require it. --- .changeset/grumpy-bikes-prove.md | 9 +++ packages/wrangler/e2e/helpers/wrangler.ts | 5 +- packages/wrangler/e2e/versions.test.ts | 4 +- .../wrangler/src/__tests__/deploy.test.ts | 11 +++- .../wrangler/src/__tests__/rollback.test.ts | 4 +- packages/wrangler/src/__tests__/zones.test.ts | 56 ++++++++++++++----- packages/wrangler/src/deploy/deploy.ts | 22 ++++++-- packages/wrangler/src/dev.tsx | 5 +- packages/wrangler/src/dev/remote.tsx | 6 +- packages/wrangler/src/tail/index.ts | 9 ++- packages/wrangler/src/triggers/deploy.ts | 9 ++- .../wrangler/src/versions/rollback/index.ts | 2 +- packages/wrangler/src/zones.ts | 46 ++++++++++----- pnpm-lock.yaml | 18 +++--- 14 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 .changeset/grumpy-bikes-prove.md diff --git a/.changeset/grumpy-bikes-prove.md b/.changeset/grumpy-bikes-prove.md new file mode 100644 index 000000000000..42cf4a92c006 --- /dev/null +++ b/.changeset/grumpy-bikes-prove.md @@ -0,0 +1,9 @@ +--- +"wrangler": patch +--- + +fix: use account id for listing zones + +Fixes https://github.com/cloudflare/workers-sdk/issues/4944 + +Trying to fetch `/zones` fails when it spans more than 500 zones. The fix to use an account id when doing so. This patch passes the account id to the zones call, threading it through all the functions that require it. diff --git a/packages/wrangler/e2e/helpers/wrangler.ts b/packages/wrangler/e2e/helpers/wrangler.ts index 3eb2a176589b..b888422f5c4f 100644 --- a/packages/wrangler/e2e/helpers/wrangler.ts +++ b/packages/wrangler/e2e/helpers/wrangler.ts @@ -35,7 +35,10 @@ export class WranglerLongLivedCommand extends LongLivedCommand { } async waitForReady(): Promise<{ url: string }> { - const match = await this.readUntil(/Ready on (?https?:\/\/.*)/, 5_000); + const match = await this.readUntil( + /Ready on (?https?:\/\/.*)/, + 10_000 + ); return match.groups as { url: string }; } diff --git a/packages/wrangler/e2e/versions.test.ts b/packages/wrangler/e2e/versions.test.ts index 15a1c334a24f..037e2b44229d 100644 --- a/packages/wrangler/e2e/versions.test.ts +++ b/packages/wrangler/e2e/versions.test.ts @@ -315,7 +315,7 @@ describe("versions deploy", { timeout: TIMEOUT }, () => { ├ Finding latest stable Worker Version to rollback to │ │ - ? Please provide an optional message for this rollback (120 characters max)? + ? Please provide an optional message for this rollback (120 characters max) 🤖 Using default value in non-interactive context: Rollback via e2e test │ ├ WARNING You are about to rollback to Worker Version 00000000-0000-0000-0000-000000000000. @@ -425,7 +425,7 @@ describe("versions deploy", { timeout: TIMEOUT }, () => { │ Tag: e2e-upload │ Message: Upload via e2e test │ - ? Please provide an optional message for this rollback (120 characters max)? + ? Please provide an optional message for this rollback (120 characters max) 🤖 Using default value in non-interactive context: Rollback to old version │ ├ WARNING You are about to rollback to Worker Version 00000000-0000-0000-0000-000000000000. diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index a1112e0c1eed..33416c3a77e2 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -10400,12 +10400,19 @@ function mockUnauthorizedPublishRoutesRequest({ ); } -function mockGetZones(domain: string, zones: { id: string }[] = []) { +function mockGetZones( + domain: string, + zones: { id: string }[] = [], + accountId = "some-account-id" +) { msw.use( http.get("*/zones", ({ request }) => { const url = new URL(request.url); - expect([...url.searchParams.entries()]).toEqual([["name", domain]]); + expect([...url.searchParams.entries()]).toEqual([ + ["name", domain], + ["account.id", accountId], + ]); return HttpResponse.json( { diff --git a/packages/wrangler/src/__tests__/rollback.test.ts b/packages/wrangler/src/__tests__/rollback.test.ts index e79956d1d7af..37c1cfdcfbf9 100644 --- a/packages/wrangler/src/__tests__/rollback.test.ts +++ b/packages/wrangler/src/__tests__/rollback.test.ts @@ -119,7 +119,7 @@ describe("rollback", () => { mockPostDeployment(); mockPrompt({ - text: "Please provide a message for this rollback (120 characters max, optional)?", + text: "Please provide an optional message for this rollback (120 characters max)", result: "Test rollback", }); @@ -168,7 +168,7 @@ describe("rollback", () => { mockPostDeployment(true); mockPrompt({ - text: "Please provide a message for this rollback (120 characters max, optional)?", + text: "Please provide an optional message for this rollback (120 characters max)", result: "Test rollback", }); diff --git a/packages/wrangler/src/__tests__/zones.test.ts b/packages/wrangler/src/__tests__/zones.test.ts index 4fda35537edc..768a249ab18d 100644 --- a/packages/wrangler/src/__tests__/zones.test.ts +++ b/packages/wrangler/src/__tests__/zones.test.ts @@ -3,14 +3,21 @@ import { getHostFromUrl, getZoneForRoute } from "../zones"; import { mockAccountId, mockApiToken } from "./helpers/mock-account-id"; import { msw } from "./helpers/msw"; -function mockGetZones(domain: string, zones: { id: string }[] = []) { +function mockGetZones( + domain: string, + zones: { id: string }[] = [], + accountId = "some-account-id" +) { msw.use( http.get( "*/zones", ({ request }) => { const url = new URL(request.url); - expect([...url.searchParams.entries()]).toEqual([["name", domain]]); + expect([...url.searchParams.entries()]).toEqual([ + ["name", domain], + ["account.id", accountId], + ]); return HttpResponse.json( { @@ -67,7 +74,12 @@ describe("Zones", () => { describe("getZoneForRoute", () => { test("string route", async () => { mockGetZones("example.com", [{ id: "example-id" }]); - expect(await getZoneForRoute("example.com/*")).toEqual({ + expect( + await getZoneForRoute({ + route: "example.com/*", + accountId: "some-account-id", + }) + ).toEqual({ host: "example.com", id: "example-id", }); @@ -75,8 +87,9 @@ describe("Zones", () => { test("string route (not a zone)", async () => { mockGetZones("wrong.com", []); - await expect(getZoneForRoute("wrong.com/*")).rejects - .toMatchInlineSnapshot(` + await expect( + getZoneForRoute({ route: "wrong.com/*", accountId: "some-account-id" }) + ).rejects.toMatchInlineSnapshot(` [Error: Could not find zone for \`wrong.com\`. Make sure the domain is set up to be proxied by Cloudflare. For more details, refer to https://developers.cloudflare.com/workers/configuration/routing/routes/#set-up-a-route] `); @@ -86,7 +99,10 @@ describe("Zones", () => { // when a zone_id is provided in the route mockGetZones("example.com", [{ id: "example-id" }]); expect( - await getZoneForRoute({ pattern: "example.com/*", zone_id: "other-id" }) + await getZoneForRoute({ + route: { pattern: "example.com/*", zone_id: "other-id" }, + accountId: "some-account-id", + }) ).toEqual({ host: "example.com", id: "other-id", @@ -98,8 +114,11 @@ describe("Zones", () => { mockGetZones("example.com", [{ id: "example-id" }]); expect( await getZoneForRoute({ - pattern: "some.third-party.com/*", - zone_id: "other-id", + route: { + pattern: "some.third-party.com/*", + zone_id: "other-id", + }, + accountId: "some-account-id", }) ).toEqual({ host: "some.third-party.com", @@ -111,8 +130,11 @@ describe("Zones", () => { mockGetZones("example.com", [{ id: "example-id" }]); expect( await getZoneForRoute({ - pattern: "example.com/*", - zone_name: "example.com", + route: { + pattern: "example.com/*", + zone_name: "example.com", + }, + accountId: "some-account-id", }) ).toEqual({ host: "example.com", @@ -123,8 +145,11 @@ describe("Zones", () => { mockGetZones("example.com", [{ id: "example-id" }]); expect( await getZoneForRoute({ - pattern: "subdomain.example.com/*", - zone_name: "example.com", + route: { + pattern: "subdomain.example.com/*", + zone_name: "example.com", + }, + accountId: "some-account-id", }) ).toEqual({ host: "subdomain.example.com", @@ -135,8 +160,11 @@ describe("Zones", () => { mockGetZones("example.com", [{ id: "example-id" }]); expect( await getZoneForRoute({ - pattern: "some.third-party.com/*", - zone_name: "example.com", + route: { + pattern: "some.third-party.com/*", + zone_name: "example.com", + }, + accountId: "some-account-id", }) ).toEqual({ host: "some.third-party.com", diff --git a/packages/wrangler/src/deploy/deploy.ts b/packages/wrangler/src/deploy/deploy.ts index 22afa5fcf78c..204984cb7ef3 100644 --- a/packages/wrangler/src/deploy/deploy.ts +++ b/packages/wrangler/src/deploy/deploy.ts @@ -878,7 +878,13 @@ export async function publishRoutes( workerUrl, scriptName, notProd, - }: { workerUrl: string; scriptName: string; notProd: boolean } + accountId, + }: { + workerUrl: string; + scriptName: string; + notProd: boolean; + accountId: string; + } ): Promise { try { return await fetchResult(`${workerUrl}/routes`, { @@ -897,7 +903,11 @@ export async function publishRoutes( if (isAuthenticationError(e)) { // An authentication error is probably due to a known issue, // where the user is logged in via an API token that does not have "All Zones". - return await publishRoutesFallback(routes, { scriptName, notProd }); + return await publishRoutesFallback(routes, { + scriptName, + notProd, + accountId, + }); } else { throw e; } @@ -911,7 +921,11 @@ export async function publishRoutes( */ async function publishRoutesFallback( routes: Route[], - { scriptName, notProd }: { scriptName: string; notProd: boolean } + { + scriptName, + notProd, + accountId, + }: { scriptName: string; notProd: boolean; accountId: string } ) { if (notProd) { throw new UserError( @@ -932,7 +946,7 @@ async function publishRoutesFallback( const activeZones = new Map(); const routesToDeploy = new Map(); for (const route of routes) { - const zone = await getZoneForRoute(route); + const zone = await getZoneForRoute({ route, accountId }); if (zone) { activeZones.set(zone.id, zone.host); routesToDeploy.set( diff --git a/packages/wrangler/src/dev.tsx b/packages/wrangler/src/dev.tsx index c4c6b4ce3f40..ba2170179648 100644 --- a/packages/wrangler/src/dev.tsx +++ b/packages/wrangler/src/dev.tsx @@ -912,7 +912,10 @@ export async function validateDevServerSettings( // we want it to exit the Wrangler process early to allow the user to fix it. Calling it here forces // the error to be thrown where it will correctly exit the Wrangler process if (args.remote) { - await getZoneIdForPreview(host, routes); + const accountId = + args.accountId ?? config.account_id ?? getAccountFromCache()?.id; + assert(accountId, "Account ID must be provided for remote dev"); + await getZoneIdForPreview({ host, routes, accountId }); } const initialIp = args.ip || config.dev.ip; const initialIpListenCheck = initialIp === "*" ? "0.0.0.0" : initialIp; diff --git a/packages/wrangler/src/dev/remote.tsx b/packages/wrangler/src/dev/remote.tsx index 80083b8bdd14..aee5cd8991da 100644 --- a/packages/wrangler/src/dev/remote.tsx +++ b/packages/wrangler/src/dev/remote.tsx @@ -701,7 +701,11 @@ export async function getWorkerAccountAndContext(props: { }; // What zone should the realish preview for this Worker run on? - const zoneId = await getZoneIdForPreview(props.host, props.routes); + const zoneId = await getZoneIdForPreview({ + host: props.host, + routes: props.routes, + accountId: props.accountId, + }); const workerContext: CfWorkerContext = { env: props.env, diff --git a/packages/wrangler/src/tail/index.ts b/packages/wrangler/src/tail/index.ts index bbbb05cca939..52a2bddd12c3 100644 --- a/packages/wrangler/src/tail/index.ts +++ b/packages/wrangler/src/tail/index.ts @@ -99,9 +99,14 @@ export async function tailHandler(args: TailArgs) { let scriptName; + const accountId = await requireAuth(config); + // Worker names can't contain "." (and most routes should), so use that as a discriminator if (args.worker?.includes(".")) { - scriptName = await getWorkerForZone(args.worker); + scriptName = await getWorkerForZone({ + worker: args.worker, + accountId, + }); if (args.format === "pretty") { logger.log(`Connecting to worker ${scriptName} at route ${args.worker}`); } @@ -115,8 +120,6 @@ export async function tailHandler(args: TailArgs) { ); } - const accountId = await requireAuth(config); - const cliFilters: TailCLIFilters = { status: args.status as ("ok" | "error" | "canceled")[] | undefined, header: args.header, diff --git a/packages/wrangler/src/triggers/deploy.ts b/packages/wrangler/src/triggers/deploy.ts index bf334cf6d02b..90a00cf8d3c0 100644 --- a/packages/wrangler/src/triggers/deploy.ts +++ b/packages/wrangler/src/triggers/deploy.ts @@ -146,7 +146,7 @@ export default async function triggersDeploy(props: Props): Promise { // to bother with all the error handling tomfoolery. const routesWithOtherBindings: Record = {}; for (const route of routes) { - const zone = await getZoneForRoute(route); + const zone = await getZoneForRoute({ route, accountId }); if (!zone) { continue; } @@ -194,7 +194,12 @@ export default async function triggersDeploy(props: Props): Promise { // Update routing table for the script. if (routesOnly.length > 0) { deployments.push( - publishRoutes(routesOnly, { workerUrl, scriptName, notProd }).then(() => { + publishRoutes(routesOnly, { + workerUrl, + scriptName, + notProd, + accountId, + }).then(() => { if (routesOnly.length > 10) { return routesOnly .slice(0, 9) diff --git a/packages/wrangler/src/versions/rollback/index.ts b/packages/wrangler/src/versions/rollback/index.ts index 90bf2e07e2c7..bdddcd736b43 100644 --- a/packages/wrangler/src/versions/rollback/index.ts +++ b/packages/wrangler/src/versions/rollback/index.ts @@ -85,7 +85,7 @@ export async function versionsRollbackHandler(args: VersionsRollbackArgs) { })); const message = await prompt( - "Please provide an optional message for this rollback (120 characters max)?", + "Please provide an optional message for this rollback (120 characters max)", { defaultValue: args.message ?? "Rollback", } diff --git a/packages/wrangler/src/zones.ts b/packages/wrangler/src/zones.ts index cb3da6d5412d..f32f5f249079 100644 --- a/packages/wrangler/src/zones.ts +++ b/packages/wrangler/src/zones.ts @@ -49,16 +49,20 @@ export function getHostFromRoute(route: Route): string | undefined { * - We try to extract a host from it * - We try to get a zone id from the host */ -export async function getZoneForRoute(route: Route): Promise { +export async function getZoneForRoute(from: { + route: Route; + accountId: string; +}): Promise { + const { route, accountId } = from; const host = getHostFromRoute(route); let id: string | undefined; if (typeof route === "object" && "zone_id" in route) { id = route.zone_id; } else if (typeof route === "object" && "zone_name" in route) { - id = await getZoneIdFromHost(route.zone_name); + id = await getZoneIdFromHost({ host: route.zone_name, accountId }); } else if (host) { - id = await getZoneIdFromHost(host); + id = await getZoneIdFromHost({ host, accountId }); } return id && host ? { id, host } : undefined; @@ -93,17 +97,19 @@ export function getHostFromUrl(urlLike: string): string | undefined { return undefined; } } -export async function getZoneIdForPreview( - host: string | undefined, - routes: Route[] | undefined -) { +export async function getZoneIdForPreview(from: { + host: string | undefined; + routes: Route[] | undefined; + accountId: string; +}) { + const { host, routes, accountId } = from; let zoneId: string | undefined; if (host) { - zoneId = await getZoneIdFromHost(host); + zoneId = await getZoneIdFromHost({ host, accountId }); } if (!zoneId && routes) { const firstRoute = routes[0]; - const zone = await getZoneForRoute(firstRoute); + const zone = await getZoneForRoute({ route: firstRoute, accountId }); if (zone) { zoneId = zone.id; } @@ -117,14 +123,20 @@ export async function getZoneIdForPreview( * For each domain-like part of the host (e.g. w.x.y.z) try to get a zone id for it by * lopping off subdomains until we get a hit from the API. */ -export async function getZoneIdFromHost(host: string): Promise { - const hostPieces = host.split("."); +export async function getZoneIdFromHost(from: { + host: string; + accountId: string; +}): Promise { + const hostPieces = from.host.split("."); while (hostPieces.length > 1) { const zones = await fetchListResult<{ id: string }>( `/zones`, {}, - new URLSearchParams({ name: hostPieces.join(".") }) + new URLSearchParams({ + name: hostPieces.join("."), + "account.id": from.accountId, + }) ); if (zones.length > 0) { return zones[0].id; @@ -133,7 +145,7 @@ export async function getZoneIdFromHost(host: string): Promise { } throw new UserError( - `Could not find zone for \`${host}\`. Make sure the domain is set up to be proxied by Cloudflare.\nFor more details, refer to https://developers.cloudflare.com/workers/configuration/routing/routes/#set-up-a-route` + `Could not find zone for \`${from.host}\`. Make sure the domain is set up to be proxied by Cloudflare.\nFor more details, refer to https://developers.cloudflare.com/workers/configuration/routing/routes/#set-up-a-route` ); } @@ -200,8 +212,12 @@ export function findClosestRoute( /** * Given a route (must be assigned and within the correct zone), return the name of the worker assigned to it */ -export async function getWorkerForZone(worker: string) { - const zone = await getZoneForRoute(worker); +export async function getWorkerForZone(from: { + worker: string; + accountId: string; +}) { + const { worker, accountId } = from; + const zone = await getZoneForRoute({ route: worker, accountId }); if (!zone) { throw new UserError( `The route '${worker}' is not part of one of your zones. Either add this zone from the Cloudflare dashboard, or try using a route within one of your existing zones.` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a60f910f2bce..90b2bd03e763 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13234,8 +13234,8 @@ snapshots: '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) eslint-plugin-jest-dom: 4.0.3(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) @@ -15817,13 +15817,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0): + eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 4.3.4(supports-color@9.2.2) enhanced-resolve: 5.14.1 eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) get-tsconfig: 4.6.0 globby: 13.1.4 is-core-module: 2.13.0 @@ -15835,14 +15835,14 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -15924,7 +15924,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0): + eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: array-includes: 3.1.6 array.prototype.flat: 1.3.1 @@ -15933,7 +15933,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3