feat(scripts): enable strict checking for additional sub-folders(packages) v3 (#25074)

* feat(scripts): enable strict checking for dependency-graph-generator

* feat(scripts): enable strict checking for jest/

* feat(scripts): enable strict checking for babel/

* feat(scripts): enable strict checking for api-extractor/

* feat(scripts): enable strict checking for typescript/

* feat(scripts): enable strict checking for webpack/

* feat(scripts): enable strict checking for tasks/

* feat(scripts): register new sub-folders to ts-solution config
This commit is contained in:
Martin Hochel 2022-10-11 15:47:43 +02:00 коммит произвёл GitHub
Родитель 2d36a7c692
Коммит df1e8f5f97
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
41 изменённых файлов: 333 добавлений и 114 удалений

Просмотреть файл

@ -124,6 +124,7 @@
"@testing-library/user-event": "13.5.0",
"@tsconfig/node14": "1.0.3",
"@types/babel__helper-plugin-utils": "7.10.0",
"@types/babel__register": "7.17.0",
"@types/chrome-remote-interface": "0.30.0",
"@types/circular-dependency-plugin": "5.0.5",
"@types/copy-webpack-plugin": "6.4.0",
@ -135,6 +136,7 @@
"@types/express": "4.17.2",
"@types/fs-extra": "8.0.1",
"@types/glob": "7.1.1",
"@types/graphviz": "0.0.34",
"@types/gulp": "4.0.9",
"@types/gulp-babel": "6.1.30",
"@types/gulp-cache": "0.4.5",
@ -161,6 +163,7 @@
"@types/scheduler": "0.16.2",
"@types/semver": "^6.2.0",
"@types/tmp": "0.2.0",
"@types/webpack-bundle-analyzer": "4.4.3",
"@types/webpack-dev-middleware": "4.1.0",
"@types/webpack-env": "1.16.0",
"@types/webpack-hot-middleware": "2.25.6",
@ -193,6 +196,7 @@
"danger": "^11.0.0",
"dedent": "0.7.0",
"del": "6.0.0",
"dotparser": "1.1.1",
"enhanced-resolve": "5.8.2",
"enquirer": "2.3.6",
"enzyme": "3.10.0",
@ -215,9 +219,11 @@
"extract-comments": "1.1.0",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "6.1.0",
"find-free-port": "2.0.0",
"fs-extra": "8.1.0",
"geckodriver": "3.0.2",
"glob": "7.2.0",
"graphviz": "0.0.9",
"gulp": "4.0.2",
"gulp-babel": "8.0.0",
"gulp-cache": "1.1.3",

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["*"]
}

Просмотреть файл

@ -1,14 +1,17 @@
const isNodeCaller = caller => {
return caller && (caller.name === '@babel/register' || caller.name === 'babel-jest');
/** @typedef {import('@babel/core').TransformOptions['caller']} Caller */
const isNodeCaller = (/** @type {Caller}*/ caller) => {
return Boolean(caller && (caller.name === '@babel/register' || caller.name === 'babel-jest'));
};
const isDistCaller = caller => {
const isDistCaller = (/** @type {Caller}*/ caller) => {
return !!(caller && caller.name === 'babel-gulp');
};
const supportsESM = caller => {
const supportsESM = (/** @type {Caller}*/ caller) => {
// @ts-expect-error - TODO: caller.useESModules api doesn't exists (types/implementation), is this a bug? https://babeljs.io/docs/en/options#caller
return !!((caller && caller.name === 'babel-loader') || caller.useESModules);
};
module.exports = api => {
module.exports = (/** @type {import('@babel/core').ConfigAPI} */ api) => {
const isDistBundle = api.caller(isDistCaller);
const isNode = api.caller(isNodeCaller);
const useESModules = !isNode && api.caller(supportsESM);

Просмотреть файл

@ -1,4 +1,3 @@
// @ts-ignore - @babel/register doesn't ship types
require('@babel/register')({
extensions: ['.js', '.ts', '.tsx'],
ignore: [/node_modules/],

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["*"]
}

Просмотреть файл

@ -1,12 +1,18 @@
const graphviz = require('graphviz');
const parser = require('dotparser');
const readFileSync = require('fs').readFileSync;
const spawnSync = require('child_process').spawnSync;
const findGitRoot = require('../monorepo/index').findGitRoot;
const getDependencies = require('../monorepo/index').getDependencies;
const parser = /** @type {typeof import('dotparser')['default']}*/ (/** @type {unknown} */ (require('dotparser')));
const { readFileSync } = require('fs');
const { spawnSync } = require('child_process');
const path = require('path');
const yargs = require('yargs');
/** @typedef {import('yargs').Arguments<{root:string;'include-dev'?:string;'graphviz-path'?:string}>} CliArgs */
const { findGitRoot, getDependencies } = require('../monorepo');
const dotFilePath = path.resolve(__dirname, 'repo-graph.dot');
/**
* @type {string[]}
*/
let ignoreDevDependencies = [];
/**
@ -14,6 +20,7 @@ let ignoreDevDependencies = [];
*
* For this utility to work you will actually need to install graphviz on your machine
* http://www.graphviz.org
* @param {CliArgs} argv
*/
async function main(argv) {
if (!argv.root) {
@ -81,8 +88,9 @@ function _parseDotFile(pathToDotFile) {
const items = parsed[0].children;
items.forEach(item => {
if (item.type === 'node_stmt') {
graph.addNode(item.node_id.id);
graph.addNode(String(item.node_id.id));
} else {
// @ts-expect-error - edge_list doesn't exist on type definition - is this a bug ?
graph.addEdge(item.edge_list[0].id, item.edge_list[1].id, { dir: 'forward' });
}
});
@ -130,8 +138,11 @@ function _getSubTree(graph, rootPackage) {
* @param {string} node id of the node
*/
function _getEdgesAndChildren(graph, node) {
/** @type any[] */
const edges = [];
/** @type any[] */
const children = [];
// @ts-expect-error - edges prop doesn't exist on typings - wrong typings ?
graph.edges.forEach(edge => {
if (ignoreDevDependencies.includes(edge.nodeOne.id) || ignoreDevDependencies.includes(edge.nodeTwo.id)) {
return;
@ -146,7 +157,7 @@ function _getEdgesAndChildren(graph, node) {
return { edges, children };
}
require('yargs')
yargs
.scriptName('dependency-graph-generator')
.usage('$0 [args]')
.command(
@ -168,7 +179,7 @@ require('yargs')
description: 'The path to graphviz which needs to be installed, required for windows users',
});
},
async argv => await main(argv),
async argv => await main(/** @type {CliArgs}*/ (argv)),
)
.demand('root')
.help().argv;

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["*"]
}

Просмотреть файл

@ -1,8 +1,7 @@
// @ts-check
const lernaAlias = require('../lernaAliasNorthstar');
const findGitRoot = require('../monorepo/findGitRoot');
module.exports = customConfig => ({
module.exports = (/** @type {import('@jest/types').Config.InitialOptions} */ customConfig) => ({
coverageDirectory: './coverage/',
coverageReporters: ['json', 'lcov'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],

Просмотреть файл

@ -13,7 +13,7 @@ class JestReporter extends DefaultReporter {
super(...args);
this._isLoggingError = false;
this.log = message => {
this.log = (/** @type {string} */ message) => {
if (this._isLoggingError) {
process.stderr.write(message + '\n');
} else {

Просмотреть файл

@ -1,20 +1,20 @@
// @ts-check
const fs = require('fs-extra');
const path = require('path');
const merge = require('../tasks/merge');
const resolve = require('resolve');
const { resolveCwd } = require('just-scripts');
const { findRepoDeps } = require('../monorepo/index');
const merge = require('../tasks/merge');
const { findRepoDeps } = require('../monorepo');
const findConfig = require('../find-config');
const packageJsonPath = findConfig('package.json');
const packageJsonPath = findConfig('package.json') ?? '';
const packageRoot = path.dirname(packageJsonPath);
const jestAliases = () => {
// Get deps of the current package within the repo
const packageDeps = findRepoDeps();
/** @type {Record<string,string>} */
const aliases = {};
for (const { packageJson } of packageDeps) {

Просмотреть файл

@ -19,6 +19,11 @@ const consoleError = console.error;
console.error = customError.bind(null, 'error');
console.warn = customError.bind(null, 'warn');
/**
*
* @param {string} type
* @param {any[]} args
*/
function customError(type, ...args) {
if (type === 'warn') {
consoleWarn(...args);

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": ["*"]
}

Просмотреть файл

@ -3,10 +3,22 @@ const chalk = require('chalk');
const isProduction = process.argv.indexOf('--production') > -1;
const isVerbose = process.argv.indexOf('--verbose') > -1;
/**
*
* @param {string} packageName
* @param {string} task
*/
module.exports.logStartTask = (packageName, task) => {
console.log(`${getTimePrefix(packageName)} Starting: ${chalk.cyan(task)}`);
};
/**
*
* @param {string} packageName
* @param {string} task
* @param {number} startTime
* @param {string} errorMessage
*/
module.exports.logEndTask = (packageName, task, startTime, errorMessage) => {
console.log(
`${getTimePrefix(packageName)} ${getPassFail(errorMessage === undefined)}: ${chalk.cyan(task)} (${getDuration(
@ -15,12 +27,22 @@ module.exports.logEndTask = (packageName, task, startTime, errorMessage) => {
);
};
/**
*
* @param {unknown} taskStatus
*/
module.exports.logStatus = taskStatus => {
if (isProduction || isVerbose) {
console.log(' ' + taskStatus);
}
};
/**
*
* @param {string} packageName
* @param {boolean} passed
* @param {number} startTime
*/
module.exports.logEndBuild = (packageName, passed, startTime) => {
console.log();
console.log(
@ -43,19 +65,40 @@ module.exports.logEndBuild = (packageName, passed, startTime) => {
);
};
/**
*
* @param {number} startTime
* @returns
*/
function getDuration(startTime) {
let duration = new Date().getTime() - startTime;
return chalk.yellow(formatTime(duration));
}
/**
*
* @param {boolean} passed
* @returns
*/
function getPassFail(passed) {
return passed ? chalk.green('Pass') : chalk.red('Error');
}
/**
*
* @param {string} packageName
* @returns
*/
function getTimePrefix(packageName) {
return `[${chalk.magenta(packageName)} ${chalk.gray(new Date().toLocaleTimeString([], { hour12: false }))}]`;
}
/**
*
* @param {number} milliseconds
* @returns
*/
function formatTime(milliseconds) {
if (milliseconds >= 1000) {
return milliseconds / 1000 + 's';

Просмотреть файл

@ -27,9 +27,6 @@
"connect-history-api-fallback": "^1.3.0",
"doctoc": "^2.0.1",
"doctrine": "^3.0.0",
"dotparser": "^1.0.0",
"find-free-port": "~2.0.0",
"graphviz": "^0.0.9",
"inquirer": "^7.3.3",
"lerna-alias": "^3.0.3-0",
"lerna-dependency-graph": "^1.0.2",

Просмотреть файл

@ -112,7 +112,7 @@ export function apiExtractor() {
}
},
onConfigLoaded: config => {
if (!isUsingTsSolutionConfigs) {
if (!(isUsingTsSolutionConfigs && tsConfig)) {
return;
}

Просмотреть файл

@ -36,7 +36,7 @@ function parseModule(args: Arguments & { module?: string | string[] }) {
);
}
acc[outputType] = true;
acc[outputType as keyof JustArgs['module']] = true;
return acc;
},

Просмотреть файл

@ -1,4 +1,4 @@
import { transformAsync } from '@babel/core';
import { BabelFileResult, transformAsync } from '@babel/core';
import * as glob from 'glob';
import fs from 'fs';
import { logger } from 'just-task';
@ -20,7 +20,7 @@ export async function babel() {
const codeBuffer = await fs.promises.readFile(filePath);
const sourceCode = codeBuffer.toString().replace(EOL_REGEX, '\n');
const result = await transformAsync(sourceCode, {
const result = (await transformAsync(sourceCode, {
ast: false,
sourceMaps: true,
@ -32,7 +32,7 @@ export async function babel() {
filename: filePath,
sourceFileName: path.basename(filename),
});
})) /* Bad `transformAsync` types. it can be null only if 2nd param is null(config)*/ as NonNullableRecord<BabelFileResult>;
const resultCode = addSourceMappingUrl(result.code, path.basename(filename) + '.map');
if (resultCode === sourceCode) {
@ -48,3 +48,7 @@ export async function babel() {
await fs.promises.writeFile(sourceMapFile, JSON.stringify(result.map));
}
}
type NonNullableRecord<T> = {
[P in keyof T]-?: NonNullable<T[P]>;
};

Просмотреть файл

@ -10,7 +10,7 @@ export function bundleSizeCollect() {
// information which gets reported by Size Auditor
const distRoot = path.join(__dirname, '../../apps/test-bundles/dist');
const sizes = {};
const sizes: Record<string, number> = {};
const outputFilename = 'bundlesize.json';
var items = fs.readdirSync(distRoot);
@ -25,11 +25,11 @@ export function bundleSizeCollect() {
fs.writeFileSync(path.join(distRoot, outputFilename), JSON.stringify({ sizes }));
function getFilesizeInBytes(fileName) {
function getFilesizeInBytes(fileName: string) {
return fs.statSync(fileName).size;
}
function getComponentName(fileName) {
function getComponentName(fileName: string) {
return path.basename(fileName, '.min.js');
}
}

Просмотреть файл

@ -4,7 +4,7 @@ import { series, resolveCwd, copyTask, copyInstructionsTask, logger } from 'just
import { getProjectMetadata, findGitRoot } from '../monorepo';
import { getTsPathAliasesConfig } from './utils';
export function expandSourcePath(pattern: string): string {
export function expandSourcePath(pattern: string): string | null {
if (!pattern) {
return null;
}
@ -29,6 +29,7 @@ export function expandSourcePath(pattern: string): string {
return pattern.replace(packageName, path.dirname(resolvedPackageJson));
} catch (e) {
console.error(e);
return null;
}
}
@ -42,7 +43,7 @@ export function copyCompiled() {
const packageDir = process.cwd();
if (!isUsingTsSolutionConfigs) {
if (!(isUsingTsSolutionConfigs && tsConfig)) {
throw new Error(`this task compliant only with packages that use TS solution config files.`);
}
@ -57,6 +58,13 @@ export function copyCompiled() {
const projectMetadata = getProjectMetadata({ root, name: packageJson.name });
if (!projectMetadata.sourceRoot) {
throw new Error(`${packageJson.name} is missing 'sourceRoot' in workspace.json`);
}
if (!packageJson.module) {
throw new Error(`${packageJson.name} is missing 'module' property in package.json`);
}
const paths = {
esm: {
in: path.join(
@ -110,7 +118,7 @@ export function copy() {
if (Array.isArray(sources)) {
return copyTask({
paths: sources.map(src => expandSourcePath(src)),
paths: sources.map(src => expandSourcePath(src)).filter(Boolean) as string[],
dest: destinationPath,
});
}

Просмотреть файл

@ -9,7 +9,7 @@ const beachballBin = require.resolve('beachball/bin/beachball.js');
const bumpCmd = [process.execPath, beachballBin, 'bump'];
const gitRoot = findGitRoot();
function run(args) {
function run(args: string[]) {
const [cmd, ...restArgs] = args;
const runResult = spawnSync(cmd, restArgs, { cwd: gitRoot });
if (runResult.status === 0) {
@ -59,7 +59,7 @@ export function generateVersionFiles() {
}
// 2. gather version info
const updatedVersionContents = {};
const updatedVersionContents: Record<string, string> = {};
const packageJsons = glob.sync('+(packages|apps)/*/package.json', { cwd: gitRoot });
packageJsons.forEach(packageJsonPath => {
const versionFile = path.join(gitRoot, path.dirname(packageJsonPath), 'src/version.ts');

Просмотреть файл

@ -1,4 +1,4 @@
import { getAllPackageInfo, findGitRoot } from '../monorepo/index';
import { getAllPackageInfo, findGitRoot } from '../monorepo';
import { readConfig } from '../read-config';
import * as glob from 'glob';
import * as path from 'path';
@ -119,7 +119,7 @@ export function lintImports() {
if (!exportStatements) {
_addError(importErrors.exportMulti, relativePath, 'no exported class or const');
} else if (exportStatements.length > 1) {
const exports = exportStatements.map(exp => exp.match(exportRegex)[2]);
const exports = exportStatements.map(exp => (exp.match(exportRegex) as RegExpMatchArray)[2]);
_addError(importErrors.exportMulti, relativePath, 'choose one of ' + exports.join(', '));
}
@ -144,10 +144,10 @@ export function lintImports() {
const importPath = importMatch[2];
const packageRootPath = importPath.split('/')[0];
const relativePath = path.relative(sourcePath, filePath);
let fullImportPath: string;
let fullImportPath: string | undefined;
let pathIsRelative = false;
let pathIsDeep = false;
let pkgName: string;
let pkgName: string | undefined = undefined;
if (importPath[0] === '.') {
// import is a file path. is this a file?
@ -211,12 +211,15 @@ export function lintImports() {
_addError(importErrors.pathDeep, relativePath, importPath);
}
if (reExportedPackages[pkgName] && !allowedReexportedImports.includes(importPath)) {
if (
reExportedPackages[pkgName as keyof typeof reExportedPackages] &&
!allowedReexportedImports.includes(importPath)
) {
_addError(
importErrors.pathReExported,
relativePath,
importPath,
'@fluentui/react/lib/' + reExportedPackages[pkgName],
'@fluentui/react/lib/' + reExportedPackages[pkgName as keyof typeof reExportedPackages],
);
}
@ -238,7 +241,7 @@ export function lintImports() {
}
}
return undefined;
return;
}
function _addError(errorGroup: ImportErrorGroup, relativePath: string, importPath: string, alternative?: string) {
@ -270,7 +273,7 @@ export function lintImports() {
};
let hasError = false;
for (const groupName of Object.keys(importErrors)) {
for (const groupName of Object.keys(importErrors) as Array<keyof ImportErrors>) {
const errorGroup: ImportErrorGroup = importErrors[groupName];
if (errorGroup.count) {
hasError = true;

Просмотреть файл

@ -1,4 +1,11 @@
module.exports = function merge(obj1, obj2) {
module.exports = merge;
/**
*
* @param {Record<string,any>} obj1
* @param {Record<string,any>} obj2
*/
function merge(obj1, obj2) {
const merged = Object.assign({}, obj1);
for (const prop in obj2) {
@ -15,4 +22,4 @@ module.exports = function merge(obj1, obj2) {
}
return merged;
};
}

Просмотреть файл

@ -3,7 +3,7 @@ import * as glob from 'glob';
import { sassTask } from 'just-scripts';
import postcssModules from 'postcss-modules';
const _fileNameToClassMap = {};
const _fileNameToClassMap: Record<string, Record<string, string>> = {};
function createTypeScriptModule(fileName: string, css: string) {
const { splitStyles } = require('@microsoft/load-themed-styles');

Просмотреть файл

@ -1,9 +1,14 @@
import { argv } from 'just-scripts';
import * as fs from 'fs';
import * as path from 'path';
import { findGitRoot } from '../monorepo/index';
import { findGitRoot } from '../monorepo';
import storybook from '@storybook/react/standalone';
// TODO: this should be replaced with `'@storybook/core-server';` API
// @ts-expect-error - standalone.js is basically private API/thus doesn't ship types. NOTE: Storybook can be run standalone from Node, although it should be noted this isn't officially supported any more. - https://github.com/storybookjs/storybook/blob/master/lib/core/docs/standalone.md#standalone-mode
import _storybook from '@storybook/react/standalone';
const storybook: StorybookStandaloneBuildFn = _storybook;
type StorybookStandaloneBuildFn = (options?: StorybookDevOptions | StorybookStaticOptions) => Promise<void>;
// Option types are documented here but not included in package for some reason
// https://github.com/storybookjs/storybook/blob/master/lib/core/docs/standalone.md

Просмотреть файл

@ -24,7 +24,7 @@ function prepareTsTaskConfig(options: TscTaskOptions) {
const { isUsingTsSolutionConfigs, tsConfigFile, tsConfig } = getTsPathAliasesConfig();
if (isUsingTsSolutionConfigs) {
if (isUsingTsSolutionConfigs && tsConfig) {
logger.info(`📣 TSC: package is using TS path aliases. Overriding tsconfig settings.`);
const tsConfigOutDir = tsConfig.compilerOptions.outDir as string;

Просмотреть файл

@ -0,0 +1,8 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": ["*"],
"files": ["../../typings/find-free-port/index.d.ts"]
}

Просмотреть файл

@ -24,6 +24,15 @@
"./prettier/**",
"./fluentui-publish/**",
"./puppeteer/**",
"./triage-bot/**"
"./triage-bot/**",
"./webpack/**",
"./jest/**",
"./dependency-graph-generator/**",
"./typescript/**",
"./tasks/**",
"./babel/**",
"./api-extractor/**",
"./typescript/**",
"./lint-staged/**"
]
}

Просмотреть файл

@ -11,6 +11,30 @@
"include": [],
"files": [],
"references": [
{
"path": "./api-extractor/tsconfig.json"
},
{
"path": "./babel/tsconfig.json"
},
{
"path": "./lint-staged/tsconfig.json"
},
{
"path": "./typescript/tsconfig.json"
},
{
"path": "./tasks/tsconfig.json"
},
{
"path": "./jest/tsconfig.json"
},
{
"path": "./webpack/tsconfig.json"
},
{
"path": "./dependency-graph-generator/tsconfig.json"
},
{
"path": "./triage-bot/tsconfig.json"
},

Просмотреть файл

@ -1,5 +1,3 @@
// @ts-check
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');

Просмотреть файл

@ -1,5 +1,3 @@
// @ts-check
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": ["*"]
}

Просмотреть файл

@ -9,10 +9,11 @@
* Helper which resolves a specific set of environment variable values. If not present,
* the provided default values will be returned.
*
* @param options - A object where the keys are the environment variables to read,
* @param {Record<string,string>} options - A object where the keys are the environment variables to read,
* and their values represent the default value to use if the variable is not present.
*/
const getVariables = options => {
/** @type {Record<string,string>} */
const variables = {};
for (const key of Object.keys(options)) {
@ -28,9 +29,9 @@ const getVariables = options => {
* Function which returns DefinePlugin options for a specific set of environment variables.
* This is needed because Webpack 5 no longer automatically resolves process.env values.
*
* @param {boolean=} isProduction - If true will ensure NODE_ENV is 'production', even
* @param {boolean} [isProduction] - If true will ensure NODE_ENV is 'production', even
* if environment variables specify otherwise.
* @param {object=} otherValues - Other values to include in the environment. Key is the
* @param {Record<string,string>} [otherValues] - Other values to include in the environment. Key is the
* environment variable name and value is the non-stringified value.
*/
module.exports = (isProduction, otherValues) => ({

Просмотреть файл

@ -1,7 +1,6 @@
// @ts-check
const path = require('path');
const { findRepoDeps, findGitRoot } = require('../monorepo/index');
const { findRepoDeps, findGitRoot } = require('../monorepo');
const { readConfig } = require('../read-config');
/**
@ -87,7 +86,6 @@ function getResolveAlias(useLib, cwd) {
module.exports = getResolveAlias;
// @ts-ignore
if (require.main === module) {
console.log(getResolveAlias());
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.scripts.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["*"]
}

Просмотреть файл

@ -1,23 +1,21 @@
// @ts-check
/**
* @typedef {import("webpack").Configuration} WebpackConfig
* @typedef {WebpackConfig & { devServer?: object }} WebpackServeConfig
* @typedef {import("webpack").ModuleOptions} WebpackModule
* @typedef {import("webpack").Configuration['output']} WebpackOutput
*/
/** */
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
/** @type {(c1: Partial<WebpackServeConfig>, c2: Partial<WebpackServeConfig>) => WebpackServeConfig} */
const merge = require('../tasks/merge');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const getResolveAlias = require('./getResolveAlias');
const { findGitRoot } = require('../monorepo/index');
// @ts-ignore - accessing package.json is a private API access, thus ignoring TS here
const webpackVersion = /** @type {string} */ (require('webpack/package.json').version);
const merge = require('../tasks/merge');
const { findGitRoot } = require('../monorepo');
const getResolveAlias = require('./getResolveAlias');
// @ts-ignore
const webpackVersion = require('webpack/package.json').version;
const getDefaultEnvironmentVars = require('./getDefaultEnvironmentVars');
console.log(`Webpack version: ${webpackVersion}`);
@ -318,8 +316,16 @@ module.exports = {
},
};
/**
*
* @param {string} bundleName
* @param {boolean} isProduction
* @param {boolean} [profile]
* @returns
*/
function getPlugins(bundleName, isProduction, profile) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
/** @type {webpack.WebpackPluginInstance[]} */
const plugins = [new webpack.DefinePlugin(getDefaultEnvironmentVars(isProduction))];
if (isProduction && profile) {

Просмотреть файл

@ -15,18 +15,19 @@ const { paths } = config;
// ERROR: https://github.com/webpack/webpack/issues/7378
// HACK FIX: https://github.com/TypeStrong/ts-loader/issues/653
class IgnoreNotFoundExportPlugin {
apply(compiler) {
apply(compiler: webpack.Compiler) {
const messageRegExp = /export '.*'( \(reexported as '.*'\))? was not found in/;
const doneHook = stats => {
const doneHook = (stats: any) => {
stats.compilation.warnings = stats.compilation.warnings.filter(
warn => !(warn && messageRegExp.test(warn.message)),
(warn: any) => !(warn && messageRegExp.test(warn.message)),
);
};
if (compiler.hooks) {
compiler.hooks.done.tap('IgnoreNotFoundExportPlugin', doneHook);
} else {
// @ts-expect-error - TODO: this api is non existent thus this probably doesn't work anymore ?
compiler.plugin('done', doneHook);
}
}
@ -60,23 +61,25 @@ const makeConfig = (srcPath: string, name: string): webpack.Configuration => ({
react: 'react',
'react-dom': 'reactDOM',
},
...(argv.debug && {
optimization: {
minimizer: [
new TerserWebpackPlugin({
parallel: true,
terserOptions: {
mangle: false,
output: {
beautify: true,
comments: true,
preserve_annotations: true,
},
},
}),
],
},
}),
...(argv.debug
? {
optimization: {
minimizer: [
new TerserWebpackPlugin({
parallel: true,
terserOptions: {
mangle: false,
output: {
beautify: true,
comments: true,
preserve_annotations: true,
},
},
}),
],
},
}
: null),
plugins: [
new CleanWebpackPlugin(),
new IgnoreNotFoundExportPlugin(),
@ -94,7 +97,7 @@ const makeConfig = (srcPath: string, name: string): webpack.Configuration => ({
},
});
const toEsDistPath = srcPath => {
const toEsDistPath = (srcPath: string) => {
return paths.packageDist('react-northstar', path.join('es', srcPath));
};

Просмотреть файл

@ -13,10 +13,11 @@ import getDefaultEnvironmentVars from './getDefaultEnvironmentVars';
const { paths } = config;
const { __DEV__, __PERF__, __PROD__ } = config.compiler_globals;
const webpackConfig: webpack.Configuration = {
const webpackConfig: webpack.Configuration &
Required<Pick<webpack.Configuration, 'plugins' | 'optimization'>> & { entry: Record<string, string | string[]> } = {
name: 'client',
target: 'web',
mode: config.compiler_mode,
mode: config.compiler_mode!,
entry: {
app: paths.docsSrc('index'),
},
@ -109,16 +110,17 @@ const webpackConfig: webpack.Configuration = {
}),
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/),
__DEV__ &&
// Disable ProgressPlugin in CI and multi-project build because the outdated lines can't be deleted and
// spam the log (note that build:docs is the resolved command used by lerna run build --stream)
!process.env.TF_BUILD &&
!process.argv.includes('build:docs') &&
new webpack.ProgressPlugin({
entries: true,
modules: true,
modulesCount: 500,
} as any),
].filter(Boolean),
// Disable ProgressPlugin in CI and multi-project build because the outdated lines can't be deleted and
// spam the log (note that build:docs is the resolved command used by lerna run build --stream)
!process.env.TF_BUILD &&
!process.argv.includes('build:docs')
? new webpack.ProgressPlugin({
entries: true,
modules: true,
modulesCount: 500,
})
: null,
].filter(Boolean) as webpack.WebpackPluginInstance[],
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
alias: {
@ -165,8 +167,9 @@ if (__DEV__) {
},
(val, key) => `&${key}=${val}`,
).join('')}`;
const entry = webpackConfig.entry as webpack.EntryObject;
entry.app = [webpackHotMiddlewareEntry].concat(entry.app as string);
const entry = webpackConfig.entry;
entry.app = [webpackHotMiddlewareEntry].concat(entry.app);
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin());
}

8
typings/find-free-port/index.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
// Type definitions for find-free-port 2.0.0
declare module 'find-free-port' {
function findFreePort(args: [...values: Array<string | number>, cb: (err: unknown, freePort: number) => void]): any;
function findFreePort(...args: Array<string | number>): Promise<number>;
export default findFreePort;
}

Просмотреть файл

@ -0,0 +1,5 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {},
"include": ["*.d.ts"]
}

Просмотреть файл

@ -27,6 +27,9 @@
},
{
"path": "./json-stable-stringify-without-jsonify/tsconfig.json"
},
{
"path": "./find-free-port/tsconfig.json"
}
]
}

Просмотреть файл

@ -5300,6 +5300,13 @@
dependencies:
"@types/babel__core" "*"
"@types/babel__register@7.17.0":
version "7.17.0"
resolved "https://registry.yarnpkg.com/@types/babel__register/-/babel__register-7.17.0.tgz#fcb3ee6bfe9314215a0af5de7d9f19faf4144e50"
integrity sha512-/iL2G2eq5drPFQpzb/wMYk7B0LMWRpWajnPn1XuIzeQ2w+CRrzNbwJ5xpBdZkciYx0jqZa8h40dTXpMeTcGV7A==
dependencies:
"@types/babel__core" "*"
"@types/babel__template@*":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
@ -5705,6 +5712,13 @@
dependencies:
"@types/node" "*"
"@types/graphviz@0.0.34":
version "0.0.34"
resolved "https://registry.yarnpkg.com/@types/graphviz/-/graphviz-0.0.34.tgz#40657ce27383e3bd36bea6a4b7449866f3caa8eb"
integrity sha512-5pyobgT+/NhwKy/LMLw14xFInvYXBPx4ITc2a5FvZbm6hcudcP73DpTKTlaZbjr8fdNAkaK9KdP8GAEF0iBwlQ==
dependencies:
"@types/node" "*"
"@types/gulp-babel@6.1.30":
version "6.1.30"
resolved "https://registry.yarnpkg.com/@types/gulp-babel/-/gulp-babel-6.1.30.tgz#72220a2e72517bd2cf461fc6250849035ad58798"
@ -6437,6 +6451,15 @@
"@types/expect" "^1.20.4"
"@types/node" "*"
"@types/webpack-bundle-analyzer@4.4.3":
version "4.4.3"
resolved "https://registry.yarnpkg.com/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.3.tgz#1f8eba759677a3bf094166572fc7debf68161f61"
integrity sha512-7+4XhCMxc1XyQr2lwAbEEeWTax+FX70xMeskU0WtxrODczoOZXTo9vrYh/XF7pAOn+NxqR4yRKW5gfz1HHNnfw==
dependencies:
"@types/node" "*"
tapable "^2.2.0"
webpack "^5"
"@types/webpack-dev-middleware@4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@types/webpack-dev-middleware/-/webpack-dev-middleware-4.1.0.tgz#3bf432f2ff2313b6470af21b748dd5d73dba5ec6"
@ -11901,10 +11924,10 @@ dotenv@~10.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
dotparser@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dotparser/-/dotparser-1.0.0.tgz#32458fcfa855046705b90df929ed87a849e32304"
integrity sha512-yIvKnnQbK8dhh6aN44xNPd00FuHWVygAW8iYW05DCgzGzHJfe/VaQQAoq3QBDAa8cMFS7Lub8SCAsej/lLUomQ==
dotparser@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/dotparser/-/dotparser-1.1.1.tgz#c474942f329638b44ddb3dff27e9a6385dbab2f9"
integrity sha512-8ojhUts0HbLnXJgjTiJOddwVVBUk6hg4SJ5kGiuhzgK/f+y79TiWvICwx1oCWlVbBC8YI3nEaIQg9fjGYbGBXw==
download@^7.1.0:
version "7.1.0"
@ -13754,10 +13777,10 @@ find-cache-dir@^3.3.1:
make-dir "^3.0.2"
pkg-dir "^4.1.0"
find-free-port@~2.0.0:
find-free-port@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b"
integrity sha1-SyLl9leesaOMQaxryz7+0bbamxs=
integrity sha512-J1j8gfEVf5FN4PR5w5wrZZ7NYs2IvqsHcd03cAeQx3Ec/mo+lKceaVNhpsRKoZpZKbId88o8qh+dwUwzBV6WCg==
find-replace@^3.0.0:
version "3.0.0"
@ -14967,7 +14990,7 @@ graceful-fs@^4.2.9:
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
graphviz@0.0.9, graphviz@^0.0.9:
graphviz@0.0.9:
version "0.0.9"
resolved "https://registry.yarnpkg.com/graphviz/-/graphviz-0.0.9.tgz#0bbf1df588c6a92259282da35323622528c4bbc4"
integrity sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==