Skip to content

Commit f7e3ecd

Browse files
committed
refactor: convert remaining JavaScript test files to TypeScript
This changeset converts all remaining JavaScript tests to TypeScript. It's sort of a hack job; I used a bulk converter for most of it, then hand-converted the rest. There's varying degrees of "hey, he did a nice job in this file" and "hey, he did a terrible job in this file," but on the whole this is an improvement. I also updated all of the import paths in tests from importing transpiled (`dist/`) code to untranspiled (`src/`) code. Ergonomically this is better--it's confusing to work on tests that aren't necessarily running code that reflects your edits--but really, I was forced into this by spooky conflicts between transpiled types and untranspiled types.
1 parent defbb03 commit f7e3ecd

File tree

99 files changed

+1691
-1144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+1691
-1144
lines changed

package-lock.json

+52
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
"@sindresorhus/slugify": "2.2.1",
164164
"@tsconfig/node18": "^18.2.4",
165165
"@tsconfig/recommended": "^1.0.8",
166+
"@types/backoff": "^2.5.5",
166167
"@types/content-type": "1.1.8",
167168
"@types/debug": "4.1.12",
168169
"@types/envinfo": "7.8.4",
@@ -206,6 +207,7 @@
206207
"strip-ansi": "7.1.0",
207208
"temp-dir": "3.0.0",
208209
"tree-kill": "1.2.2",
210+
"tsx": "^4.19.3",
209211
"typescript": "5.8.3",
210212
"typescript-eslint": "^8.26.0",
211213
"verdaccio": "6.1.2",

src/commands/env/env-get.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const envGet = async (name: string, options: OptionValues, command: BaseC
1717
const { siteInfo } = cachedConfig
1818
const env = await getEnvelopeEnv({ api, context, env: cachedConfig.env, key: name, scope, siteInfo })
1919

20+
// @ts-expect-error FIXME(ndhoule)
2021
const { value } = env[name] || {}
2122

2223
// Return json response for piping commands

src/lib/completion/get-autocompletion.ts

+10-16
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
/**
2-
* @typedef CompletionItem
3-
* @type import('tabtab').CompletionItem
4-
*/
5-
/**
6-
*
7-
* @param {import('tabtab').TabtabEnv} env
8-
* @param {Record<string, CompletionItem & {options: CompletionItem[]}>} program
9-
* @returns {CompletionItem[]|void}
10-
*/
11-
// @ts-expect-error TS(7006) FIXME: Parameter 'env' implicitly has an 'any' type.
12-
const getAutocompletion = function (env, program) {
1+
import type { CompletionItem } from '@pnpm/tabtab'
2+
3+
const getAutocompletion = function (
4+
env: { complete: boolean; lastPartial: string; line: string; words: number },
5+
program: Record<
6+
string,
7+
CompletionItem & { description?: string | undefined; name?: string | undefined; options: CompletionItem[] }
8+
>,
9+
): CompletionItem[] | undefined {
1310
if (!env.complete) {
1411
return
1512
}
1613
// means that we are currently in the first command (the root command)
1714
if (env.words === 1) {
18-
// @ts-expect-error TS(2345) FIXME: Argument of type '({ description, name }: { descri... Remove this comment to see the full error message
1915
const rootCommands = Object.values(program).map(({ description, name }) => ({ name, description }))
2016

2117
// suggest all commands
@@ -26,20 +22,18 @@ const getAutocompletion = function (env, program) {
2622

2723
// $ netlify add<cursor>
2824
// we can now check if a command starts with the last partial
29-
// @ts-expect-error TS(2769) FIXME: No overload matches this call.
3025
const autocomplete = rootCommands.filter(({ name }) => name.startsWith(env.lastPartial))
3126
return autocomplete
3227
}
3328

3429
const [, command, ...args] = env.line.split(' ')
3530

31+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
3632
if (program[command]) {
3733
const usedArgs = new Set(args)
38-
// @ts-expect-error TS(7031) FIXME: Binding element 'name' implicitly has an 'any' typ... Remove this comment to see the full error message
3934
const unusedOptions = program[command].options.filter(({ name }) => !usedArgs.has(name))
4035

4136
if (env.lastPartial.length !== 0) {
42-
// @ts-expect-error TS(7031) FIXME: Binding element 'name' implicitly has an 'any' typ... Remove this comment to see the full error message
4337
return unusedOptions.filter(({ name }) => name.startsWith(env.lastPartial))
4438
}
4539

src/lib/edge-functions/proxy.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'
1919
import { getGeoLocation } from '../geo-location.js'
2020
import { getPathInProject } from '../settings.js'
2121
import { type Spinner, startSpinner, stopSpinner } from '../spinner.js'
22-
import type { CLIState, ServerSettings, SiteInfo } from '../../utils/types.js'
22+
import type { CLIState, ServerSettings } from '../../utils/types.js'
2323

2424
import { getBootstrapURL } from './bootstrap.js'
2525
import { DIST_IMPORT_MAP_PATH, EDGE_FUNCTIONS_SERVE_FOLDER } from './consts.js'
@@ -51,13 +51,16 @@ const getDownloadUpdateFunctions = () => {
5151
}
5252
}
5353

54-
export const handleProxyRequest = (req: ExtendedIncomingMessage, proxyReq: ClientRequest) => {
54+
export const handleProxyRequest = (req: ExtendedIncomingMessage, proxyReq: ClientRequest): void => {
5555
Object.entries(req[headersSymbol]).forEach(([header, value]) => {
5656
proxyReq.setHeader(header, value)
5757
})
5858
}
5959

60-
export const createSiteInfoHeader = (siteInfo: SiteInfo, localURL: string) => {
60+
export const createSiteInfoHeader = (
61+
siteInfo: { id?: string | undefined; name?: string | undefined; url?: string | undefined },
62+
localURL?: string,
63+
): string => {
6164
const { id, name, url } = siteInfo
6265
const site = { id, name, url: localURL ?? url }
6366
const siteString = JSON.stringify(site)

src/lib/geo-location.ts

+37-31
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,27 @@ const CACHE_TTL = 8.64e7
88
// 10 seconds
99
const REQUEST_TIMEOUT = 1e4
1010

11-
/**
12-
* @typedef GeoLocation
13-
* @type {object}
14-
* @property {string} city
15-
* @property {object} country
16-
* @property {string} country.code
17-
* @property {string} country.name
18-
* @property {object} subdivision
19-
* @property {string} subdivision.code
20-
* @property {string} subdivision.name
21-
* @property {number} longitude
22-
* @property {number} latitude
23-
* @property {string} timezone
24-
*/
25-
export const mockLocation = {
11+
export type Geolocation = {
12+
city: string
13+
country: {
14+
code: string
15+
name: string
16+
}
17+
subdivision: {
18+
code: string
19+
name: string
20+
}
21+
longitude: number
22+
latitude: number
23+
timezone: string
24+
}
25+
26+
interface State {
27+
get(key: string): unknown
28+
set(key: string, value: unknown): void
29+
}
30+
31+
export const mockLocation: Geolocation = {
2632
city: 'San Francisco',
2733
country: { code: 'US', name: 'United States' },
2834
subdivision: { code: 'CA', name: 'California' },
@@ -32,19 +38,21 @@ export const mockLocation = {
3238
}
3339

3440
/**
35-
* Returns geolocation data from a remote API, the local cache, or a mock
36-
* location, depending on the mode selected.
37-
*
38-
* @param {object} params
39-
* @param {"cache"|"update"|"mock"} params.mode
40-
* @param {string} params.geoCountry
41-
* @param {boolean} params.offline
42-
* @param {import('../utils/cli-state.js').default} params.state
43-
* @returns {Promise<GeoLocation>}
41+
* Returns geolocation data from a remote API, the local cache, or a mock location, depending on the
42+
* specified mode.
4443
*/
45-
// @ts-expect-error TS(7031) FIXME: Binding element 'geoCountry' implicitly has an 'an... Remove this comment to see the full error message
46-
export const getGeoLocation = async ({ geoCountry, mode, offline, state }) => {
47-
const cacheObject = state.get(STATE_GEO_PROPERTY)
44+
export const getGeoLocation = async ({
45+
geoCountry,
46+
mode,
47+
offline = false,
48+
state,
49+
}: {
50+
mode: 'cache' | 'update' | 'mock'
51+
geoCountry?: string | undefined
52+
offline?: boolean | undefined
53+
state: State
54+
}): Promise<Geolocation> => {
55+
const cacheObject = state.get(STATE_GEO_PROPERTY) as { data: Geolocation; timestamp: number } | undefined
4856

4957
// If `--country` was used, we also set `--mode=mock`.
5058
if (geoCountry) {
@@ -103,11 +111,9 @@ export const getGeoLocation = async ({ geoCountry, mode, offline, state }) => {
103111
}
104112

105113
/**
106-
* Returns geolocation data from a remote API
107-
*
108-
* @returns {Promise<GeoLocation>}
114+
* Returns geolocation data from a remote API.
109115
*/
110-
const getGeoLocationFromAPI = async () => {
116+
const getGeoLocationFromAPI = async (): Promise<Geolocation> => {
111117
const res = await fetch(API_URL, {
112118
method: 'GET',
113119
signal: AbortSignal.timeout(REQUEST_TIMEOUT),

src/lib/http-agent.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,23 @@ const DEFAULT_HTTPS_PORT = 443
3131
// 50 seconds
3232
const AGENT_PORT_TIMEOUT = 50
3333

34-
// @ts-expect-error TS(7031) FIXME: Binding element 'certificateFile' implicitly has a... Remove this comment to see the full error message
35-
export const tryGetAgent = async ({ certificateFile, httpProxy }) => {
34+
export const tryGetAgent = async ({
35+
certificateFile,
36+
httpProxy,
37+
}: {
38+
httpProxy?: string | undefined
39+
certificateFile?: string | undefined
40+
}): Promise<
41+
| {
42+
error?: string | undefined
43+
warning?: string | undefined
44+
message?: string | undefined
45+
}
46+
| {
47+
agent: HttpsProxyAgentWithCA
48+
response: unknown
49+
}
50+
> => {
3651
if (!httpProxy) {
3752
return {}
3853
}

src/utils/deploy/hash-files.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@ import { pipeline } from 'stream/promises'
33
import walker from 'folder-walker'
44

55
import { fileFilterCtor, fileNormalizerCtor, hasherCtor, manifestCollectorCtor } from './hasher-segments.js'
6+
import { $TSFixMe } from '../../commands/types.js'
67

78
const hashFiles = async ({
89
assetType = 'file',
9-
// @ts-expect-error TS(7031) FIXME: Binding element 'concurrentHash' implicitly has an... Remove this comment to see the full error message
1010
concurrentHash,
11-
// @ts-expect-error TS(7031) FIXME: Binding element 'directories' implicitly has an 'a... Remove this comment to see the full error message
1211
directories,
13-
// @ts-expect-error TS(7031) FIXME: Binding element 'filter' implicitly has an 'any' t... Remove this comment to see the full error message
1412
filter,
1513
hashAlgorithm = 'sha1',
16-
// @ts-expect-error TS(7031) FIXME: Binding element 'normalizer' implicitly has an 'an... Remove this comment to see the full error message
1714
normalizer,
18-
// @ts-expect-error TS(7031) FIXME: Binding element 'statusCb' implicitly has an 'any'... Remove this comment to see the full error message
1915
statusCb,
20-
}) => {
16+
}: {
17+
assetType?: string | undefined
18+
concurrentHash: $TSFixMe
19+
directories: $TSFixMe
20+
filter: $TSFixMe
21+
hashAlgorithm?: string | undefined
22+
normalizer?: $TSFixMe
23+
statusCb: $TSFixMe
24+
}): Promise<{ files: Record<string, string>; filesShaMap: Record<string, $TSFixMe[]> }> => {
2125
if (!filter) throw new Error('Missing filter function option')
2226

2327
const fileStream = walker(directories, { filter })

0 commit comments

Comments
 (0)