diff --git a/packages/service-clients/odsp-client/package.json b/packages/service-clients/odsp-client/package.json index 93a7d1f3954e..52a3c19f0eef 100644 --- a/packages/service-clients/odsp-client/package.json +++ b/packages/service-clients/odsp-client/package.json @@ -106,6 +106,7 @@ "dependencies": { "@fluidframework/container-definitions": "workspace:~", "@fluidframework/container-loader": "workspace:~", + "@fluidframework/container-runtime-definitions": "workspace:~", "@fluidframework/core-interfaces": "workspace:~", "@fluidframework/core-utils": "workspace:~", "@fluidframework/driver-definitions": "workspace:~", @@ -114,6 +115,7 @@ "@fluidframework/odsp-doclib-utils": "workspace:~", "@fluidframework/odsp-driver": "workspace:~", "@fluidframework/odsp-driver-definitions": "workspace:~", + "@fluidframework/runtime-utils": "workspace:~", "@fluidframework/telemetry-utils": "workspace:~", "uuid": "^11.1.0" }, diff --git a/packages/service-clients/odsp-client/src/odspClient.ts b/packages/service-clients/odsp-client/src/odspClient.ts index 44459bd74d50..cf0e9029138c 100644 --- a/packages/service-clients/odsp-client/src/odspClient.ts +++ b/packages/service-clients/odsp-client/src/odspClient.ts @@ -13,7 +13,9 @@ import { loadExistingContainer, type ILoaderProps, } from "@fluidframework/container-loader/internal"; +import type { IContainerRuntimeInternal } from "@fluidframework/container-runtime-definitions/internal"; import type { + FluidObject, IConfigProviderBase, IRequest, ITelemetryBaseLogger, @@ -232,6 +234,37 @@ export class OdspClient { } private async getContainerServices(container: IContainer): Promise { - return new OdspContainerServices(container); + const runtimeInternal = await this.getRuntimeInternal(container); + // Get the resolved URL for ODSP-specific URL building + const resolvedUrl = container.resolvedUrl; + const odspResolvedUrl = + resolvedUrl && isOdspResolvedUrl(resolvedUrl) ? resolvedUrl : undefined; + return new OdspContainerServices(container, odspResolvedUrl, runtimeInternal); } + + private async getRuntimeInternal( + container: IContainer, + ): Promise { + const entryPoint = await container.getEntryPoint(); + if ( + entryPoint !== undefined && + typeof (entryPoint as IMaybeFluidObjectWithContainerRuntime).IStaticEntryPoint + ?.extensionStore === "function" + ) { + // If the container has a static entry point with an extension store, use that to get the runtime + return (entryPoint as IMaybeFluidObjectWithContainerRuntime).IStaticEntryPoint + .extensionStore; + } + } +} + +/** + * Unclear if this is the best way to go about accessing the runtime internal from the entry point. + * We need it for IContainerRuntimeInternal.lookupTemporaryBlobStorageId, + * and fluid-static guarantees this exists on the container's entry point, but it is not exposed publicly. + */ +interface IMaybeFluidObjectWithContainerRuntime extends FluidObject { + IStaticEntryPoint: { + extensionStore: IContainerRuntimeInternal; + }; } diff --git a/packages/service-clients/odsp-client/src/odspContainerServices.ts b/packages/service-clients/odsp-client/src/odspContainerServices.ts index 10cf8926293e..cbbf905a0b16 100644 --- a/packages/service-clients/odsp-client/src/odspContainerServices.ts +++ b/packages/service-clients/odsp-client/src/odspContainerServices.ts @@ -4,7 +4,11 @@ */ import type { IContainer } from "@fluidframework/container-definitions/internal"; +import type { IContainerRuntimeInternal } from "@fluidframework/container-runtime-definitions/internal"; +import type { IFluidHandle } from "@fluidframework/core-interfaces"; import { createServiceAudience } from "@fluidframework/fluid-static/internal"; +import type { IOdspResolvedUrl } from "@fluidframework/odsp-driver-definitions/internal"; +import { lookupTemporaryBlobStorageId } from "@fluidframework/runtime-utils/internal"; import type { IOdspAudience, @@ -12,16 +16,82 @@ import type { } from "./interfaces.js"; import { createOdspAudienceMember } from "./odspAudience.js"; +/** + * Helper function to build a blob URL from a storage ID using ODSP-specific logic + * @param storageId - The storage ID of the blob + * @param resolvedUrl - The ODSP resolved URL containing endpoint information + * @returns The blob URL if it can be built, undefined otherwise + */ +function buildOdspBlobUrl( + storageId: string, + resolvedUrl: IOdspResolvedUrl, +): string | undefined { + try { + const attachmentGETUrl = resolvedUrl.endpoints.attachmentGETStorageUrl; + if (!attachmentGETUrl) { + return undefined; + } + return `${attachmentGETUrl}/${encodeURIComponent(storageId)}/content`; + } catch { + return undefined; + } +} + +/** + * Helper function for ODSPClient to lookup blob URLs + * @param runtimeInternal - The container runtime internal interface + * @param handle - The blob handle to lookup the URL for + * @param resolvedUrl - The ODSP resolved URL containing endpoint information + * @returns The blob URL if found and the blob is not pending, undefined otherwise + */ +function lookupOdspBlobURL( + runtimeInternal: IContainerRuntimeInternal, + handle: IFluidHandle, + resolvedUrl: IOdspResolvedUrl, +): string | undefined { + try { + if ( + runtimeInternal !== undefined && + typeof (runtimeInternal as { lookupTemporaryBlobStorageId?: unknown }) + .lookupTemporaryBlobStorageId === "function" + ) { + // Get the storage ID from the runtime + const storageId = lookupTemporaryBlobStorageId(runtimeInternal, handle); + if (storageId === undefined) { + return undefined; + } + + // Build the URL using ODSP-specific logic + return buildOdspBlobUrl(storageId, resolvedUrl); + } + return undefined; + } catch { + return undefined; + } +} + /** * @internal */ export class OdspContainerServices implements IOdspContainerServices { public readonly audience: IOdspAudience; - public constructor(container: IContainer) { + public constructor( + container: IContainer, + private readonly odspResolvedUrl?: IOdspResolvedUrl, + private readonly containerRuntimeInternal?: IContainerRuntimeInternal, + ) { this.audience = createServiceAudience({ container, createServiceMember: createOdspAudienceMember, }); } + + public lookupTemporaryBlobURL(handle: IFluidHandle): string | undefined { + if (!this.odspResolvedUrl || this.containerRuntimeInternal === undefined) { + // Can't build URLs without ODSP resolved URL information + return undefined; + } + return lookupOdspBlobURL(this.containerRuntimeInternal, handle, this.odspResolvedUrl); + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee01b118240f..e7cbc5d813a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,7 +123,7 @@ importers: version: 0.58.3(@types/node@18.19.86) '@fluidframework/eslint-config-fluid': specifier: ^8.1.0 - version: 8.1.0(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)(typescript@5.4.5) + version: 8.1.0(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)(typescript@5.9.2) eslint: specifier: ~8.57.1 version: 8.57.1 @@ -13561,6 +13561,9 @@ importers: '@fluidframework/container-loader': specifier: workspace:~ version: link:../../loader/container-loader + '@fluidframework/container-runtime-definitions': + specifier: workspace:~ + version: link:../../runtime/container-runtime-definitions '@fluidframework/core-interfaces': specifier: workspace:~ version: link:../../common/core-interfaces @@ -13585,6 +13588,9 @@ importers: '@fluidframework/odsp-driver-definitions': specifier: workspace:~ version: link:../../drivers/odsp-driver-definitions + '@fluidframework/runtime-utils': + specifier: workspace:~ + version: link:../../runtime/runtime-utils '@fluidframework/telemetry-utils': specifier: workspace:~ version: link:../../utils/telemetry-utils @@ -30077,6 +30083,17 @@ snapshots: - supports-color - typescript + '@fluid-internal/eslint-plugin-fluid@0.4.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@typescript-eslint/parser': 8.46.3(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/utils': 8.46.3(eslint@8.57.1)(typescript@5.9.2) + eslint: 8.57.1 + ts-morph: 22.0.0 + transitivePeerDependencies: + - supports-color + - typescript + '@fluid-internal/test-driver-definitions@2.71.0': dependencies: '@fluidframework/core-interfaces': 2.71.0 @@ -30822,6 +30839,34 @@ snapshots: - supports-color - typescript + '@fluidframework/eslint-config-fluid@8.1.0(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@fluid-internal/eslint-plugin-fluid': 0.4.0(eslint@8.57.1)(typescript@5.9.2) + '@rushstack/eslint-patch': 1.12.0 + '@rushstack/eslint-plugin': 0.19.0(eslint@8.57.1)(typescript@5.9.2) + '@rushstack/eslint-plugin-security': 0.11.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.2) + eslint-config-biome: 2.1.3 + eslint-config-prettier: 10.1.8(eslint@8.57.1) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + eslint-plugin-jsdoc: 55.0.5(eslint@8.57.1) + eslint-plugin-promise: 7.2.1(eslint@8.57.1) + eslint-plugin-react: 7.37.5(eslint@8.57.1) + eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) + eslint-plugin-tsdoc: 0.4.0 + eslint-plugin-unicorn: 48.0.1(eslint@8.57.1) + eslint-plugin-unused-imports: 4.2.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + transitivePeerDependencies: + - '@typescript-eslint/utils' + - eslint + - eslint-import-resolver-node + - eslint-plugin-import + - supports-color + - typescript + '@fluidframework/file-driver@2.71.0': dependencies: '@fluid-internal/client-utils': 2.71.0 @@ -33089,6 +33134,15 @@ snapshots: - supports-color - typescript + '@rushstack/eslint-plugin-security@0.11.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@rushstack/tree-pattern': 0.3.4 + '@typescript-eslint/utils': 8.31.1(eslint@8.57.1)(typescript@5.9.2) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + '@rushstack/eslint-plugin@0.19.0(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@rushstack/tree-pattern': 0.3.4 @@ -33098,6 +33152,15 @@ snapshots: - supports-color - typescript + '@rushstack/eslint-plugin@0.19.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@rushstack/tree-pattern': 0.3.4 + '@typescript-eslint/utils': 8.31.1(eslint@8.57.1)(typescript@5.9.2) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + '@rushstack/node-core-library@3.66.1(@types/node@18.19.86)': dependencies: colors: 1.2.5 @@ -33860,6 +33923,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.9.2) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 @@ -33873,6 +33954,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3(supports-color@8.1.1) + eslint: 8.57.1 + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.46.3(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@typescript-eslint/scope-manager': 8.46.3 @@ -33885,6 +33979,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.46.3(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.46.3 + debug: 4.4.3(supports-color@8.1.1) + eslint: 8.57.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/project-service@8.46.3(typescript@5.4.5)': dependencies: '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.4.5) @@ -33894,6 +34000,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.46.3(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.2) + '@typescript-eslint/types': 8.46.3 + debug: 4.4.3(supports-color@8.1.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -33918,6 +34033,10 @@ snapshots: dependencies: typescript: 5.4.5 + '@typescript-eslint/tsconfig-utils@8.46.3(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) @@ -33930,6 +34049,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.9.2) + debug: 4.4.3(supports-color@8.1.1) + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.9.2) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@7.18.0': {} @@ -33967,6 +34098,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 1.4.3(typescript@5.9.2) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.31.1(typescript@5.4.5)': dependencies: '@typescript-eslint/types': 8.31.1 @@ -33981,6 +34127,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.31.1(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/visitor-keys': 8.31.1 + debug: 4.4.3(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.46.3(typescript@5.4.5)': dependencies: '@typescript-eslint/project-service': 8.46.3(typescript@5.4.5) @@ -33997,6 +34157,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.46.3(typescript@5.9.2)': + dependencies: + '@typescript-eslint/project-service': 8.46.3(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.2) + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/visitor-keys': 8.46.3 + debug: 4.4.3(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) @@ -34023,6 +34199,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.2) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@8.31.1(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) @@ -34034,6 +34221,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.31.1(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.31.1 + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.9.2) + eslint: 8.57.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) @@ -34045,6 +34243,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.2) + eslint: 8.57.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -36352,6 +36561,21 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1))(eslint@8.57.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + eslint: 8.57.1 + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + get-tsconfig: 4.12.0 + is-bun-module: 2.0.0 + stable-hash-x: 0.2.0 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + transitivePeerDependencies: + - supports-color + eslint-plugin-chai-expect@3.0.0(eslint@8.57.1): dependencies: eslint: 8.57.1 @@ -36380,6 +36604,24 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.3(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): + dependencies: + '@typescript-eslint/types': 8.46.3 + comment-parser: 1.4.1 + debug: 4.4.3(supports-color@8.1.1) + eslint: 8.57.1 + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + is-glob: 4.0.3 + minimatch: 10.0.3 + semver: 7.7.3 + stable-hash-x: 0.2.0 + unrs-resolver: 1.11.1 + optionalDependencies: + '@typescript-eslint/utils': 8.46.3(eslint@8.57.1)(typescript@5.9.2) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + eslint-plugin-jest@27.4.3(eslint@8.57.1)(jest@29.7.0(@types/node@18.19.86)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@18.19.86)(typescript@5.4.5)))(typescript@5.4.5): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.4.5) @@ -36492,6 +36734,12 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5) + eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2) + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 @@ -42890,10 +43138,18 @@ snapshots: dependencies: typescript: 5.4.5 + ts-api-utils@1.4.3(typescript@5.9.2): + dependencies: + typescript: 5.9.2 + ts-api-utils@2.1.0(typescript@5.4.5): dependencies: typescript: 5.4.5 + ts-api-utils@2.1.0(typescript@5.9.2): + dependencies: + typescript: 5.9.2 + ts-deepmerge@7.0.2: {} ts-interface-checker@0.1.13: {}