From 232a0f8516bab1f9906512ea59e21c891045d7b6 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Mon, 27 Oct 2025 15:01:39 -0700 Subject: [PATCH] Eslint review, round 1 (#58168) --- eslint.config.ts | 66 +++++-------------- package.json | 14 ++-- .../archived-enterprise-versions.ts | 2 +- .../scripts/deleted-assets-pr-comment.ts | 2 +- src/assets/scripts/find-orphaned-assets.ts | 8 ++- src/assets/tests/static-assets.ts | 2 +- src/audit-logs/lib/index.ts | 12 ++-- src/audit-logs/pages/audit-log-events.tsx | 4 +- .../lib/helpers/should-include-result.ts | 2 +- .../liquid-ifversion-versions.ts | 2 +- .../linting-rules/note-warning-formatting.ts | 2 +- .../outdated-release-phase-terminology.ts | 4 +- src/content-linter/tests/lint-files.ts | 4 +- src/content-render/liquid/ifversion.ts | 2 +- src/content-render/liquid/prompt.ts | 2 +- src/content-render/liquid/spotlight.ts | 2 +- src/content-render/liquid/tool.ts | 2 +- .../scripts/deleted-features-pr-comment.ts | 2 +- src/data-directory/tests/index.ts | 2 +- src/events/middleware.ts | 2 +- src/events/types.ts | 4 +- src/fixtures/tests/annotations.ts | 2 +- .../tests/playwright-rendering.spec.ts | 4 +- .../components/context/SharedUIContext.tsx | 4 +- src/frame/components/hooks/useFeatureFlags.ts | 2 +- .../UnrenderedMarkdownContent.tsx | 4 +- src/frame/lib/read-frontmatter.ts | 3 +- src/frame/lib/warm-server.ts | 16 ++++- src/frame/middleware/api.ts | 2 +- src/frame/middleware/block-robots.ts | 2 +- src/frame/middleware/context/generic-toc.ts | 2 +- src/frame/middleware/helmet.ts | 4 +- src/frame/middleware/index.ts | 12 ++-- .../scripts/create-enterprise-issue.ts | 2 +- .../scripts/deprecate/archive-version.ts | 5 +- .../scripts/deprecate/rewrite-asset-paths.ts | 18 ++++- src/github-apps/lib/index.ts | 4 +- src/github-apps/scripts/sync.ts | 2 +- src/graphql/pages/reference.tsx | 2 +- src/graphql/scripts/sync.ts | 2 +- .../components/ProductSelectionCard.tsx | 38 +++++++++-- src/languages/lib/render-with-fallback.ts | 2 +- .../middleware/learning-track.ts | 2 +- .../scripts/check-github-github-links.ts | 5 +- src/metrics/scripts/docstat.ts | 2 +- src/observability/middleware/handle-errors.ts | 4 +- .../tests/get-automatic-request-logger.ts | 4 +- src/rest/components/RestAuth.tsx | 2 +- src/rest/components/types.ts | 6 +- src/rest/pages/category.tsx | 4 +- src/rest/pages/subcategory.tsx | 4 +- src/rest/scripts/test-open-api-schema.ts | 16 +++-- src/rest/scripts/update-files.ts | 2 +- .../scripts/utils/inject-models-schema.ts | 6 +- .../helpers/execute-search-actions.ts | 4 +- .../hooks/useAISearchAutocomplete.ts | 2 +- .../components/hooks/useMultiQueryParams.ts | 12 +++- src/search/components/input/AskAIResults.tsx | 2 +- src/search/components/input/SearchOverlay.tsx | 10 +-- .../ai-search-autocomplete.ts | 2 +- src/search/middleware/search-routes.ts | 2 +- .../utils/indexing-elasticsearch-utils.ts | 6 +- .../index/utils/retry-on-error-test.ts | 8 +-- src/search/tests/api-ai-search.ts | 10 +-- src/types.ts | 2 +- src/versions/scripts/use-short-versions.ts | 3 +- src/webhooks/components/types.ts | 2 +- .../pages/webhook-events-and-payloads.tsx | 4 +- .../content-changes-table-comment.ts | 2 +- src/workflows/find-past-built-pr.ts | 2 +- src/workflows/git-utils.ts | 8 +-- src/workflows/secondary-ratelimit-retry.ts | 6 +- src/workflows/walk-files.ts | 10 ++- 73 files changed, 246 insertions(+), 182 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index aeb30e33a9ad..3668a5fde641 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -67,63 +67,33 @@ export default [ // JSX A11y recommended rules ...jsxA11y.configs.recommended.rules, - // TypeScript-specific overrides + // Overrides 'import/no-extraneous-dependencies': [ 'error', { packageDir: '.', }, ], - 'import/extensions': 'off', - 'no-console': 'off', - camelcase: 'off', - 'no-shadow': 'off', - 'prefer-template': 'off', - 'no-constant-condition': 'off', - 'no-unused-vars': 'off', - 'no-undef': 'off', - 'no-use-before-define': 'off', - 'no-redeclare': 'off', // Allow function overloads in TypeScript - 'import/no-named-as-default-member': 'off', - 'one-var': 'off', - 'import/no-namespace': 'off', - 'import/no-anonymous-default-export': 'off', - 'object-shorthand': 'off', - 'no-empty': 'off', - 'prefer-const': 'off', - 'import/no-named-as-default': 'off', - 'no-useless-concat': 'off', - 'func-style': 'off', - - // TypeScript ESLint specific rules + 'import/extensions': ['error', { json: 'always' }], + 'no-empty': ['error', { allowEmptyCatch: true }], '@typescript-eslint/no-unused-vars': 'error', + 'prefer-const': ['error', { destructuring: 'all' }], - // Disable GitHub plugin rules that were disabled in original config - 'github/array-foreach': 'off', - 'github/no-then': 'off', - - // Disable rules that might not exist or cause issues initially - 'i18n-text/no-en': 'off', - 'filenames/match-regex': 'off', - 'eslint-comments/no-use': 'off', - 'eslint-comments/no-unused-disable': 'off', - 'eslint-comments/no-unlimited-disable': 'off', - - // Disable new ESLint 9 rules that are causing issues - 'no-constant-binary-expression': 'off', - - // Disable stricter TypeScript rules initially - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-expressions': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/no-wrapper-object-types': 'off', - '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', - '@typescript-eslint/no-unsafe-function-type': 'off', - '@typescript-eslint/no-empty-object-type': 'off', - '@typescript-eslint/prefer-as-const': 'off', + // Rules that must be disabled + 'no-redeclare': 'off', // Allow function overloads in TypeScript + 'i18n-text/no-en': 'off', // This rule causes eslint to not run at all + 'filenames/match-regex': 'off', // This rule causes eslint to not run at all - // React/JSX specific rules - 'jsx-a11y/no-onchange': 'off', + // Disabled rules to review + 'github/no-then': 'off', // 30+ + '@typescript-eslint/ban-ts-comment': 'off', // 50+ + 'no-undef': 'off', // 50+ + 'no-shadow': 'off', // 150+ + 'prefer-template': 'off', // 150+ + 'github/array-foreach': 'off', // 250+ + camelcase: 'off', // 600+ + 'no-console': 'off', // 800+ + '@typescript-eslint/no-explicit-any': 'off', // 1000+ }, }, diff --git a/package.json b/package.json index eae47fc34dcc..802bb7bfb1c6 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "index-general-search": "tsx src/search/scripts/index/index-cli general-search", "index-test-fixtures": "./src/search/scripts/index-test-fixtures.sh", "labeler": "tsx .github/actions/labeler/labeler.ts", - "lint": "eslint '**/*.{js,mjs,ts,tsx}'", + "lint": "eslint '**/*.{ts,tsx}'", "lint-content": "tsx src/content-linter/scripts/lint-content.ts", "lint-translation": "vitest src/content-linter/tests/lint-files.ts", "liquid-markdown-tables": "tsx src/tools/scripts/liquid-markdown-tables/index.ts", @@ -67,8 +67,8 @@ "postinstall": "cp package-lock.json .installed.package-lock.json && echo \"Updated .installed.package-lock.json\" # see husky/post-checkout and husky/post-merge", "precompute-pageinfo": "tsx src/article-api/scripts/precompute-pageinfo.ts", "prepare": "husky src/workflows/husky", - "prettier": "prettier -w \"**/*.{ts,tsx,js,mjs,scss,yml,yaml}\"", - "prettier-check": "prettier -c \"**/*.{ts,tsx,js,mjs,scss,yml,yaml}\"", + "prettier": "prettier -w \"**/*.{ts,tsx,scss,yml,yaml}\"", + "prettier-check": "prettier -c \"**/*.{ts,tsx,scss,yml,yaml}\"", "prevent-pushes-to-main": "tsx src/workflows/prevent-pushes-to-main.ts", "purge-fastly-edge-cache": "tsx src/workflows/purge-fastly-edge-cache.ts", "purge-fastly-edge-cache-per-language": "tsx src/languages/scripts/purge-fastly-edge-cache-per-language.ts", @@ -105,12 +105,12 @@ "what-docs-early-access-branch": "tsx src/early-access/scripts/what-docs-early-access-branch.ts" }, "lint-staged": { - "*.{js,mjs,ts,tsx}": "eslint --cache --fix", - "*.{js,mjs,scss,ts,tsx,yml,yaml}": "prettier --write", + "*.{ts,tsx}": "eslint --cache --fix", + "*.{scss,ts,tsx,yml,yaml}": "prettier --write", "{content,data}/**/*.md": "npm run lint-content -- --precommit --paths" }, "nodemonConfig": { - "ext": "ts,js,json,yml,md,html,scss", + "ext": "ts,json,yml,md,html,scss", "exec": "tsx", "ignore": [ "assets", @@ -139,7 +139,7 @@ }, { "files": [ - "**/*.{ts,tsx,js,mjs}" + "**/*.{ts,tsx}" ], "options": { "printWidth": 100, diff --git a/src/archives/middleware/archived-enterprise-versions.ts b/src/archives/middleware/archived-enterprise-versions.ts index fd2be04e9251..848a151f0e03 100644 --- a/src/archives/middleware/archived-enterprise-versions.ts +++ b/src/archives/middleware/archived-enterprise-versions.ts @@ -235,7 +235,7 @@ export default async function archivedEnterpriseVersions( // `x-host` is a custom header set by Fastly. // GLB automatically deletes the `x-forwarded-host` header. const host = req.get('x-host') || req.get('x-forwarded-host') || req.get('host') - let modifiedBody = body + const modifiedBody = body .replaceAll( `${OLD_AZURE_BLOB_ENTERPRISE_DIR}/${requestedVersion}/assets/cb-`, `${ENTERPRISE_GH_PAGES_URL_PREFIX}${requestedVersion}/assets/cb-`, diff --git a/src/assets/scripts/deleted-assets-pr-comment.ts b/src/assets/scripts/deleted-assets-pr-comment.ts index cc7802a79918..19aca379f7aa 100755 --- a/src/assets/scripts/deleted-assets-pr-comment.ts +++ b/src/assets/scripts/deleted-assets-pr-comment.ts @@ -1,4 +1,4 @@ -import * as github from '@actions/github' +import github from '@actions/github' import core from '@actions/core' const { GITHUB_TOKEN } = process.env diff --git a/src/assets/scripts/find-orphaned-assets.ts b/src/assets/scripts/find-orphaned-assets.ts index 7b9aa2dbff7b..da4fd6d8b5dd 100755 --- a/src/assets/scripts/find-orphaned-assets.ts +++ b/src/assets/scripts/find-orphaned-assets.ts @@ -145,7 +145,9 @@ async function main(opts: MainOptions) { // Add exceptions sourceFiles.push('.github/CONTRIBUTING.md') sourceFiles.push('README.md') - verbose && console.log(`${sourceFiles.length.toLocaleString()} source files found in total.`) + if (verbose) { + console.log(`${sourceFiles.length.toLocaleString()} source files found in total.`) + } const allImages = new Set( walk( @@ -159,7 +161,9 @@ async function main(opts: MainOptions) { ).filter((filePath) => !filePath.endsWith('.md')), ) - verbose && console.log(`${allImages.size.toLocaleString()} images found in total.`) + if (verbose) { + console.log(`${allImages.size.toLocaleString()} images found in total.`) + } for (const sourceFile of sourceFiles) { const content = fs.readFileSync(sourceFile, 'utf-8') diff --git a/src/assets/tests/static-assets.ts b/src/assets/tests/static-assets.ts index 13ee2083cc07..479b6af44f96 100644 --- a/src/assets/tests/static-assets.ts +++ b/src/assets/tests/static-assets.ts @@ -43,7 +43,7 @@ type MockResponse = { _json?: string _send?: string headers: Record - set?: (key: string | Object, value: string) => void + set?: (key: string | object, value: string) => void removeHeader?: (key: string) => void hasHeader?: (key: string) => boolean } diff --git a/src/audit-logs/lib/index.ts b/src/audit-logs/lib/index.ts index 9f1608e309a4..3af7c77a7bc2 100644 --- a/src/audit-logs/lib/index.ts +++ b/src/audit-logs/lib/index.ts @@ -96,7 +96,7 @@ async function resolveReferenceLinksToTitles( // docs_reference_links: 'event reference links' // }, // ] -export function getAuditLogEvents(page: string, version: string) { +export function getAuditLogEvents(page: string, version: string): AuditLogEventT[] { const openApiVersion = getOpenApiVersion(version) const auditLogFileName = path.join(AUDIT_LOG_DATA_DIR, openApiVersion, `${page}.json`) @@ -115,14 +115,14 @@ export function getAuditLogEvents(page: string, version: string) { ?.set(page, readCompressedJsonFileFallback(auditLogFileName)) } - const auditLogEvents = auditLogEventsCache.get(openApiVersion)?.get(page)! + const auditLogEvents = auditLogEventsCache.get(openApiVersion)?.get(page) // If an event doesn't yet have a description (value will be empty string or // "N/A"), then we don't show the event. - const filteredAuditLogEvents = auditLogEvents.filter( + const filteredAuditLogEvents = auditLogEvents?.filter( (event) => event.description !== 'N/A' && event.description !== '', ) - return filteredAuditLogEvents + return filteredAuditLogEvents || [] } // get categorized audit log event data for the requested page and version @@ -137,7 +137,7 @@ export function getAuditLogEvents(page: string, version: string) { // repo: [ [Object] ], // user: [ [Object], [Object] ] // } -export function getCategorizedAuditLogEvents(page: string, version: string) { +export function getCategorizedAuditLogEvents(page: string, version: string): CategorizedEvents { const events = getAuditLogEvents(page, version) const openApiVersion = getOpenApiVersion(version) @@ -148,7 +148,7 @@ export function getCategorizedAuditLogEvents(page: string, version: string) { categorizedAuditLogEventsCache.get(openApiVersion)?.set(page, categorizeEvents(events)) } - return categorizedAuditLogEventsCache.get(openApiVersion)?.get(page)! + return categorizedAuditLogEventsCache.get(openApiVersion)?.get(page) || {} } // Filters audit log events based on allowlist values. diff --git a/src/audit-logs/pages/audit-log-events.tsx b/src/audit-logs/pages/audit-log-events.tsx index ac114c6c37d2..27e84296aaf7 100644 --- a/src/audit-logs/pages/audit-log-events.tsx +++ b/src/audit-logs/pages/audit-log-events.tsx @@ -86,7 +86,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => Object.keys(auditLogEvents).map((category) => category), context, ) - auditLogEventsMiniTocs && miniTocItems.push(...auditLogEventsMiniTocs) + if (auditLogEventsMiniTocs) { + miniTocItems.push(...auditLogEventsMiniTocs) + } return { props: { diff --git a/src/content-linter/lib/helpers/should-include-result.ts b/src/content-linter/lib/helpers/should-include-result.ts index c6824eb16641..afa77e5afd44 100644 --- a/src/content-linter/lib/helpers/should-include-result.ts +++ b/src/content-linter/lib/helpers/should-include-result.ts @@ -1,4 +1,4 @@ -import * as nodePath from 'path' +import nodePath from 'path' import { reportingConfig } from '@/content-linter/style/github-docs' interface LintFlaw { diff --git a/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts b/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts index f5b37395ad2d..97da99f41abe 100644 --- a/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts +++ b/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts @@ -30,7 +30,7 @@ export const liquidIfversionVersions = { // The versions frontmatter object or all versions if the file // being processed is a data file. const fm = getFrontmatter(params.lines) - let content = fm ? getFrontmatterLines(params.lines).join('\n') : params.lines.join('\n') + const content = fm ? getFrontmatterLines(params.lines).join('\n') : params.lines.join('\n') const fileVersionsFm = params.name.startsWith('data') ? { ghec: '*', ghes: '*', fpt: '*' } diff --git a/src/content-linter/lib/linting-rules/note-warning-formatting.ts b/src/content-linter/lib/linting-rules/note-warning-formatting.ts index 820ac069f8b9..e55a57da2295 100644 --- a/src/content-linter/lib/linting-rules/note-warning-formatting.ts +++ b/src/content-linter/lib/linting-rules/note-warning-formatting.ts @@ -72,7 +72,7 @@ export const noteWarningFormatting = { // Collect content inside legacy notes if (inLegacyNote) { - noteContent.push({ text: line, lineNumber: lineNumber }) + noteContent.push({ text: line, lineNumber }) continue } diff --git a/src/content-linter/lib/linting-rules/outdated-release-phase-terminology.ts b/src/content-linter/lib/linting-rules/outdated-release-phase-terminology.ts index d91249170547..28ce1d3e2c8b 100644 --- a/src/content-linter/lib/linting-rules/outdated-release-phase-terminology.ts +++ b/src/content-linter/lib/linting-rules/outdated-release-phase-terminology.ts @@ -78,8 +78,8 @@ function findOutdatedTerminologyMatches(line: string): MatchInfo[] { start: match.index, end: match.index + match[0].length, text: match[0], - replacement: replacement, - outdatedTerm: outdatedTerm, + replacement, + outdatedTerm, }) } } diff --git a/src/content-linter/tests/lint-files.ts b/src/content-linter/tests/lint-files.ts index f0ad3f5c4e8d..e6de28e097e0 100755 --- a/src/content-linter/tests/lint-files.ts +++ b/src/content-linter/tests/lint-files.ts @@ -240,7 +240,9 @@ if (ymlToLint.length === 0) { describe('lint yaml content', () => { if (ymlToLint.length < 1) return describe.each(ymlToLint)('%s', (yamlRelPath, yamlAbsPath) => { - let dictionary, isEarlyAccess, fileContents + let dictionary + let isEarlyAccess + let fileContents // This variable is used to determine if the file was parsed successfully. // When `yaml.load()` fails to parse the file, it is overwritten with the error message. // `false` is intentionally chosen since `null` and `undefined` are valid return values. diff --git a/src/content-render/liquid/ifversion.ts b/src/content-render/liquid/ifversion.ts index 64059f4bf349..5ff38fe44843 100644 --- a/src/content-render/liquid/ifversion.ts +++ b/src/content-render/liquid/ifversion.ts @@ -37,7 +37,7 @@ const notRegex = /(?:^|\s)not\s/ // native Liquid `if` block tag. It has special handling for statements like {% ifversion ghes < 3.0 %}, // using semver to evaluate release numbers instead of doing standard number comparisons, which // don't work the way we want because they evaluate 3.2 > 3.10 = true. -export default class extends Tag { +export default class Ifversion extends Tag { tagToken: TagToken branches: Branch[] elseTemplates: Template[] diff --git a/src/content-render/liquid/prompt.ts b/src/content-render/liquid/prompt.ts index a01ebfaedff6..0b5cf74b1ec3 100644 --- a/src/content-render/liquid/prompt.ts +++ b/src/content-render/liquid/prompt.ts @@ -29,7 +29,7 @@ export const Prompt: LiquidTag = { }, // Render the inner Markdown, wrap in , then append the SVG - render: function* (scope: any): Generator { + *render(scope: any): Generator { const content = yield this.liquid.renderer.renderTemplates(this.templates, scope) // build a URL with the prompt text encoded as query parameter diff --git a/src/content-render/liquid/spotlight.ts b/src/content-render/liquid/spotlight.ts index 3a895714092b..4a48154976cb 100644 --- a/src/content-render/liquid/spotlight.ts +++ b/src/content-render/liquid/spotlight.ts @@ -53,7 +53,7 @@ export const Spotlight = { stream.start() }, - render: function* (scope: Record): Generator { + *render(scope: Record): Generator { const output = yield this.liquid!.renderer.renderTemplates(this.templates, scope) return yield this.liquid!.parseAndRender(template, { diff --git a/src/content-render/liquid/tool.ts b/src/content-render/liquid/tool.ts index 42152db538a5..c62dedf1ea1b 100644 --- a/src/content-render/liquid/tool.ts +++ b/src/content-render/liquid/tool.ts @@ -66,7 +66,7 @@ export const Tool = { }, // scope is a Liquid scope object, Generator yields/returns Liquid template values - no TypeScript definitions available - render: function* (scope: any): Generator { + *render(scope: any): Generator { const output = yield this.liquid.renderer.renderTemplates(this.templates, scope) return yield this.liquid.parseAndRender(template, { tagName: this.tagName, diff --git a/src/data-directory/scripts/deleted-features-pr-comment.ts b/src/data-directory/scripts/deleted-features-pr-comment.ts index 271e9ebbcfc1..e50a50c16483 100644 --- a/src/data-directory/scripts/deleted-features-pr-comment.ts +++ b/src/data-directory/scripts/deleted-features-pr-comment.ts @@ -8,7 +8,7 @@ * */ -import * as github from '@actions/github' +import github from '@actions/github' import core from '@actions/core' import { program } from 'commander' diff --git a/src/data-directory/tests/index.ts b/src/data-directory/tests/index.ts index 6ba9dde7b2a1..f4f6818da043 100644 --- a/src/data-directory/tests/index.ts +++ b/src/data-directory/tests/index.ts @@ -20,7 +20,7 @@ describe('data-directory', () => { }) test('option: preprocess function', async () => { - const preprocess = function (content: string) { + function preprocess(content: string) { return content.replace('markdown', 'MARKDOWN') } const data = dataDirectory(fixturesDir, { preprocess }) diff --git a/src/events/middleware.ts b/src/events/middleware.ts index 691b2f4a987d..73ba96aff54f 100644 --- a/src/events/middleware.ts +++ b/src/events/middleware.ts @@ -42,7 +42,7 @@ const sentValidationErrors = new QuickLRU({ // to prevent sending multiple validation errors that can spam requests to Hydro const getValidationErrorHash = (validateErrors: ErrorObject[]) => { // limit to 10 second windows - const window: Number = Math.floor(new Date().getTime() / 10000) + const window: number = Math.floor(new Date().getTime() / 10000) return `${window}:${(validateErrors || []) .map((error: ErrorObject) => error.message + error.instancePath + JSON.stringify(error.params)) .join(':')}` diff --git a/src/events/types.ts b/src/events/types.ts index a75c58b1591c..5ce0be05c8cf 100644 --- a/src/events/types.ts +++ b/src/events/types.ts @@ -105,12 +105,12 @@ export type EventPropsByType = { link_samepage?: boolean link_container?: string } - [EventType.page]: {} + [EventType.page]: { type: string } // no unique properties [EventType.preference]: { preference_name: string preference_value: string } - [EventType.print]: {} + [EventType.print]: { type: string } // no unique properties [EventType.search]: { search_query: string search_context?: string diff --git a/src/fixtures/tests/annotations.ts b/src/fixtures/tests/annotations.ts index 7784c947323e..f75df8e8b895 100644 --- a/src/fixtures/tests/annotations.ts +++ b/src/fixtures/tests/annotations.ts @@ -47,7 +47,7 @@ describe('annotations', () => { const noteTexts = notes.map((i: number, el: any) => $(el).text()).get() expect(noteTexts).toEqual([ 'Configures this workflow to run every time a change is pushed to the branch called release.', - 'This job checks out the repository contents ...\n' + "And here's the second comment line.", + "This job checks out the repository contents ...\nAnd here's the second comment line.", ]) } }) diff --git a/src/fixtures/tests/playwright-rendering.spec.ts b/src/fixtures/tests/playwright-rendering.spec.ts index 10e82e2b3a67..03c2c65add91 100644 --- a/src/fixtures/tests/playwright-rendering.spec.ts +++ b/src/fixtures/tests/playwright-rendering.spec.ts @@ -748,7 +748,7 @@ test.describe('survey', () => { await page.evaluate(() => { Object.defineProperty(document, 'visibilityState', { configurable: true, - get: function () { + get() { return 'hidden' }, }) @@ -803,7 +803,7 @@ test.describe('survey', () => { await page.evaluate(() => { Object.defineProperty(document, 'visibilityState', { configurable: true, - get: function () { + get() { return 'hidden' }, }) diff --git a/src/frame/components/context/SharedUIContext.tsx b/src/frame/components/context/SharedUIContext.tsx index 2f484c19b302..5beff34f1683 100644 --- a/src/frame/components/context/SharedUIContext.tsx +++ b/src/frame/components/context/SharedUIContext.tsx @@ -24,8 +24,8 @@ export const SharedUIContextProvider = ({ children }: { children: React.ReactNod return ( {children} diff --git a/src/frame/components/hooks/useFeatureFlags.ts b/src/frame/components/hooks/useFeatureFlags.ts index a0345da561f4..1cd834b6eb55 100644 --- a/src/frame/components/hooks/useFeatureFlags.ts +++ b/src/frame/components/hooks/useFeatureFlags.ts @@ -1,6 +1,6 @@ import { useMainContext } from '@/frame/components/context/MainContext' -export type FeatureFlags = {} +export type FeatureFlags = Record export const useFeatureFlags = (): FeatureFlags => { const { featureFlags } = useMainContext() diff --git a/src/frame/components/ui/MarkdownContent/UnrenderedMarkdownContent.tsx b/src/frame/components/ui/MarkdownContent/UnrenderedMarkdownContent.tsx index ef770b608cbc..98f02c43c773 100644 --- a/src/frame/components/ui/MarkdownContent/UnrenderedMarkdownContent.tsx +++ b/src/frame/components/ui/MarkdownContent/UnrenderedMarkdownContent.tsx @@ -86,8 +86,8 @@ export const UnrenderedMarkdownContent = ({ sendEvent({ type: EventType.clipboard, clipboard_operation: 'copy', - eventGroupKey: eventGroupKey, - eventGroupId: eventGroupId, + eventGroupKey, + eventGroupId, }) }} > diff --git a/src/frame/lib/read-frontmatter.ts b/src/frame/lib/read-frontmatter.ts index be21dbca6b41..f1b7f8878fdf 100644 --- a/src/frame/lib/read-frontmatter.ts +++ b/src/frame/lib/read-frontmatter.ts @@ -11,7 +11,8 @@ function readFrontmatter(markdown: string, opts: ReadFrontmatterOptions = {}) { const schema = opts.schema || { type: 'object', properties: {} } const filepath = opts.filepath || null - let content, data + let content + let data try { ;({ content, data } = matter(markdown)) diff --git a/src/frame/lib/warm-server.ts b/src/frame/lib/warm-server.ts index d8df339db58f..dccaf093576a 100644 --- a/src/frame/lib/warm-server.ts +++ b/src/frame/lib/warm-server.ts @@ -5,9 +5,18 @@ import { createLogger } from '@/observability/logger' const logger = createLogger(import.meta.url) +type WarmServerResult = { + pages: Awaited> + redirects: Awaited> + unversionedTree: Awaited> + siteTree: Awaited> + pageList: Awaited> + pageMap: Awaited> +} + // Instrument these functions so that // it's wrapped in a timer that reports to Datadog -const dog: Record = { +const dog = { loadUnversionedTree: statsd.asyncTimer(loadUnversionedTree, 'load_unversioned_tree'), loadSiteTree: statsd.asyncTimer(loadSiteTree, 'load_site_tree'), loadPages: statsd.asyncTimer(loadPages, 'load_pages'), @@ -17,9 +26,9 @@ const dog: Record = { } // For multiple-triggered Promise sharing -let promisedWarmServer: any +let promisedWarmServer: Promise | undefined -async function warmServer(languagesOnly = []) { +async function warmServer(languagesOnly: string[] = []): Promise { const startTime = Date.now() logger.debug( @@ -42,6 +51,7 @@ async function warmServer(languagesOnly = []) { unversionedTree, siteTree, pageList, + pageMap, } } diff --git a/src/frame/middleware/api.ts b/src/frame/middleware/api.ts index 706bf88cf42c..1c460344f4f6 100644 --- a/src/frame/middleware/api.ts +++ b/src/frame/middleware/api.ts @@ -42,7 +42,7 @@ if (process.env.ELASTICSEARCH_URL) { createProxyMiddleware({ target: 'https://docs.github.com', changeOrigin: true, - pathRewrite: function (path, req: ExtendedRequest) { + pathRewrite(path, req: ExtendedRequest) { return req.originalUrl }, }), diff --git a/src/frame/middleware/block-robots.ts b/src/frame/middleware/block-robots.ts index 0a9b1013f54e..298575ec9f0c 100644 --- a/src/frame/middleware/block-robots.ts +++ b/src/frame/middleware/block-robots.ts @@ -23,7 +23,7 @@ export function blockIndex(path: string) { return pathRegExps.some((pathRe) => pathRe.test(path)) } -const middleware = function blockRobots(req: Request, res: Response, next: NextFunction) { +function middleware(req: Request, res: Response, next: NextFunction) { if (blockIndex(req.path)) res.set('x-robots-tag', 'noindex') return next() } diff --git a/src/frame/middleware/context/generic-toc.ts b/src/frame/middleware/context/generic-toc.ts index d5147448cdb0..1c110f114459 100644 --- a/src/frame/middleware/context/generic-toc.ts +++ b/src/frame/middleware/context/generic-toc.ts @@ -170,7 +170,7 @@ async function getTocItems(node: Tree, context: Context, opts: Options): Promise } } - let childTocItems = [] + const childTocItems = [] if (child.childPages) { childTocItems.push(...(await getTocItems(child, context, opts))) } diff --git a/src/frame/middleware/helmet.ts b/src/frame/middleware/helmet.ts index 978ed674d825..e045cbbaeb80 100644 --- a/src/frame/middleware/helmet.ts +++ b/src/frame/middleware/helmet.ts @@ -18,9 +18,7 @@ const DEFAULT_OPTIONS = { crossOriginResourcePolicy: true, crossOriginEmbedderPolicy: false, // doesn't work with youtube referrerPolicy: { - // See docs-engineering #2426 - // The `... as 'no-referrer-when-downgrade'` is a workaround for TypeScript - policy: 'no-referrer-when-downgrade' as 'no-referrer-when-downgrade', + policy: 'no-referrer-when-downgrade' as const, }, // This module defines a Content Security Policy (CSP) to disallow // inline scripts and content from untrusted sources. diff --git a/src/frame/middleware/index.ts b/src/frame/middleware/index.ts index bf4fc11b46dd..54c543eae829 100644 --- a/src/frame/middleware/index.ts +++ b/src/frame/middleware/index.ts @@ -78,11 +78,15 @@ const ENABLE_FASTLY_TESTING = JSON.parse(process.env.ENABLE_FASTLY_TESTING || 'f // Catch unhandled promise rejections and passing them to Express's error handler // https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016 -const asyncMiddleware = (fn: Function) => (req: Request, res: Response, next: NextFunction) => { - Promise.resolve(fn(req, res, next)).catch(next) -} +const asyncMiddleware = + ( + fn: (req: TReq, res: Response, next: NextFunction) => T | Promise, + ) => + (req: Request, res: Response, next: NextFunction) => { + Promise.resolve(fn(req as TReq, res, next)).catch(next) + } -export default function (app: Express) { +export default function index(app: Express) { // *** Request connection management *** if (!isTest) app.use(timeout(MAX_REQUEST_TIMEOUT)) app.use(abort) diff --git a/src/ghes-releases/scripts/create-enterprise-issue.ts b/src/ghes-releases/scripts/create-enterprise-issue.ts index 7ae0ee7f2be7..e7fe92ee61f1 100644 --- a/src/ghes-releases/scripts/create-enterprise-issue.ts +++ b/src/ghes-releases/scripts/create-enterprise-issue.ts @@ -356,7 +356,7 @@ async function isExistingIssue( ): Promise { const { labels, searchQuery, titleMatch } = opts const labelQuery = labels && labels.map((label) => `label:"${encodeURI(label)}"`).join('+') - let query = encodeURIComponent('is:issue ' + `repo:${repo} `) + let query = encodeURIComponent(`is:issue repo:${repo} `) if (searchQuery) { query += '+' + searchQuery diff --git a/src/ghes-releases/scripts/deprecate/archive-version.ts b/src/ghes-releases/scripts/deprecate/archive-version.ts index e3f0c3435b3b..b0e037fe87e5 100755 --- a/src/ghes-releases/scripts/deprecate/archive-version.ts +++ b/src/ghes-releases/scripts/deprecate/archive-version.ts @@ -63,10 +63,11 @@ main() async function main() { console.log(`Archiving Enterprise version: ${version}`) - let pageList: PageList, urls: Array + let pageList: PageList + let urls: Array if (singlePage) { const pageName = singlePage.trim().startsWith('/') ? singlePage.slice(1) : singlePage - const urls = languageKeys + urls = languageKeys .map((key) => `/${key}/enterprise-server@${version}/${pageName}`) .map((href) => `${host}${href}`) console.log(`\nScraping HTML for a single page only:\n${urls.join('\n')}\n`) diff --git a/src/ghes-releases/scripts/deprecate/rewrite-asset-paths.ts b/src/ghes-releases/scripts/deprecate/rewrite-asset-paths.ts index f5f2ff3a31f1..a86ff9231f81 100644 --- a/src/ghes-releases/scripts/deprecate/rewrite-asset-paths.ts +++ b/src/ghes-releases/scripts/deprecate/rewrite-asset-paths.ts @@ -1,6 +1,18 @@ import fs from 'fs' import path from 'path' +interface ScraperResource { + isHtml(): boolean + isCss(): boolean + getText(): string + getFilename(): string + encoding: BufferEncoding +} + +interface ResourceSavedArgs { + resource: ScraperResource +} + export class RewriteAssetPathsPlugin { tempDirectory: string localDev: boolean @@ -12,8 +24,10 @@ export class RewriteAssetPathsPlugin { this.replaceUrl = replaceUrl } - apply(registerAction: Function) { - registerAction('onResourceSaved', async ({ resource }: any) => { + apply( + registerAction: (event: string, callback: (args: ResourceSavedArgs) => Promise) => void, + ) { + registerAction('onResourceSaved', async ({ resource }: ResourceSavedArgs) => { // Show some activity process.stdout.write('.') diff --git a/src/github-apps/lib/index.ts b/src/github-apps/lib/index.ts index ed0cfa35a8f9..0aab639fb5c1 100644 --- a/src/github-apps/lib/index.ts +++ b/src/github-apps/lib/index.ts @@ -70,7 +70,9 @@ export async function getAppsServerSideProps( ? Object.values(appsItems).map((item: any) => item.displayTitle!) : Object.keys(appsItems) const appMiniToc = await getAutomatedPageMiniTocItems(titles, context) - appMiniToc && miniTocItems.push(...appMiniToc) + if (appMiniToc) { + miniTocItems.push(...appMiniToc) + } return { currentVersion, appsItems, categoriesWithoutSubcategories } } diff --git a/src/github-apps/scripts/sync.ts b/src/github-apps/scripts/sync.ts index d52b5092f0ca..000b510e0062 100755 --- a/src/github-apps/scripts/sync.ts +++ b/src/github-apps/scripts/sync.ts @@ -452,7 +452,7 @@ function getDisplayTitle( : `"${sentenceCase(title)}" ` + resourceGroup + ' permissions' : !resourceGroup ? sentenceCase(title) + ' permissions' - : sentenceCase(resourceGroup) + ' permissions for ' + `"${title}"` + : sentenceCase(resourceGroup) + ` permissions for "${title}"` return { title, displayTitle } } diff --git a/src/graphql/pages/reference.tsx b/src/graphql/pages/reference.tsx index 872c444da5db..41bf36fbdb1d 100644 --- a/src/graphql/pages/reference.tsx +++ b/src/graphql/pages/reference.tsx @@ -18,7 +18,7 @@ import { type Props = { mainContext: MainContextT automatedPageContext: AutomatedPageContextT - schema: Object + schema: object language: string graphqlPageName: string objects?: ObjectT[] diff --git a/src/graphql/scripts/sync.ts b/src/graphql/scripts/sync.ts index 11af29181759..772b811f051d 100755 --- a/src/graphql/scripts/sync.ts +++ b/src/graphql/scripts/sync.ts @@ -28,7 +28,7 @@ const versionsToBuild = Object.keys(allVersions) main() -let allIgnoredChanges = [] +const allIgnoredChanges = [] async function main() { for (const version of versionsToBuild) { diff --git a/src/landings/components/ProductSelectionCard.tsx b/src/landings/components/ProductSelectionCard.tsx index 80d83c1ff11f..415d217cc941 100644 --- a/src/landings/components/ProductSelectionCard.tsx +++ b/src/landings/components/ProductSelectionCard.tsx @@ -2,12 +2,38 @@ import type { ProductGroupT } from '@/landings/components/ProductSelections' import React from 'react' import { Link } from '@/frame/components/Link' -import * as Octicons from '@primer/octicons-react' -import { LinkExternalIcon } from '@primer/octicons-react' +import { + LinkExternalIcon, + RocketIcon, + CommentDiscussionIcon, + CopilotIcon, + GearIcon, + ShieldLockIcon, + DeviceMobileIcon, + ProjectIcon, + OrganizationIcon, + CodeSquareIcon, + GlobeIcon, + PencilIcon, +} from '@primer/octicons-react' type ProductSelectionCardProps = { group: ProductGroupT } +const octiconMap: { [name: string]: React.FunctionComponent } = { + LinkExternalIcon, + RocketIcon, + CommentDiscussionIcon, + CopilotIcon, + GearIcon, + ShieldLockIcon, + DeviceMobileIcon, + ProjectIcon, + OrganizationIcon, + CodeSquareIcon, + GlobeIcon, + PencilIcon, +} export const ProductSelectionCard = ({ group }: ProductSelectionCardProps) => { // Don't display the group if it has no children due to versioning @@ -27,9 +53,11 @@ export const ProductSelectionCard = ({ group }: ProductSelectionCardProps) => { ) } else if (group.octicon) { - const octicon: React.FunctionComponent = ( - Octicons as { [name: string]: React.FunctionComponent } - )[group.octicon] as React.FunctionComponent + const octicon: React.FunctionComponent = octiconMap[group.octicon] + + if (!octicon) { + throw new Error(`Octicon ${group.octicon} not found`) + } return (
diff --git a/src/languages/lib/render-with-fallback.ts b/src/languages/lib/render-with-fallback.ts index 502c8c38b7e5..3a76c90da54c 100644 --- a/src/languages/lib/render-with-fallback.ts +++ b/src/languages/lib/render-with-fallback.ts @@ -78,7 +78,7 @@ export function createTranslationFallbackComment(error: Error, property: string) } else if (isAutotitleError(error)) { // For AUTOTITLE errors, include the error message if (error.message) { - let cleanMessage = error.message + const cleanMessage = error.message .replace(/\n/g, ' ') .replace(/\s+/g, ' ') .trim() diff --git a/src/learning-track/middleware/learning-track.ts b/src/learning-track/middleware/learning-track.ts index b9c1cab7911e..1bec3b34c55a 100644 --- a/src/learning-track/middleware/learning-track.ts +++ b/src/learning-track/middleware/learning-track.ts @@ -175,7 +175,7 @@ async function indexOfLearningTrackGuide( const renderOpts = { textOnly: true } for (let i = 0; i < trackGuidePaths.length; i++) { // Learning track URLs may have Liquid conditionals. - let renderedGuidePath = await executeWithFallback( + const renderedGuidePath = await executeWithFallback( context, () => renderContent(trackGuidePaths[i], context, renderOpts), () => '', // todo use english trackGuidePaths[i] diff --git a/src/links/scripts/check-github-github-links.ts b/src/links/scripts/check-github-github-links.ts index 7baa9a83dbec..4a3b78e8369d 100755 --- a/src/links/scripts/check-github-github-links.ts +++ b/src/links/scripts/check-github-github-links.ts @@ -180,7 +180,10 @@ async function main(opts: MainOptions, args: string[]) { 'utf-8', ) } - const brokenLinks: {}[] = [] + const brokenLinks: { + linkPath: string + file: string + }[] = [] // Break up the long list of URLs to test into batches for (const batch of [...Array(Math.floor(docsLinksFiles.length / BATCH_SIZE)).keys()]) { diff --git a/src/metrics/scripts/docstat.ts b/src/metrics/scripts/docstat.ts index 2e1f6bad7afc..261bb0c821dc 100644 --- a/src/metrics/scripts/docstat.ts +++ b/src/metrics/scripts/docstat.ts @@ -145,7 +145,7 @@ let cleanPath = getCleanPath(providedPath) // Get the version let version: string | null = getVersion(cleanPath) -let usingFptOnly = !!options.fptOnly +const usingFptOnly = !!options.fptOnly // If the URL does not specify a version, default to all versions unless --fptOnly is passed if (version === FREE_PRO_TEAM) { diff --git a/src/observability/middleware/handle-errors.ts b/src/observability/middleware/handle-errors.ts index c9545cc61fb4..dd637d91a1be 100644 --- a/src/observability/middleware/handle-errors.ts +++ b/src/observability/middleware/handle-errors.ts @@ -1,4 +1,4 @@ -import type { NextFunction, Response, ErrorRequestHandler } from 'express' +import type { NextFunction, Response } from 'express' import FailBot from '../lib/failbot' import { nextApp } from '@/frame/middleware/next' @@ -50,7 +50,7 @@ function timedOut(req: ExtendedRequest) { statsd.increment('middleware.timeout', 1, incrementTags) } -const handleError: ErrorRequestHandler = async function handleError( +async function handleError( error: ErrorWithCode | number, req: ExtendedRequest, res: Response, diff --git a/src/observability/tests/get-automatic-request-logger.ts b/src/observability/tests/get-automatic-request-logger.ts index 290d2ef28b5d..1f66fe812ff9 100644 --- a/src/observability/tests/get-automatic-request-logger.ts +++ b/src/observability/tests/get-automatic-request-logger.ts @@ -43,7 +43,7 @@ describe('getAutomaticRequestLogger', () => { } // Override res.end to simulate response completion - const endOverride = function (this: any, chunk?: any, encoding?: any) { + function endOverride(this: any, chunk?: any, encoding?: any) { if (!responseEnded) { responseEnded = true // Simulate a small delay for response time @@ -143,7 +143,7 @@ describe('getAutomaticRequestLogger', () => { } // Override res.end to simulate response completion - const endOverride = function (this: any, chunk?: any, encoding?: any) { + function endOverride(this: any, chunk?: any, encoding?: any) { if (!responseEnded) { responseEnded = true // Simulate a small delay for response time diff --git a/src/rest/components/RestAuth.tsx b/src/rest/components/RestAuth.tsx index 902244501dfa..aaed841f339a 100644 --- a/src/rest/components/RestAuth.tsx +++ b/src/rest/components/RestAuth.tsx @@ -75,7 +75,7 @@ function FineGrainedAccess({ progAccess }: FineGrainedProps) { // Each object represents a set of permissions containing one // or more key-value pairs. All permissions in a set are required. // If there is more than one set of permissions, any set can be used. - const formattedPermissions = progAccess.permissions.map((permissionSet: Object, index) => { + const formattedPermissions = progAccess.permissions.map((permissionSet: object, index) => { // Given the example above, the first object is now an array of tuples // [['"Actions" repository permissions', 'read'], ['"Administration" organization permissions', 'read']] // that can be formatted as a string like `"Administration" organization permissions (write)' diff --git a/src/rest/components/types.ts b/src/rest/components/types.ts index 49e8d4731f84..4213a3d2e1c1 100644 --- a/src/rest/components/types.ts +++ b/src/rest/components/types.ts @@ -18,7 +18,7 @@ export interface ProgAccessT { userToServerRest?: boolean serverToServer?: boolean fineGrainedPat?: boolean - permissions: Array + permissions: Array allowPermissionlessAccess?: boolean allowsPublicRead?: boolean basicAuth?: boolean @@ -90,8 +90,8 @@ export type ExampleT = { statusCode: string contentType?: string description: string - example?: Object - schema?: Object + example?: object + schema?: object } } diff --git a/src/rest/pages/category.tsx b/src/rest/pages/category.tsx index 0a7f1d5701d2..cb0fbf2dd86d 100644 --- a/src/rest/pages/category.tsx +++ b/src/rest/pages/category.tsx @@ -200,7 +200,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => req.context, )) as MinitocItemsT - restOperationsMiniTocItems && miniTocItems.push(...restOperationsMiniTocItems) + if (restOperationsMiniTocItems) { + miniTocItems.push(...restOperationsMiniTocItems) + } } // Replace the toc items in the context with the REST toc items we just diff --git a/src/rest/pages/subcategory.tsx b/src/rest/pages/subcategory.tsx index b6d7774f2efb..6a8958a0ec58 100644 --- a/src/rest/pages/subcategory.tsx +++ b/src/rest/pages/subcategory.tsx @@ -80,7 +80,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => req.context, )) as MinitocItemsT - restOperationsMiniTocItems && miniTocItems.push(...restOperationsMiniTocItems) + if (restOperationsMiniTocItems) { + miniTocItems.push(...restOperationsMiniTocItems) + } } const mainContext = await getMainContext(req, res) diff --git a/src/rest/scripts/test-open-api-schema.ts b/src/rest/scripts/test-open-api-schema.ts index 77e90dd85264..bf006936a5ec 100755 --- a/src/rest/scripts/test-open-api-schema.ts +++ b/src/rest/scripts/test-open-api-schema.ts @@ -98,9 +98,11 @@ async function createCheckContentDirectory(contentFiles: string[]): Promise { - !checkContent[version][category] - ? (checkContent[version][category] = [subCategory]) - : checkContent[version][category].push(subCategory) + if (!checkContent[version][category]) { + checkContent[version][category] = [subCategory] + } else { + checkContent[version][category].push(subCategory) + } checkContent[version][category].sort() }) } @@ -121,9 +123,11 @@ function getOnlyApiVersions(version: string): string[] { function createCheckObj(): CheckObject { const versions: CheckObject = {} Object.keys(allVersions).forEach((version) => { - isApiVersioned(version) - ? getOnlyApiVersions(version).forEach((apiVersion) => (versions[apiVersion] = {})) - : (versions[`${allVersions[version].version}`] = {}) + if (isApiVersioned(version)) { + getOnlyApiVersions(version).forEach((apiVersion) => (versions[apiVersion] = {})) + } else { + versions[`${allVersions[version].version}`] = {} + } }) return versions diff --git a/src/rest/scripts/update-files.ts b/src/rest/scripts/update-files.ts index a9698ba9ad41..c4619cf5a6d5 100755 --- a/src/rest/scripts/update-files.ts +++ b/src/rest/scripts/update-files.ts @@ -242,7 +242,7 @@ async function validateInputParameters(): Promise { } // Check that the source repo exists. - for (let sourceRepoDirectory of sourceRepoDirectories) { + for (const sourceRepoDirectory of sourceRepoDirectories) { if (!existsSync(sourceRepoDirectory)) { const errorMsg = sourceRepoDirectory === 'github' || sourceRepoDirectory === GITHUB_REP_DIR diff --git a/src/rest/scripts/utils/inject-models-schema.ts b/src/rest/scripts/utils/inject-models-schema.ts index 7cb723d140a2..4b40dd0c0ac9 100644 --- a/src/rest/scripts/utils/inject-models-schema.ts +++ b/src/rest/scripts/utils/inject-models-schema.ts @@ -77,13 +77,13 @@ export async function injectModelsSchema(schema: any, schemaName: string): Promi tags: operationObject.tags || ['models'], // Only use 'models' if no tags present verb: operation, requestPath: path, - category: category, + category, subcategory: operationObject['x-github']?.subcategory || '', summary: name, - description: description, + description, 'x-github': { ...operationObject['x-github'], // Preserve all x-github metadata - category: category, + category, enabledForGitHubApps: operationObject['x-github']?.enabledForGitHubApps, githubCloudOnly: operationObject['x-github']?.githubCloudOnly, permissions: operationObject['x-github']?.permissions || {}, diff --git a/src/search/components/helpers/execute-search-actions.ts b/src/search/components/helpers/execute-search-actions.ts index e6aa9a43bc1c..3ed226121858 100644 --- a/src/search/components/helpers/execute-search-actions.ts +++ b/src/search/components/helpers/execute-search-actions.ts @@ -74,9 +74,9 @@ export async function executeCombinedSearch( debug = false, abortSignal?: AbortSignal, ) { - let language = router.locale || 'en' + const language = router.locale || 'en' - const params = new URLSearchParams({ query: query, version, language }) + const params = new URLSearchParams({ query, version, language }) if (debug) { params.set('debug', '1') } diff --git a/src/search/components/hooks/useAISearchAutocomplete.ts b/src/search/components/hooks/useAISearchAutocomplete.ts index 49940db0d583..5f4531c59e6a 100644 --- a/src/search/components/hooks/useAISearchAutocomplete.ts +++ b/src/search/components/hooks/useAISearchAutocomplete.ts @@ -29,7 +29,7 @@ const DEBOUNCE_TIME = 100 // In milliseconds // Results are only cached for the current session // We cache results so if a user presses backspace, we can show the results immediately without burdening the API -let sessionCache = {} as Record +const sessionCache = {} as Record // Helper to incorporate version & locale into the cache key function getCacheKey(query: string, version: string, locale: string) { diff --git a/src/search/components/hooks/useMultiQueryParams.ts b/src/search/components/hooks/useMultiQueryParams.ts index 07f5935a7a09..30b87916a44f 100644 --- a/src/search/components/hooks/useMultiQueryParams.ts +++ b/src/search/components/hooks/useMultiQueryParams.ts @@ -45,9 +45,17 @@ export function useMultiQueryParams() { const searchParams = new URLSearchParams(asPathQuery) initialKeys.forEach((key) => { if (key === 'search-overlay-ask-ai') { - newParams[key] === 'true' ? searchParams.set(key, 'true') : searchParams.delete(key) + if (newParams[key] === 'true') { + searchParams.set(key, 'true') + } else { + searchParams.delete(key) + } } else { - newParams[key] ? searchParams.set(key, newParams[key]) : searchParams.delete(key) + if (newParams[key]) { + searchParams.set(key, newParams[key]) + } else { + searchParams.delete(key) + } } }) const paramsString = searchParams.toString() ? `?${searchParams.toString()}` : '' diff --git a/src/search/components/input/AskAIResults.tsx b/src/search/components/input/AskAIResults.tsx index 7638c4284717..5fce5019c0d6 100644 --- a/src/search/components/input/AskAIResults.tsx +++ b/src/search/components/input/AskAIResults.tsx @@ -566,6 +566,6 @@ function sendAISearchResultEvent({ ai_search_result_response_status: status, ai_search_result_connected_event_id: connectedEventId, eventGroupKey: ASK_AI_EVENT_GROUP, - eventGroupId: eventGroupId, + eventGroupId, }) } diff --git a/src/search/components/input/SearchOverlay.tsx b/src/search/components/input/SearchOverlay.tsx index 126d2ead66e8..af97f3a04992 100644 --- a/src/search/components/input/SearchOverlay.tsx +++ b/src/search/components/input/SearchOverlay.tsx @@ -358,7 +358,7 @@ export function SearchOverlay({ if (searchParams.has('query')) { searchParams.delete('query') } - router.push(`${selectedOption.url}?${searchParams.toString()}` || '') + router.push(`${selectedOption.url}?${searchParams.toString()}`) onClose() } @@ -412,12 +412,12 @@ export function SearchOverlay({ if (searchParams.has('query')) { searchParams.delete('query') } - window.open(`${url}?${searchParams.toString()}` || '', '_blank') + window.open(`${url}?${searchParams.toString()}`, '_blank') } // Handle keyboard navigation of suggestions const handleKeyDown = (event: React.KeyboardEvent) => { - let optionsLength = listElementsRef.current?.length ?? 0 + const optionsLength = listElementsRef.current?.length ?? 0 if (event.key === 'ArrowDown') { event.preventDefault() if (optionsLength > 0) { @@ -855,8 +855,8 @@ function renderSearchGroups( ) { const groups = [] - let isInAskAIState = askAIState?.isAskAIState && !askAIState.aiSearchError - let isInAskAIStateButNoAnswer = isInAskAIState && askAIState.aiCouldNotAnswer + const isInAskAIState = askAIState?.isAskAIState && !askAIState.aiSearchError + const isInAskAIStateButNoAnswer = isInAskAIState && askAIState.aiCouldNotAnswer // This spinner is for both the AI search and the general search results. // We already show a spinner when streaming AI response, so don't want to show 2 here diff --git a/src/search/lib/get-elasticsearch-results/ai-search-autocomplete.ts b/src/search/lib/get-elasticsearch-results/ai-search-autocomplete.ts index 1a3bdab704b4..554dd156ed19 100644 --- a/src/search/lib/get-elasticsearch-results/ai-search-autocomplete.ts +++ b/src/search/lib/get-elasticsearch-results/ai-search-autocomplete.ts @@ -19,7 +19,7 @@ export async function getAISearchAutocompleteResults({ const t0 = new Date() const client = getElasticsearchClient() as Client - let searchQuery: any = { + const searchQuery: any = { index: indexName, size, // Send absolutely minimal from Elasticsearch to here. Less data => faster. diff --git a/src/search/middleware/search-routes.ts b/src/search/middleware/search-routes.ts index 1138f569e432..145addcf3a67 100644 --- a/src/search/middleware/search-routes.ts +++ b/src/search/middleware/search-routes.ts @@ -70,7 +70,7 @@ router.get( // If no query is provided, we want to return the top 5 most popular terms // This is a special case for AI search autocomplete // So we use `force` to allow the query to be empty without the usual validation error - let force = {} as any + const force = {} as any if (!req.query.query) { force.query = '' } diff --git a/src/search/scripts/index/utils/indexing-elasticsearch-utils.ts b/src/search/scripts/index/utils/indexing-elasticsearch-utils.ts index cf7fcc087cf8..5b2b559d5499 100644 --- a/src/search/scripts/index/utils/indexing-elasticsearch-utils.ts +++ b/src/search/scripts/index/utils/indexing-elasticsearch-utils.ts @@ -76,8 +76,8 @@ export async function populateIndex( }, ) - if (bulkResponse.errors) { - console.error(`Bulk response errors: ${bulkResponse.errors}`) + if (bulkResponse.failed > 0) { + console.error(`Bulk response failed: ${bulkResponse.failed} documents failed`) throw new Error('Bulk errors happened.') } const t1 = new Date() @@ -140,7 +140,7 @@ export async function updateAlias( ) for (const index of indices) { - if (index.index !== indexAlias && index.index.startsWith(indexName)) { + if (index.index && index.index !== indexAlias && index.index.startsWith(indexName)) { aliasUpdates.push({ remove_index: { index: index.index } }) console.log('Deleting old index', index.index) } diff --git a/src/search/scripts/index/utils/retry-on-error-test.ts b/src/search/scripts/index/utils/retry-on-error-test.ts index bed48738f492..93e251b32d01 100644 --- a/src/search/scripts/index/utils/retry-on-error-test.ts +++ b/src/search/scripts/index/utils/retry-on-error-test.ts @@ -21,9 +21,9 @@ import { sleep } from '@/search/lib/helpers/time' -export async function retryOnErrorTest( - errorTest: (error: any) => boolean, - callback: Function, +export async function retryOnErrorTest( + errorTest: (error: unknown) => boolean, + callback: () => Promise, { attempts = 4, sleepTime = 1000, @@ -37,7 +37,7 @@ export async function retryOnErrorTest( jitterPercent?: number onError?: (error: Error, attempts: number, sleepTime: number) => void } = {}, -) { +): Promise { while (true) { try { return await callback() diff --git a/src/search/tests/api-ai-search.ts b/src/search/tests/api-ai-search.ts index abf9dddcd545..3a0ce311ca70 100644 --- a/src/search/tests/api-ai-search.ts +++ b/src/search/tests/api-ai-search.ts @@ -10,7 +10,7 @@ describe('AI Search Routes', () => { afterAll(() => stopMockServer()) test('/api/ai-search/v1 should handle a successful response', async () => { - let apiBody = { query: 'How do I create a Repository?', language: 'en', version: 'dotcom' } + const apiBody = { query: 'How do I create a Repository?', language: 'en', version: 'dotcom' } const response = await fetch('http://localhost:4000/api/ai-search/v1', { method: 'POST', @@ -80,7 +80,7 @@ describe('AI Search Routes', () => { }) test('should handle validation errors: query missing', async () => { - let body = { language: 'en', version: 'dotcom' } + const body = { language: 'en', version: 'dotcom' } const response = await post('/api/ai-search/v1', { body: JSON.stringify(body), headers: { 'Content-Type': 'application/json' }, @@ -95,7 +95,7 @@ describe('AI Search Routes', () => { }) test('should handle validation errors: version missing', async () => { - let body = { query: 'example query' } + const body = { query: 'example query' } const response = await post('/api/ai-search/v1', { body: JSON.stringify(body), headers: { 'Content-Type': 'application/json' }, @@ -110,7 +110,7 @@ describe('AI Search Routes', () => { }) test('should handle multiple validation errors: query missing and version', async () => { - let body = { language: 'fr', version: 'fpt' } + const body = { language: 'fr', version: 'fpt' } const response = await post('/api/ai-search/v1', { body: JSON.stringify(body), headers: { 'Content-Type': 'application/json' }, @@ -140,7 +140,7 @@ describe('AI Search Routes', () => { if (response.body) { const reader = response.body.getReader() const decoder = new TextDecoder() - let chunks = [] + const chunks = [] try { while (true) { diff --git a/src/types.ts b/src/types.ts index 1a709d0c8efa..3c39cac8056f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -139,7 +139,7 @@ export type Context = { enPage?: Page productNames?: ProductNames currentVersion?: string - process?: { env: {} } + process?: { env: Record } site?: { data: { ui: any diff --git a/src/versions/scripts/use-short-versions.ts b/src/versions/scripts/use-short-versions.ts index e4597a2dbd42..bbcfc6cb8584 100755 --- a/src/versions/scripts/use-short-versions.ts +++ b/src/versions/scripts/use-short-versions.ts @@ -131,7 +131,8 @@ main().then( // Using any for token objects as liquidjs doesn't provide TypeScript types function removeInputProps(arrayOfObjects: any[]): any[] { return arrayOfObjects.map((obj: any) => { - delete obj.input || delete obj.token.input + delete obj.input + delete obj.token.input return obj }) } diff --git a/src/webhooks/components/types.ts b/src/webhooks/components/types.ts index 70cf3536891f..4c1ae0f77236 100644 --- a/src/webhooks/components/types.ts +++ b/src/webhooks/components/types.ts @@ -21,7 +21,7 @@ interface WebhookActionData { codeExamples: Array availability: Array action: string - payloadExample?: Object + payloadExample?: object } export interface WebhookAction { name: string diff --git a/src/webhooks/pages/webhook-events-and-payloads.tsx b/src/webhooks/pages/webhook-events-and-payloads.tsx index caf2d19653aa..96c48ea8d29d 100644 --- a/src/webhooks/pages/webhook-events-and-payloads.tsx +++ b/src/webhooks/pages/webhook-events-and-payloads.tsx @@ -96,7 +96,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => webhooks.map((webhook) => webhook.data.category), context, ) - webhooksMiniTocs && miniTocItems.push(...webhooksMiniTocs) + if (webhooksMiniTocs) { + miniTocItems.push(...webhooksMiniTocs) + } return { props: { diff --git a/src/workflows/content-changes-table-comment.ts b/src/workflows/content-changes-table-comment.ts index 1bd6949653ee..26750f4658d3 100755 --- a/src/workflows/content-changes-table-comment.ts +++ b/src/workflows/content-changes-table-comment.ts @@ -10,7 +10,7 @@ import fs from 'node:fs' import path from 'node:path' -import * as github from '@actions/github' +import github from '@actions/github' import core from '@actions/core' import walk from 'walk-sync' diff --git a/src/workflows/find-past-built-pr.ts b/src/workflows/find-past-built-pr.ts index a2bf28a91006..c2dbdebb1108 100644 --- a/src/workflows/find-past-built-pr.ts +++ b/src/workflows/find-past-built-pr.ts @@ -22,7 +22,7 @@ async function main() { console.log('ID:', issue.id) console.log('Number:', issue.number) console.log('URL:', issue.html_url) - number = issue.number + number = String(issue.number) if (number) { // We've found the issue (pull request), but before we accept // this `number`, check that the issue isn't locked. diff --git a/src/workflows/git-utils.ts b/src/workflows/git-utils.ts index fef5e873ea53..d5ac998628a3 100644 --- a/src/workflows/git-utils.ts +++ b/src/workflows/git-utils.ts @@ -234,12 +234,12 @@ async function searchCode( } } -async function secondaryRateLimitRetry( - callable: Function, - args: Record, +async function secondaryRateLimitRetry>( + callable: (args: TArgs) => Promise, + args: TArgs, maxAttempts = 10, sleepTime = 1000, -) { +): Promise { try { const response = await callable(args) return response diff --git a/src/workflows/secondary-ratelimit-retry.ts b/src/workflows/secondary-ratelimit-retry.ts index b12a087e4cbc..ad0fe2e0e88b 100644 --- a/src/workflows/secondary-ratelimit-retry.ts +++ b/src/workflows/secondary-ratelimit-retry.ts @@ -7,10 +7,10 @@ const DEFAULT_ATTEMPTS = parseInt(process.env.SECONDARY_RATELIMIT_RETRY_ATTEMPTS // "You have exceeded a secondary rate limit". // More info about what they are here: // https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#about-secondary-rate-limits -export async function octoSecondaryRatelimitRetry( - fn: Function, +export async function octoSecondaryRatelimitRetry( + fn: () => Promise, { attempts = DEFAULT_ATTEMPTS, sleepTime = DEFAULT_SLEEPTIME } = {}, -) { +): Promise { let tries = 0 while (true) { try { diff --git a/src/workflows/walk-files.ts b/src/workflows/walk-files.ts index e1343334c165..017855e7f982 100644 --- a/src/workflows/walk-files.ts +++ b/src/workflows/walk-files.ts @@ -25,11 +25,17 @@ export function readFiles(dir = 'content', ext = 'md', opts = {}) { return paths.map((path) => [path, fs.readFileSync(path, 'utf8')]) } -export function filterFiles(files: [path: string, file: string][], fn: Function) { +export function filterFiles( + files: [path: string, file: string][], + fn: (path: string, file: string) => boolean, +) { return files.filter(([path, file]) => fn(path, file)) } -export function withFiles(files: [path: string, file: string][], fn: Function) { +export function withFiles( + files: [path: string, file: string][], + fn: (path: string, file: string) => string, +) { return files.map(([path, file]) => [path, fn(path, file)]) }