Merge pull request #14817 from backstage/introduce-check-type-dependencies

feat: introduce type-deps command in repo-tools package
This commit is contained in:
Patrik Oldsberg
2022-11-28 21:00:46 +01:00
committed by GitHub
7 changed files with 45 additions and 24 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/repo-tools': patch
---
add the command type-deps to the repo tool package.
+1 -1
View File
@@ -21,7 +21,7 @@
"lint": "backstage-cli repo lint --since origin/master",
"lint:docs": "node ./scripts/check-docs-quality",
"lint:all": "backstage-cli repo lint",
"lint:type-deps": "node scripts/check-type-dependencies.js",
"lint:type-deps": "backstage-repo-tools type-deps",
"docker-build": "yarn tsc && yarn workspace example-backend build --build-dependencies && yarn workspace example-backend build-image",
"new": "backstage-cli new --scope backstage --baseVersion 0.0.0 --no-private",
"create-plugin": "echo \"use 'yarn new' instead\"",
+10
View File
@@ -13,6 +13,7 @@ Options:
Commands:
api-reports [options] [path...]
type-deps
help [command]
```
@@ -27,3 +28,12 @@ Options:
--docs
-h, --help
```
### `backstage-repo-tools type-deps`
```
Usage: backstage-repo-tools type-deps [options]
Options:
-h, --help
```
+1
View File
@@ -31,6 +31,7 @@
},
"dependencies": {
"@backstage/errors": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@microsoft/api-documenter": "^7.17.11",
"@microsoft/api-extractor": "^7.23.0",
"@microsoft/api-extractor-model": "^7.17.2",
@@ -28,6 +28,11 @@ export function registerCommands(program: Command) {
.action(
lazy(() => import('./api-reports/api-reports').then(m => m.default)),
);
program
.command('type-deps')
.description('Find inconsistencies in types of all packages and plugins')
.action(lazy(() => import('./type-deps/type-deps').then(m => m.default)));
}
// Wraps an action function so that it always exits and handles errors
@@ -1,6 +1,5 @@
#!/usr/bin/env node
/*
* Copyright 2020 The Backstage Authors
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +14,14 @@
* limitations under the License.
*/
const fs = require('fs');
const { resolve: resolvePath } = require('path');
import fs from 'fs';
import { resolve as resolvePath } from 'path';
// Cba polluting root package.json, we'll have this
// eslint-disable-next-line import/no-extraneous-dependencies
const chalk = require('chalk');
const { getPackages } = require('@manypkg/get-packages');
import chalk from 'chalk';
import { getPackages, Package } from '@manypkg/get-packages';
async function main() {
export default async () => {
const { packages } = await getPackages(resolvePath('.'));
let hadErrors = false;
@@ -63,24 +62,29 @@ async function main() {
process.exit(2);
}
}
};
function shouldCheckTypes(pkg) {
type PackageJsonWithTypes = {
packageJson: {
types?: string;
};
};
function shouldCheckTypes(pkg: Package & PackageJsonWithTypes) {
return (
!pkg.private &&
!pkg.packageJson.private &&
pkg.packageJson.types &&
fs.existsSync(resolvePath(pkg.dir, 'dist/index.d.ts'))
);
}
function findAllDeps(declSrc) {
function findAllDeps(declSrc: string) {
const importedDeps = (declSrc.match(/^import .* from '.*';$/gm) || [])
.map(match => match.match(/from '(.*)'/)[1])
.map(match => match.match(/from '(.*)'/)?.[1] ?? '')
.filter(n => !n.startsWith('.'));
const referencedDeps = (
declSrc.match(/^\/\/\/ <reference types=".*" \/>$/gm) || []
)
.map(match => match.match(/types="(.*)"/)[1])
.map(match => match.match(/types="(.*)"/)?.[1] ?? '')
.filter(n => !n.startsWith('.'))
// We allow references to these without an explicit dependency.
.filter(n => !['node', 'react'].includes(n));
@@ -91,7 +95,7 @@ function findAllDeps(declSrc) {
* Scan index.d.ts for imports and return errors for any dependency that's
* missing or incorrect in package.json
*/
function checkTypes(pkg) {
function checkTypes(pkg: Package) {
const typeDecl = fs.readFileSync(
resolvePath(pkg.dir, 'dist/index.d.ts'),
'utf8',
@@ -121,7 +125,7 @@ function checkTypes(pkg) {
* Find the package used for types. This assumes that types are working is a package
* can be resolved, it doesn't do any checking of presence of types inside the dep.
*/
function findTypesPackage(dep, pkg) {
function findTypesPackage(dep: string, pkg: Package) {
try {
require.resolve(`@types/${dep}/package.json`, { paths: [pkg.dir] });
return `@types/${dep}`;
@@ -161,7 +165,7 @@ function findTypesPackage(dep, pkg) {
/**
* Figures out what type dependencies are missing, or should be moved between dep types
*/
function findTypeDepErrors(typeDeps, pkg) {
function findTypeDepErrors(typeDeps: string[], pkg: Package) {
const devDeps = mkTypeDepSet(pkg.packageJson.devDependencies);
const deps = mkTypeDepSet({
...pkg.packageJson.dependencies,
@@ -204,19 +208,14 @@ function findTypeDepErrors(typeDeps, pkg) {
return errors;
}
function mkTypeDepSet(deps) {
function mkTypeDepSet(deps: Record<string, string> | undefined) {
const typeDeps = Object.keys(deps || {}).filter(n => n.startsWith('@types/'));
return new Set(typeDeps);
}
function mkErr(name, msg, extra) {
function mkErr(name: string, msg: string, extra: Record<string, string>) {
const error = new Error(msg);
error.name = name;
Object.assign(error, extra);
return error;
}
main().catch(error => {
console.error(error.stack || error);
process.exit(1);
});
+1
View File
@@ -8437,6 +8437,7 @@ __metadata:
resolution: "@backstage/repo-tools@workspace:packages/repo-tools"
dependencies:
"@backstage/errors": "workspace:^"
"@manypkg/get-packages": ^1.1.3
"@microsoft/api-documenter": ^7.17.11
"@microsoft/api-extractor": ^7.23.0
"@microsoft/api-extractor-model": ^7.17.2