Skip to content

Commit 5acb25b

Browse files
authored
fix: migrate framework-info to TS and vitest and enable more strictness (#4819)
* fix: version is not part of read-pkg-up result * fix: migrate context to TS and ensure we do not access version on undefined * fix: migrate framework-info to TS and vitest and enable more strictness * chore: fix tests * chore: fix order of build commands * chore: move fixture * chore: fix build * chore: move to prebuild
1 parent e41f7f1 commit 5acb25b

File tree

79 files changed

+1924
-1046
lines changed

Some content is hidden

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

79 files changed

+1924
-1046
lines changed

package-lock.json

Lines changed: 1091 additions & 210 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/build/src/log/messages/compatibility.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const getPluginDescription = function (
5050
},
5151
debug,
5252
) {
53-
const versionedPackage = getVersionedPackage(packageName, version)
53+
const versionedPackage = getVersionedPackage(version)
5454
const pluginOrigin = getPluginOrigin(loadedFrom, origin)
5555
const description = `${THEME.highlightWords(packageName)}${versionedPackage} ${pluginOrigin}`
5656
if (!debug) {
@@ -106,7 +106,7 @@ const getOutdatedPlugin = function ({
106106
loadedFrom,
107107
origin,
108108
}) {
109-
const versionedPackage = getVersionedPackage(packageName, version)
109+
const versionedPackage = getVersionedPackage(version)
110110
const outdatedDescription = getOutdatedDescription({ latestVersion, migrationGuide, loadedFrom, origin })
111111
return `${THEME.warningHighlightWords(packageName)}${versionedPackage}: ${outdatedDescription}`
112112
}
@@ -165,14 +165,14 @@ const getIncompatiblePlugin = function ({
165165
compatibleVersion,
166166
compatWarning,
167167
}) {
168-
const versionedPackage = getVersionedPackage(packageName, version)
168+
const versionedPackage = getVersionedPackage(version)
169169
return `${THEME.warningHighlightWords(
170170
packageName,
171171
)}${versionedPackage}: version ${compatibleVersion} is the most recent version compatible with ${compatWarning}`
172172
}
173173

174174
// Make sure we handle `package.json` with `version` being either `undefined`
175175
// or an empty string
176-
const getVersionedPackage = function (packageName, version = '') {
176+
const getVersionedPackage = function (version = '') {
177177
return version === '' ? '' : `@${version}`
178178
}

packages/build/src/plugins/options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const loadPluginFiles = async function ({
7979
// Core plugins can only be included once.
8080
// For example, when testing core plugins, they might be included as local plugins,
8181
// in which case they should not be included twice.
82-
const isNotRedundantCorePlugin = function (pluginOptionsA, index, pluginsOptions) {
82+
const isNotRedundantCorePlugin = function (pluginOptionsA, _index, pluginsOptions) {
8383
return (
8484
pluginOptionsA.loadedFrom !== 'core' ||
8585
pluginsOptions.every(

packages/cache-utils/src/fs.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { promises as fs } from 'fs'
1+
import { promises as fs, Stats } from 'fs'
22
import { basename, dirname } from 'path'
33

44
import cpy from 'cpy'
@@ -78,10 +78,11 @@ const getSrcGlob = async function (src: string): Promise<GlobOptions> {
7878
return baseOptions
7979
}
8080

81-
const getStat = async (src: string) => {
81+
const getStat = async (src: string): Promise<Stats | undefined> => {
8282
try {
8383
return await fs.stat(src)
8484
} catch {
8585
// continue regardless error
86+
return undefined
8687
}
8788
}

packages/config/src/path.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const getConfigPath = async function ({ configOpt, cwd, repositoryRoot, c
1515
const configPath = await pLocate(
1616
[
1717
searchConfigOpt(cwd, configOpt),
18-
searchBaseConfigFile(repositoryRoot, configBase),
18+
searchBaseConfigFile(configBase),
1919
searchConfigFile(repositoryRoot),
2020
findUp(FILENAME, { cwd }),
2121
],
@@ -36,7 +36,7 @@ const searchConfigOpt = function (cwd: string, configOpt?: string) {
3636
/**
3737
* Look for `repositoryRoot/{base}/netlify.*`
3838
*/
39-
const searchBaseConfigFile = function (repositoryRoot, configBase?: string) {
39+
const searchBaseConfigFile = function (configBase?: string) {
4040
if (configBase === undefined) {
4141
return
4242
}

packages/framework-info/.gitignore

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ node_modules
22
yarn-error.log
33
.vscode
44
dist
5-
build
5+
src/generated
66
.DS_Store
77

88
# Local Netlify folder
99
.netlify
1010

1111
# These are mock node_modules folder for testing purposes
12-
!test/fixtures/simple/node_modules
13-
!test/fixtures/multiple/node_modules
14-
!test/fixtures/monorepos/node_modules
12+
!tests/fixtures/simple/node_modules
13+
!tests/fixtures/multiple/node_modules
14+
!tests/fixtures/monorepos/node_modules

packages/framework-info/package.json

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,23 @@
55
"type": "module",
66
"main": "./dist/index.umd.cjs",
77
"exports": {
8-
"node": "./src/main.js",
8+
"node": "./lib/main.js",
99
"default": "./dist/index.umd.cjs"
1010
},
1111
"files": [
12-
"build/*.js",
13-
"src/**/*.js",
12+
"lib",
1413
"dist/index.umd.cjs"
1514
],
1615
"scripts": {
16+
"prebuild": "node scripts/transform_json.js",
1717
"build": "run-s build:*",
1818
"build:ts": "tsc",
19-
"build:json": "node scripts/transform_json.js",
2019
"build:browser": "run-s build:browser:*",
2120
"build:browser:core": "vite build",
2221
"build:browser:site-root": "cpy index.html ./dist",
23-
"test": "npm run test:dev",
24-
"test:dev": "ava",
25-
"test:ci": "c8 -r lcovonly -r text -r json ava"
22+
"test": "vitest run",
23+
"test:dev": "vitest",
24+
"test:ci": "vitest run --reporter=default"
2625
},
2726
"keywords": [
2827
"dependency-management",
@@ -58,10 +57,9 @@
5857
"url": "https://github.com/netlify/build/issues"
5958
},
6059
"dependencies": {
61-
"ajv": "^8.0.0",
60+
"ajv": "^8.12.0",
6261
"filter-obj": "^3.0.0",
6362
"find-up": "^6.3.0",
64-
"fs-extra": "^10.1.0",
6563
"is-plain-obj": "^4.0.0",
6664
"locate-path": "^7.0.0",
6765
"p-filter": "^3.0.0",
@@ -72,19 +70,18 @@
7270
"url": "^0.11.0"
7371
},
7472
"devDependencies": {
75-
"ava": "^4.0.0",
7673
"babel-loader": "^8.2.2",
77-
"c8": "^7.11.0",
7874
"cpy": "^9.0.0",
7975
"cpy-cli": "^4.0.0",
8076
"del": "^6.0.0",
77+
"fast-glob": "^3.2.12",
8178
"npm-run-all": "^4.1.5",
8279
"path-browserify": "^1.0.1",
8380
"rollup-plugin-node-polyfills": "^0.2.1",
84-
"test-each": "^4.0.0",
8581
"tmp-promise": "^3.0.2",
8682
"typescript": "^4.9.4",
87-
"vite": "^3.1.6"
83+
"vite": "^4.0.4",
84+
"vitest": "^0.27.1"
8885
},
8986
"engines": {
9087
"node": "^14.14.0 || >=16.0.0"

packages/framework-info/scripts/transform_json.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { promises as fs } from 'fs'
22
import process from 'process'
3+
import { fileURLToPath } from 'url'
34

4-
import { FRAMEWORK_NAMES } from '../src/frameworks/main.js'
5+
import glob from 'fast-glob'
56

67
const FRAMEWORKS_DIR = new URL('../src/frameworks/', import.meta.url)
7-
const BUILD_DIR = new URL('../build/', import.meta.url)
8-
const FRAMEWORKS_BUILD = new URL('frameworks.js', BUILD_DIR)
8+
const BUILD_DIR = new URL('../src/generated/', import.meta.url)
9+
const FRAMEWORKS_BUILD = new URL('frameworks.ts', BUILD_DIR)
910

1011
// We enforce frameworks to be written with JSON to ensure they remain logicless
1112
// which is simpler for contributors and avoid adding unnecessary logic.
@@ -14,7 +15,8 @@ const FRAMEWORKS_BUILD = new URL('frameworks.js', BUILD_DIR)
1415
// Therefore, we transform JSON to JavaScript files using at build time.
1516
const transformFrameworks = async function () {
1617
await fs.mkdir(BUILD_DIR, { recursive: true })
17-
const frameworks = await Promise.all(FRAMEWORK_NAMES.map(transformFramework))
18+
const frameworkFiles = await glob('*.json', { cwd: fileURLToPath(FRAMEWORKS_DIR), absolute: true })
19+
const frameworks = await Promise.all(frameworkFiles.map(transformFramework))
1820
const fileContents = `${FRAMEWORKS_HEADER}${JSON.stringify(frameworks, null, 2)}`
1921
await fs.writeFile(FRAMEWORKS_BUILD, fileContents)
2022
}
@@ -31,16 +33,16 @@ const updateLogoUrls = function (contents) {
3133
return updatedContents
3234
}
3335

34-
const transformFramework = async function (frameworkName) {
35-
const frameworkUrl = new URL(`${frameworkName}.json`, FRAMEWORKS_DIR)
36-
const jsonContents = await fs.readFile(frameworkUrl)
36+
const transformFramework = async function (frameworkFile) {
37+
const jsonContents = await fs.readFile(frameworkFile)
3738
const contents = JSON.parse(jsonContents)
3839

3940
const updatedContents = updateLogoUrls(contents)
4041
return updatedContents
4142
}
4243

43-
const FRAMEWORKS_HEADER = `// This file is autogenerated at build time
44-
export const FRAMEWORKS = `
44+
const FRAMEWORKS_HEADER = `import type { FrameworkDefinition } from "../types.js"
45+
// This file is autogenerated at build time
46+
export const FRAMEWORKS: FrameworkDefinition[] = `
4547

4648
transformFrameworks()

packages/framework-info/src/context.js

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { cwd, version as nodejsVersion } from 'process'
2+
3+
import { locatePath } from 'locate-path'
4+
import { PackageJson, readPackageUp } from 'read-pkg-up'
5+
6+
interface PackageJsonInfo {
7+
packageJson?: PackageJson
8+
packageJsonPath?: string
9+
}
10+
11+
export type PathExists = (path: string) => Promise<boolean>
12+
13+
export interface Context extends PackageJsonInfo {
14+
pathExists: PathExists
15+
nodeVersion: string
16+
}
17+
18+
export const getPackageJson = async (projectDir: string): Promise<PackageJsonInfo> => {
19+
try {
20+
const result = await readPackageUp({ cwd: projectDir, normalize: false })
21+
if (result === undefined) {
22+
return {}
23+
}
24+
25+
const { packageJson, path: packageJsonPath } = result
26+
27+
return { packageJson, packageJsonPath }
28+
} catch {
29+
return {}
30+
}
31+
}
32+
33+
export const getContext = async (projectDir: string = cwd(), nodeVersion: string = nodejsVersion): Promise<Context> => {
34+
const { packageJson, packageJsonPath = projectDir } = await getPackageJson(projectDir)
35+
36+
return {
37+
pathExists: async (path) => (await locatePath([path], { type: 'file', cwd: projectDir })) !== undefined,
38+
packageJson,
39+
packageJsonPath,
40+
nodeVersion,
41+
}
42+
}

0 commit comments

Comments
 (0)