diff --git a/website/src/components/playground-component/import-map.ts b/website/src/components/playground-component/import-map.ts index bfb5e2b18c..0d311c7aa8 100644 --- a/website/src/components/playground-component/import-map.ts +++ b/website/src/components/playground-component/import-map.ts @@ -9,10 +9,41 @@ export interface ImportMap { imports: Record; } +const pkgsBaseUrl = "https://typespec.blob.core.windows.net/pkgs"; + +async function fetchAdditionalPackageImports( + packageNames: readonly string[], +): Promise> { + const imports: Record = {}; + + const results = await Promise.allSettled( + packageNames.map(async (name) => { + const url = `${pkgsBaseUrl}/${name}/latest.json`; + const response = await fetch(url); + if (!response.ok) { + // eslint-disable-next-line no-console + console.warn(`Failed to load latest index for ${name}: ${response.status}`); + return undefined; + } + return JSON.parse(await response.text()) as ImportMap; + }), + ); + + for (const result of results) { + if (result.status === "fulfilled" && result.value) { + Object.assign(imports, result.value.imports); + } + } + + return imports; +} + export async function loadImportMap({ latestVersion, + additionalPackages = [], }: { latestVersion: string; + additionalPackages?: readonly string[]; }): Promise { const optionsScript = document.querySelector("script[type=playground-options]"); if (optionsScript === undefined) { @@ -24,15 +55,19 @@ export async function loadImportMap({ const parsed = new URLSearchParams(window.location.search); const requestedVersion = parsed.get("version"); - const importMapUrl = `https://typespec.blob.core.windows.net/pkgs/indexes/azure/${ - requestedVersion ?? latestVersion - }.json`; + const importMapUrl = `${pkgsBaseUrl}/indexes/azure/${requestedVersion ?? latestVersion}.json`; - const response = await fetch(importMapUrl); - const content = await response.text(); + const [mainResponse, additionalImports] = await Promise.all([ + fetch(importMapUrl), + fetchAdditionalPackageImports(additionalPackages), + ]); + const content = await mainResponse.text(); const importMap = JSON.parse(content); + // Merge additional imports into the main import map + Object.assign(importMap.imports, additionalImports); + (window as any).importShim.addImportMap(importMap); return { diff --git a/website/src/components/react-pages/playground.tsx b/website/src/components/react-pages/playground.tsx index a5b8fc0ee2..d3c032acef 100644 --- a/website/src/components/react-pages/playground.tsx +++ b/website/src/components/react-pages/playground.tsx @@ -3,6 +3,8 @@ import "@typespec/playground/styles.css"; import { useEffect, useState, type ReactNode } from "react"; import { loadImportMap, type VersionData } from "../playground-component/import-map"; +const additionalPlaygroundPackages = ["@typespec/http-client-python"]; + export const AsyncPlayground = ({ latestVersion, fallback, @@ -15,7 +17,10 @@ export const AsyncPlayground = ({ WebsitePlayground: typeof import("../playground-component/playground").WebsitePlayground; }>(undefined as any); useEffect(() => { - Promise.all([loadImportMap({ latestVersion }), import("../playground-component/playground")]) + Promise.all([ + loadImportMap({ latestVersion, additionalPackages: additionalPlaygroundPackages }), + import("../playground-component/playground"), + ]) .then((x) => setMod({ versionData: x[0] as any, WebsitePlayground: x[1].WebsitePlayground })) .catch((e) => { throw e;