From 64edc9b4eb19ae819dc320d2f45112ec38f4c8a7 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Tue, 15 Jul 2025 14:45:54 -0700 Subject: [PATCH 1/2] Convert src/rest/lib/index.js to TypeScript (#56410) --- src/rest/lib/{index.js => index.ts} | 115 ++++++++++++++++++---------- src/rest/pages/category.tsx | 7 +- src/rest/pages/subcategory.tsx | 5 +- src/rest/tests/rendering.js | 4 +- 4 files changed, 85 insertions(+), 46 deletions(-) rename src/rest/lib/{index.js => index.ts} (51%) diff --git a/src/rest/lib/index.js b/src/rest/lib/index.ts similarity index 51% rename from src/rest/lib/index.js rename to src/rest/lib/index.ts index 748d7d1920b5..47d96dfb1c2d 100644 --- a/src/rest/lib/index.js +++ b/src/rest/lib/index.ts @@ -5,11 +5,26 @@ import { readCompressedJsonFileFallback } from '@/frame/lib/read-json-file' import { getAutomatedPageMiniTocItems } from '@/frame/lib/get-mini-toc-items' import { allVersions, getOpenApiVersion } from '@/versions/lib/all-versions' import languages from '@/languages/lib/languages' +import type { Context } from '@/types' +import type { Operation } from '@/rest/components/types' export const REST_DATA_DIR = 'src/rest/data' export const REST_SCHEMA_FILENAME = 'schema.json' const REST_CONTENT_DIR = 'content/rest' +// Type definitions for REST operations +interface RestOperationCategory { + [subcategory: string]: Operation[] +} + +interface RestOperationData { + [category: string]: RestOperationCategory +} + +interface RestMiniTocData { + restOperationsMiniTocItems: any[] +} + /* Loads the schemas from the static/decorated folder into a single object organized by version. Not all products are calendar date @@ -38,87 +53,107 @@ const REST_CONTENT_DIR = 'content/rest' } */ const NOT_API_VERSIONED = 'not_api_versioned' -const restOperationData = new Map() -const restOperations = new Map() +const restOperationData = new Map< + string, + Map>>> +>() +const restOperations = new Map>() -Object.keys(languages).forEach((language) => { +Object.keys(languages).forEach((language: string) => { restOperationData.set(language, new Map()) - Object.keys(allVersions).forEach((version) => { + Object.keys(allVersions).forEach((version: string) => { // setting to undefined will allow us to perform checks // more easily later on - restOperationData.get(language).set(version, new Map()) + restOperationData.get(language)!.set(version, new Map()) if (allVersions[version].apiVersions && allVersions[version].apiVersions.length > 0) { - allVersions[version].apiVersions.forEach((date) => { - restOperationData.get(language).get(version).set(date, new Map()) + allVersions[version].apiVersions.forEach((date: string) => { + restOperationData.get(language)!.get(version)!.set(date, new Map()) }) } else { // Products that are not been calendar date versioned - restOperationData.get(language).get(version).set(NOT_API_VERSIONED, new Map()) + restOperationData.get(language)!.get(version)!.set(NOT_API_VERSIONED, new Map()) } }) }) -export const categoriesWithoutSubcategories = fs +export const categoriesWithoutSubcategories: string[] = fs .readdirSync(REST_CONTENT_DIR) - .filter((file) => { + .filter((file: string) => { return file.endsWith('.md') && !file.includes('index.md') && !file.includes('README.md') }) - .map((filteredFile) => filteredFile.replace('.md', '')) + .map((filteredFile: string) => filteredFile.replace('.md', '')) // version: plan + release e.g. For ghes-3.5, ghes is the plan and 3.5 is the release // apiVersion (not all versions have apiVersions): REST API Calendar Dates // openApiVersion (below, every version has an openApiVersion mapping): There's a mapping between our Docs versions // and the OpenApi Version bc it's not the same -export default async function getRest(version, apiVersion, category, subCategory) { + +export default async function getRest( + version: string, + apiVersion?: string, +): Promise { const openApiVersion = getOpenApiVersion(version) const openapiSchemaName = apiVersion ? `${openApiVersion}-${apiVersion}` : `${openApiVersion}` const apiDate = apiVersion || NOT_API_VERSIONED const fileName = path.join(REST_DATA_DIR, openapiSchemaName, REST_SCHEMA_FILENAME) + if (!restOperations.has(openApiVersion)) { restOperations.set(openApiVersion, new Map()) - restOperations.get(openApiVersion).set(apiDate, new Map()) // The `readCompressedJsonFileFallback()` function // will check for both a .br and .json extension. - restOperations.get(openApiVersion).set(apiDate, readCompressedJsonFileFallback(fileName)) - } else if (!restOperations.get(openApiVersion).has(apiDate)) { - restOperations.get(openApiVersion).set(apiDate, new Map()) + restOperations + .get(openApiVersion)! + .set(apiDate, readCompressedJsonFileFallback(fileName) as RestOperationData) + } else if (!restOperations.get(openApiVersion)!.has(apiDate)) { // The `readCompressedJsonFileFallback()` function // will check for both a .br and .json extension. - restOperations.get(openApiVersion).set(apiDate, readCompressedJsonFileFallback(fileName)) - } - if (subCategory) { - return restOperations.get(openApiVersion).get(apiDate)[category][subCategory] - } else if (category) { - return restOperations.get(openApiVersion).get(apiDate)[category] - } else { - return restOperations.get(openApiVersion).get(apiDate) + restOperations + .get(openApiVersion)! + .set(apiDate, readCompressedJsonFileFallback(fileName) as RestOperationData) } + + return restOperations.get(openApiVersion)!.get(apiDate)! } // Generates the miniToc for a rest reference page. export async function getRestMiniTocItems( - category, - subCategory, - apiVersion, - restOperations, - language, - version, - context, -) { + category: string, + subCategory: string, + apiVersion: string | undefined, + restOperations: Operation[], + language: string, + version: string, + context: Context, +): Promise { const apiDate = apiVersion || NOT_API_VERSIONED - if (!restOperationData.get(language).get(version).get(apiDate).has(category)) { - restOperationData.get(language).get(version).get(apiDate).set(category, new Map()) + const languageData = restOperationData.get(language) + if (!languageData) { + throw new Error(`Language ${language} not found in rest operation data`) + } + + const versionData = languageData.get(version) + if (!versionData) { + throw new Error(`Version ${version} not found for language ${language}`) + } + + const apiData = versionData.get(apiDate) + if (!apiData) { + throw new Error(`API date ${apiDate} not found for version ${version} and language ${language}`) + } + + if (!apiData.has(category)) { + apiData.set(category, new Map()) } - if (!restOperationData.get(language).get(version).get(apiDate).get(category).get(subCategory)) { - const languageTree = restOperationData.get(language) - const titles = restOperations.map((operation) => operation.title) + const categoryData = apiData.get(category)! + if (!categoryData.get(subCategory)) { + const titles = restOperations.map((operation: Operation) => operation.title) const restOperationsMiniTocItems = await getAutomatedPageMiniTocItems(titles, context, 3) - languageTree.get(version).get(apiDate).get(category).set(subCategory, { + categoryData.set(subCategory, { restOperationsMiniTocItems, }) - restOperationData.set(restOperationData, languageTree) } - return restOperationData.get(language).get(version).get(apiDate).get(category).get(subCategory) + + return categoryData.get(subCategory)! } diff --git a/src/rest/pages/category.tsx b/src/rest/pages/category.tsx index 06d22bc86e41..e14eaf70fcd2 100644 --- a/src/rest/pages/category.tsx +++ b/src/rest/pages/category.tsx @@ -60,7 +60,7 @@ export default function Category({ } export const getServerSideProps: GetServerSideProps = async (context) => { - const { default: getRest, getRestMiniTocItems } = await import('@/rest/lib/index.js') + const { default: getRest, getRestMiniTocItems } = await import('@/rest/lib/index') const nonEnterpriseDefaultVersionModule = await import( 'src/versions/lib/non-enterprise-default-version.js' ) @@ -86,7 +86,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => subcategory = category } - const restOperations = (await getRest(currentVersion, apiVersion, category, subcategory)) || [] + const restData = await getRest(currentVersion, apiVersion) + const restOperations = (restData && restData[category] && restData[category][subcategory]) || [] // Build table of contents for all category operations for TocLanding: // @@ -94,7 +95,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => // * loop over subcategories and get the operations per subcategory // * get the minitoc items per set of subcategory operations // * with this data, build a collection of toc items that can be used by TocLanding - const restCategoryOperations = (await getRest(currentVersion, apiVersion, category)) || [] + const restCategoryOperations = (restData && restData[category]) || {} const restCategoryTocItems = [] for (const [subCat, subCatOperations] of Object.entries(restCategoryOperations)) { diff --git a/src/rest/pages/subcategory.tsx b/src/rest/pages/subcategory.tsx index 6bb9e8439080..b6d7774f2efb 100644 --- a/src/rest/pages/subcategory.tsx +++ b/src/rest/pages/subcategory.tsx @@ -35,7 +35,7 @@ export default function SubCategory({ mainContext, automatedPageContext, restOpe } export const getServerSideProps: GetServerSideProps = async (context) => { - const { default: getRest, getRestMiniTocItems } = await import('@/rest/lib/index.js') + const { default: getRest, getRestMiniTocItems } = await import('@/rest/lib/index') const req = context.req as any const res = context.res as any @@ -55,7 +55,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => subCategory = category } - const restOperations = (await getRest(currentVersion, apiVersion, category, subCategory)) || [] + const restData = await getRest(currentVersion, apiVersion) + const restOperations = (restData && restData[category] && restData[category][subCategory]) || [] // Gets the miniTocItems in the article context. At this point it will only // include miniTocItems generated from the Markdown pages in diff --git a/src/rest/tests/rendering.js b/src/rest/tests/rendering.js index d22774fb9c91..c9f6021d064a 100644 --- a/src/rest/tests/rendering.js +++ b/src/rest/tests/rendering.js @@ -15,7 +15,9 @@ describe('REST references docs', () => { test('loads schema data for all versions', async () => { for (const version of Object.keys(allVersions)) { const calendarDate = allVersions[version].latestApiVersion - const checksRestOperations = await getRest(version, calendarDate, 'checks', 'runs') + const restData = await getRest(version, calendarDate) + const checksRestOperations = + (restData && restData['checks'] && restData['checks']['runs']) || [] const $ = await getDOM(`/en/${version}/rest/checks/runs?restVersion=${calendarDate}`) const domH2Ids = $('h2') .map((i, h2) => $(h2).attr('id')) From 77ac78ecb5b18f5200fa138ecee44f538892977d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 23:39:10 +0000 Subject: [PATCH 2/2] Bump github/gh-base-image/gh-base-noble from 20250711-165924-g6f92253c7 to 20250715-152201-gef17a3886 in the baseimages group (#56656) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8db3546ebf73..f9a1d3877238 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ # --------------------------------------------------------------- # To update the sha: # https://github.com/github/gh-base-image/pkgs/container/gh-base-image%2Fgh-base-noble -FROM ghcr.io/github/gh-base-image/gh-base-noble:20250711-165924-g6f92253c7 AS base +FROM ghcr.io/github/gh-base-image/gh-base-noble:20250715-152201-gef17a3886 AS base # Install curl for Node install and determining the early access branch # Install git for cloning docs-early-access & translations repos