move tooling into separate repo, add type generation and test types

This commit is contained in:
Tobias Koppers 2020-03-21 14:01:38 +01:00
parent 04e43c0faa
commit 3f9e6d5ec6
36 changed files with 10154 additions and 1334 deletions

View File

@ -1,3 +1,5 @@
package.json
# Ignore test fixtures
test/*.*
!test/*.js

View File

@ -8,8 +8,15 @@ module.exports = {
{
files: "*.json",
options: {
parser: "json",
useTabs: false
}
},
{
files: "*.ts",
options: {
parser: "typescript"
}
}
]
};

5
declarations.d.ts vendored
View File

@ -385,3 +385,8 @@ declare module "enhanced-resolve" {
}
type TODO = any;
type RecursiveArrayOrRecord<T> =
| { [index: string]: RecursiveArrayOrRecord<T> }
| Array<RecursiveArrayOrRecord<T>>
| T;

View File

@ -19,11 +19,14 @@ export type Bail = boolean;
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
export type Cache = true | CacheNormalized;
export type CacheOptions = true | CacheOptionsNormalized;
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
export type CacheNormalized = false | MemoryCacheOptions | FileCacheOptions;
export type CacheOptionsNormalized =
| false
| MemoryCacheOptions
| FileCacheOptions;
/**
* The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory.
*/
@ -489,7 +492,7 @@ export type ResolveLoader = ResolveOptions;
/**
* Stats options object or preset name.
*/
export type Stats =
export type StatsValue =
| (
| "none"
| "errors-only"
@ -555,7 +558,7 @@ export interface WebpackOptions {
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
cache?: Cache;
cache?: CacheOptions;
/**
* The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory.
*/
@ -603,7 +606,7 @@ export interface WebpackOptions {
/**
* Options affecting the normal modules (`NormalModuleFactory`).
*/
module?: Module;
module?: ModuleOptions;
/**
* Name of the configuration. Used when loading multiple configurations.
*/
@ -659,7 +662,7 @@ export interface WebpackOptions {
/**
* Stats options object or preset name.
*/
stats?: Stats;
stats?: StatsValue;
/**
* Environment to build for.
*/
@ -906,7 +909,7 @@ export interface Loader {
/**
* Options affecting the normal modules (`NormalModuleFactory`).
*/
export interface Module {
export interface ModuleOptions {
/**
* An array of rules applied by default for modules.
*/
@ -2096,7 +2099,7 @@ export interface WebpackOptionsNormalized {
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
cache: CacheNormalized;
cache: CacheOptionsNormalized;
/**
* The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory.
*/
@ -2144,7 +2147,7 @@ export interface WebpackOptionsNormalized {
/**
* Options affecting the normal modules (`NormalModuleFactory`).
*/
module: Module;
module: ModuleOptions;
/**
* Name of the configuration. Used when loading multiple configurations.
*/
@ -2196,7 +2199,7 @@ export interface WebpackOptionsNormalized {
/**
* Stats options object or preset name.
*/
stats: Stats;
stats: StatsValue;
/**
* Environment to build for.
*/

5
generate-types-config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
nameMapping: {
FsStats: /^Stats Import fs/
}
};

View File

@ -16,8 +16,8 @@ const {
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
/** @typedef {null|undefined|RegExp|Function|string|number} CodeValuePrimitive */
/** @typedef {CodeValuePrimitive|Record<string, CodeValuePrimitive>|RuntimeValue} CodeValue */
/** @typedef {null|undefined|RegExp|Function|string|number|boolean|bigint|undefined} CodeValuePrimitive */
/** @typedef {RecursiveArrayOrRecord<CodeValuePrimitive|RuntimeValue>} CodeValue */
class RuntimeValue {
constructor(fn, fileDependencies) {

View File

@ -15,9 +15,11 @@ const webpackSchema = require("../schemas/WebpackOptions.json");
* @property {string} path the path in the config
*/
/** @typedef {"unknown-argument" | "unexpected-non-array-in-path" | "unexpected-non-object-in-path" | "multiple-values-unexpected" | "invalid-value"} ProblemType */
/**
* @typedef {Object} Problem
* @property {string} type
* @property {ProblemType} type
* @property {string} path
* @property {string} argument
* @property {any=} value
@ -27,7 +29,7 @@ const webpackSchema = require("../schemas/WebpackOptions.json");
/**
* @typedef {Object} LocalProblem
* @property {string} type
* @property {ProblemType} type
* @property {string} path
* @property {string=} expected
*/
@ -563,7 +565,7 @@ const parseValueForArgumentConfig = (argConfig, value) => {
/**
* @param {Record<string, Argument>} args object of arguments
* @param {any} config configuration
* @param {Record<string, string | number | boolean | RegExp>} values object with values
* @param {Record<string, string | number | boolean | RegExp | (string | number | boolean | RegExp)[]>} values object with values
* @returns {Problem[] | null} problems or null for success
*/
const processArguments = (args, config, values) => {

View File

@ -8,13 +8,13 @@
const path = require("path");
const Template = require("../Template");
/** @typedef {import("../../declarations/WebpackOptions").CacheNormalized} WebpackCache */
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */
/** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
/** @typedef {import("../../declarations/WebpackOptions").Library} Library */
/** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").Module} WebpackModule */
/** @typedef {import("../../declarations/WebpackOptions").ModuleOptions} ModuleOptions */
/** @typedef {import("../../declarations/WebpackOptions").Node} WebpackNode */
/** @typedef {import("../../declarations/WebpackOptions").Optimization} Optimization */
/** @typedef {import("../../declarations/WebpackOptions").Output} Output */
@ -178,7 +178,7 @@ const applyExperimentsDefaults = experiments => {
};
/**
* @param {WebpackCache} cache options
* @param {CacheOptions} cache options
* @param {Object} options options
* @param {string} options.name name
* @param {string} options.mode mode
@ -256,7 +256,7 @@ const applyCacheDefaults = (cache, { name, mode }) => {
};
/**
* @param {WebpackModule} module options
* @param {ModuleOptions} module options
* @param {Object} options options
* @param {boolean} options.cache is caching enabled
* @param {boolean} options.mjs is mjs enabled

View File

@ -28,7 +28,7 @@ const ConstDependency = require("./ConstDependency");
const LocalModuleDependency = require("./LocalModuleDependency");
const UnsupportedDependency = require("./UnsupportedDependency");
/** @typedef {import("../../declarations/WebpackOptions").Module} ModuleOptions */
/** @typedef {import("../../declarations/WebpackOptions").ModuleOptions} ModuleOptions */
/** @typedef {import("../Compiler")} Compiler */
class AMDPlugin {

View File

@ -14,163 +14,327 @@ const memorize = require("./util/memorize");
const validateSchema = require("./validateSchema");
const webpack = require("./webpack");
module.exports = webpack;
module.exports.WebpackOptionsApply = WebpackOptionsApply;
module.exports.validate = validateSchema.bind(null, webpackOptionsSchema);
module.exports.validateSchema = validateSchema;
module.exports.version = version;
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} Configuration */
const exportPlugins = (obj, mappings) => {
for (const name of Object.keys(mappings)) {
Object.defineProperty(obj, name, {
configurable: false,
enumerable: true,
get: memorize(mappings[name])
});
module.exports = Object.assign(webpack, {
webpack,
WebpackOptionsApply,
validate: validateSchema.bind(null, webpackOptionsSchema),
validateSchema,
version,
get cli() {
return require("./cli");
},
get AutomaticPrefetchPlugin() {
return require("./AutomaticPrefetchPlugin");
},
get BannerPlugin() {
return require("./BannerPlugin");
},
get Cache() {
return require("./Cache");
},
get Compilation() {
return require("./Compilation");
},
get Compiler() {
return require("./Compiler");
},
get ContextExclusionPlugin() {
return require("./ContextExclusionPlugin");
},
get ContextReplacementPlugin() {
return require("./ContextReplacementPlugin");
},
get DefinePlugin() {
return require("./DefinePlugin");
},
get DelegatedPlugin() {
return require("./DelegatedPlugin");
},
get Dependency() {
return require("./Dependency");
},
get DllPlugin() {
return require("./DllPlugin");
},
get DllReferencePlugin() {
return require("./DllReferencePlugin");
},
get EntryPlugin() {
return require("./EntryPlugin");
},
get EnvironmentPlugin() {
return require("./EnvironmentPlugin");
},
get EvalDevToolModulePlugin() {
return require("./EvalDevToolModulePlugin");
},
get EvalSourceMapDevToolPlugin() {
return require("./EvalSourceMapDevToolPlugin");
},
get ExternalsPlugin() {
return require("./ExternalsPlugin");
},
get Generator() {
return require("./Generator");
},
get HotModuleReplacementPlugin() {
return require("./HotModuleReplacementPlugin");
},
get IgnorePlugin() {
return require("./IgnorePlugin");
},
get JavascriptModulesPlugin() {
return util.deprecate(
() => require("./javascript/JavascriptModulesPlugin"),
"webpack.JavascriptModulesPlugin has moved to webpack.javascript.JavascriptModulesPlugin",
"DEP_WEBPACK_JAVASCRIPT_MODULES_PLUGIN"
)();
},
get LibManifestPlugin() {
return require("./LibManifestPlugin");
},
get LibraryTemplatePlugin() {
return util.deprecate(
() => require("./LibraryTemplatePlugin"),
"webpack.LibraryTemplatePlugin is deprecated and has been replaced by compilation.outputOptions.library or compilation.addEntry + passing a library option",
"DEP_WEBPACK_LIBRARY_TEMPLATE_PLUGIN"
)();
},
get LoaderOptionsPlugin() {
return require("./LoaderOptionsPlugin");
},
get LoaderTargetPlugin() {
return require("./LoaderTargetPlugin");
},
get Module() {
return require("./Module");
},
get ModuleFilenameHelpers() {
return require("./ModuleFilenameHelpers");
},
get NoEmitOnErrorsPlugin() {
return require("./NoEmitOnErrorsPlugin");
},
get NormalModule() {
return require("./NormalModule");
},
get NormalModuleReplacementPlugin() {
return require("./NormalModuleReplacementPlugin");
},
get MultiCompiler() {
return require("./MultiCompiler");
},
get Parser() {
return require("./Parser");
},
get PrefetchPlugin() {
return require("./PrefetchPlugin");
},
get ProgressPlugin() {
return require("./ProgressPlugin");
},
get ProvidePlugin() {
return require("./ProvidePlugin");
},
get RuntimeGlobals() {
return require("./RuntimeGlobals");
},
get RuntimeModule() {
return require("./RuntimeModule");
},
get SingleEntryPlugin() {
return util.deprecate(
() => require("./EntryPlugin"),
"SingleEntryPlugin was renamed to EntryPlugin",
"DEP_WEBPACK_SINGLE_ENTRY_PLUGIN"
)();
},
get SourceMapDevToolPlugin() {
return require("./SourceMapDevToolPlugin");
},
get Stats() {
return require("./Stats");
},
get Template() {
return require("./Template");
},
get WatchIgnorePlugin() {
return require("./WatchIgnorePlugin");
},
get WebpackOptionsDefaulter() {
return util.deprecate(
() => require("./WebpackOptionsDefaulter"),
"webpack.WebpackOptionsDefaulter is deprecated and has been replaced by webpack.config.getNormalizedWebpackOptions and webpack.config.applyWebpackOptionsDefaults",
"DEP_WEBPACK_OPTIONS_DEFAULTER"
)();
},
// TODO webpack 6 deprecate
get WebpackOptionsValidationError() {
return validate.ValidationError;
},
get ValidationError() {
return validate.ValidationError;
},
cache: {
get MemoryCachePlugin() {
return require("./cache/MemoryCachePlugin");
}
},
config: {
get getNormalizedWebpackOptions() {
return require("./config/normalization").getNormalizedWebpackOptions;
},
get applyWebpackOptionsDefaults() {
return require("./config/defaults").applyWebpackOptionsDefaults;
}
},
ids: {
get ChunkModuleIdRangePlugin() {
return require("./ids/ChunkModuleIdRangePlugin");
},
get NaturalModuleIdsPlugin() {
return require("./ids/NaturalModuleIdsPlugin");
},
get OccurrenceModuleIdsPlugin() {
return require("./ids/OccurrenceModuleIdsPlugin");
},
get NamedModuleIdsPlugin() {
return require("./ids/NamedModuleIdsPlugin");
},
get DeterministicModuleIdsPlugin() {
return require("./ids/DeterministicModuleIdsPlugin");
},
get NamedChunkIdsPlugin() {
return require("./ids/NamedChunkIdsPlugin");
},
get OccurrenceChunkIdsPlugin() {
return require("./ids/OccurrenceChunkIdsPlugin");
},
get HashedModuleIdsPlugin() {
return require("./ids/HashedModuleIdsPlugin");
}
},
javascript: {
get JavascriptModulesPlugin() {
return require("./javascript/JavascriptModulesPlugin");
}
},
optimize: {
get AggressiveMergingPlugin() {
return require("./optimize/AggressiveMergingPlugin");
},
get AggressiveSplittingPlugin() {
return util.deprecate(
() => require("./optimize/AggressiveSplittingPlugin"),
"AggressiveSplittingPlugin is deprecated in favor of SplitChunksPlugin",
"DEP_WEBPACK_AGGRESSIVE_SPLITTING_PLUGIN"
)();
},
get LimitChunkCountPlugin() {
return require("./optimize/LimitChunkCountPlugin");
},
get MinChunkSizePlugin() {
return require("./optimize/MinChunkSizePlugin");
},
get ModuleConcatenationPlugin() {
return require("./optimize/ModuleConcatenationPlugin");
},
get RuntimeChunkPlugin() {
return require("./optimize/RuntimeChunkPlugin");
},
get SideEffectsFlagPlugin() {
return require("./optimize/SideEffectsFlagPlugin");
},
get SplitChunksPlugin() {
return require("./optimize/SplitChunksPlugin");
}
},
web: {
get FetchCompileWasmPlugin() {
return require("./web/FetchCompileWasmPlugin");
},
get JsonpTemplatePlugin() {
return require("./web/JsonpTemplatePlugin");
}
},
webworker: {
get WebWorkerTemplatePlugin() {
return require("./webworker/WebWorkerTemplatePlugin");
}
},
node: {
get NodeEnvironmentPlugin() {
return require("./node/NodeEnvironmentPlugin");
},
get NodeTemplatePlugin() {
return require("./node/NodeTemplatePlugin");
},
get ReadFileCompileWasmPlugin() {
return require("./node/ReadFileCompileWasmPlugin");
}
},
wasm: {
get AsyncWebAssemblyModulesPlugin() {
return require("./wasm-async/AsyncWebAssemblyModulesPlugin");
}
},
library: {
get AbstractLibraryPlugin() {
return require("./library/AbstractLibraryPlugin");
},
get EnableLibraryPlugin() {
return require("./library/EnableLibraryPlugin");
}
},
debug: {
get ProfilingPlugin() {
return require("./debug/ProfilingPlugin");
}
},
util: {
get createHash() {
return require("./util/createHash");
},
get comparators() {
return require("./util/comparators");
},
get serialization() {
return require("./util/serialization");
}
}
});
const finishExports = obj => {
const descriptors = Object.getOwnPropertyDescriptors(obj);
for (const name of Object.keys(descriptors)) {
const descriptor = descriptors[name];
if (descriptor.get) {
const fn = descriptor.get;
Object.defineProperty(obj, name, {
configurable: false,
enumerable: true,
get: memorize(fn)
});
} else if (typeof descriptor.value === "object") {
finishExports(descriptor.value);
}
}
Object.freeze(obj);
};
exportPlugins(module.exports, {
cli: () => require("./cli"),
AutomaticPrefetchPlugin: () => require("./AutomaticPrefetchPlugin"),
BannerPlugin: () => require("./BannerPlugin"),
Cache: () => require("./Cache"),
Compilation: () => require("./Compilation"),
Compiler: () => require("./Compiler"),
ContextExclusionPlugin: () => require("./ContextExclusionPlugin"),
ContextReplacementPlugin: () => require("./ContextReplacementPlugin"),
DefinePlugin: () => require("./DefinePlugin"),
DelegatedPlugin: () => require("./DelegatedPlugin"),
Dependency: () => require("./Dependency"),
DllPlugin: () => require("./DllPlugin"),
DllReferencePlugin: () => require("./DllReferencePlugin"),
EntryPlugin: () => require("./EntryPlugin"),
EnvironmentPlugin: () => require("./EnvironmentPlugin"),
EvalDevToolModulePlugin: () => require("./EvalDevToolModulePlugin"),
EvalSourceMapDevToolPlugin: () => require("./EvalSourceMapDevToolPlugin"),
ExternalsPlugin: () => require("./ExternalsPlugin"),
Generator: () => require("./Generator"),
HotModuleReplacementPlugin: () => require("./HotModuleReplacementPlugin"),
IgnorePlugin: () => require("./IgnorePlugin"),
JavascriptModulesPlugin: util.deprecate(
() => require("./javascript/JavascriptModulesPlugin"),
"webpack.JavascriptModulesPlugin has moved to webpack.javascript.JavascriptModulesPlugin",
"DEP_WEBPACK_JAVASCRIPT_MODULES_PLUGIN"
),
LibManifestPlugin: () => require("./LibManifestPlugin"),
LibraryTemplatePlugin: util.deprecate(
() => require("./LibraryTemplatePlugin"),
"webpack.LibraryTemplatePlugin is deprecated and has been replaced by compilation.outputOptions.library or compilation.addEntry + passing a library option",
"DEP_WEBPACK_LIBRARY_TEMPLATE_PLUGIN"
),
LoaderOptionsPlugin: () => require("./LoaderOptionsPlugin"),
LoaderTargetPlugin: () => require("./LoaderTargetPlugin"),
Module: () => require("./Module"),
ModuleFilenameHelpers: () => require("./ModuleFilenameHelpers"),
NoEmitOnErrorsPlugin: () => require("./NoEmitOnErrorsPlugin"),
NormalModule: () => require("./NormalModule"),
NormalModuleReplacementPlugin: () =>
require("./NormalModuleReplacementPlugin"),
MultiCompiler: () => require("./MultiCompiler"),
Parser: () => require("./Parser"),
PrefetchPlugin: () => require("./PrefetchPlugin"),
ProgressPlugin: () => require("./ProgressPlugin"),
ProvidePlugin: () => require("./ProvidePlugin"),
RuntimeGlobals: () => require("./RuntimeGlobals"),
RuntimeModule: () => require("./RuntimeModule"),
SingleEntryPlugin: util.deprecate(
() => require("./EntryPlugin"),
"SingleEntryPlugin was renamed to EntryPlugin",
"DEP_WEBPACK_SINGLE_ENTRY_PLUGIN"
),
SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"),
Stats: () => require("./Stats"),
Template: () => require("./Template"),
WatchIgnorePlugin: () => require("./WatchIgnorePlugin"),
WebpackOptionsDefaulter: util.deprecate(
() => require("./WebpackOptionsDefaulter"),
"webpack.WebpackOptionsDefaulter is deprecated and has been replaced by webpack.config.getNormalizedWebpackOptions and webpack.config.applyWebpackOptionsDefaults",
"DEP_WEBPACK_OPTIONS_DEFAULTER"
),
// TODO webpack 6 deprecate
WebpackOptionsValidationError: () => validate.ValidationError,
ValidationError: () => validate.ValidationError
});
exportPlugins((module.exports.cache = {}), {
MemoryCachePlugin: () => require("./cache/MemoryCachePlugin")
});
exportPlugins((module.exports.config = {}), {
getNormalizedWebpackOptions: () =>
require("./config/normalization").getNormalizedWebpackOptions,
applyWebpackOptionsDefaults: () =>
require("./config/defaults").applyWebpackOptionsDefaults
});
exportPlugins((module.exports.ids = {}), {
ChunkModuleIdRangePlugin: () => require("./ids/ChunkModuleIdRangePlugin"),
NaturalModuleIdsPlugin: () => require("./ids/NaturalModuleIdsPlugin"),
OccurrenceModuleIdsPlugin: () => require("./ids/OccurrenceModuleIdsPlugin"),
NamedModuleIdsPlugin: () => require("./ids/NamedModuleIdsPlugin"),
DeterministicModuleIdsPlugin: () =>
require("./ids/DeterministicModuleIdsPlugin"),
NamedChunkIdsPlugin: () => require("./ids/NamedChunkIdsPlugin"),
OccurrenceChunkIdsPlugin: () => require("./ids/OccurrenceChunkIdsPlugin"),
HashedModuleIdsPlugin: () => require("./ids/HashedModuleIdsPlugin")
});
exportPlugins((module.exports.javascript = {}), {
JavascriptModulesPlugin: () => require("./javascript/JavascriptModulesPlugin")
});
exportPlugins((module.exports.optimize = {}), {
AggressiveMergingPlugin: () => require("./optimize/AggressiveMergingPlugin"),
AggressiveSplittingPlugin: util.deprecate(
() => require("./optimize/AggressiveSplittingPlugin"),
"AggressiveSplittingPlugin is deprecated in favor of SplitChunksPlugin",
"DEP_WEBPACK_AGGRESSIVE_SPLITTING_PLUGIN"
),
LimitChunkCountPlugin: () => require("./optimize/LimitChunkCountPlugin"),
MinChunkSizePlugin: () => require("./optimize/MinChunkSizePlugin"),
ModuleConcatenationPlugin: () =>
require("./optimize/ModuleConcatenationPlugin"),
RuntimeChunkPlugin: () => require("./optimize/RuntimeChunkPlugin"),
SideEffectsFlagPlugin: () => require("./optimize/SideEffectsFlagPlugin"),
SplitChunksPlugin: () => require("./optimize/SplitChunksPlugin")
});
exportPlugins((module.exports.web = {}), {
FetchCompileWasmPlugin: () => require("./web/FetchCompileWasmPlugin"),
JsonpTemplatePlugin: () => require("./web/JsonpTemplatePlugin")
});
exportPlugins((module.exports.webworker = {}), {
WebWorkerTemplatePlugin: () => require("./webworker/WebWorkerTemplatePlugin")
});
exportPlugins((module.exports.node = {}), {
NodeEnvironmentPlugin: () => require("./node/NodeEnvironmentPlugin"),
NodeTemplatePlugin: () => require("./node/NodeTemplatePlugin"),
ReadFileCompileWasmPlugin: () => require("./node/ReadFileCompileWasmPlugin")
});
exportPlugins((module.exports.wasm = {}), {
AsyncWebAssemblyModulesPlugin: () =>
require("./wasm-async/AsyncWebAssemblyModulesPlugin")
});
exportPlugins((module.exports.library = {}), {
AbstractLibraryPlugin: () => require("./library/AbstractLibraryPlugin"),
EnableLibraryPlugin: () => require("./library/EnableLibraryPlugin")
});
exportPlugins((module.exports.debug = {}), {
ProfilingPlugin: () => require("./debug/ProfilingPlugin")
});
exportPlugins((module.exports.util = {}), {
createHash: () => require("./util/createHash"),
comparators: () => require("./util/comparators"),
serialization: () => require("./util/serialization")
});
finishExports(module.exports);

View File

@ -7,11 +7,13 @@
const path = require("path");
/** @typedef {import("fs").Stats} NodeFsStats */
/** @typedef {function(NodeJS.ErrnoException=): void} Callback */
/** @typedef {function(NodeJS.ErrnoException=, Buffer=): void} BufferCallback */
/** @typedef {function(NodeJS.ErrnoException=, string[]=): void} StringArrayCallback */
/** @typedef {function(NodeJS.ErrnoException=, string=): void} StringCallback */
/** @typedef {function(NodeJS.ErrnoException=, import("fs").Stats=): void} StatsCallback */
/** @typedef {function(NodeJS.ErrnoException=, NodeFsStats=): void} StatsCallback */
/**
* @typedef {Object} OutputFileSystem

View File

@ -31,8 +31,8 @@
"devDependencies": {
"@babel/core": "^7.7.2",
"@types/estree": "0.0.42",
"@types/jest": "^25.1.5",
"@types/node": "^12.6.9",
"@yarnpkg/lockfile": "^1.1.0",
"babel-loader": "^8.0.6",
"benchmark": "^2.1.1",
"bundle-loader": "~0.5.0",
@ -50,14 +50,12 @@
"eslint-plugin-prettier": "^3.1.0",
"file-loader": "^4.1.0",
"fork-ts-checker-webpack-plugin": "^1.5.0",
"glob": "^7.1.3",
"husky": "^4.2.3",
"istanbul": "^0.4.5",
"jest": "^25.1.0",
"jest-diff": "^25.1.0",
"jest-junit": "^10.0.0",
"json-loader": "^0.5.7",
"json-schema-to-typescript": "^8.1.0",
"json5": "^2.1.1",
"less": "^3.9.0",
"less-loader": "^5.0.0",
@ -81,6 +79,7 @@
"strip-ansi": "^6.0.0",
"style-loader": "^1.0.0",
"toml": "^3.0.0",
"tooling": "webpack/tooling",
"ts-loader": "^6.0.4",
"typescript": "^3.6.4",
"url-loader": "^2.1.0",
@ -104,13 +103,15 @@
"homepage": "https://github.com/webpack/webpack",
"main": "lib/index.js",
"bin": "./bin/webpack.js",
"types": "types.d.ts",
"files": [
"lib/",
"bin/",
"declarations/",
"hot/",
"schemas/",
"SECURITY.md"
"SECURITY.md",
"types.d.ts"
],
"scripts": {
"setup": "node ./setup/setup.js",
@ -130,25 +131,25 @@
"type-report": "rimraf coverage && yarn cover:types && yarn cover:report && open-cli coverage/lcov-report/index.html",
"pretest": "yarn lint",
"prelint": "yarn setup",
"lint": "yarn code-lint && yarn jest-lint && yarn type-lint && yarn special-lint && yarn pretty-lint && yarn spellcheck",
"lint": "yarn code-lint && yarn special-lint && yarn type-lint && yarn pretty-lint && yarn spellcheck",
"code-lint": "eslint . --ext '.js' --cache",
"type-lint": "tsc --pretty",
"type-lint": "tsc",
"test:types": "tsc -p tsconfig.test.json",
"spellcheck": "cspell \"{.github,benchmark,bin,examples,hot,lib,schemas,setup,tooling}/**/*.{md,yml,yaml,js,json}\" \"*.md\"",
"special-lint": "node tooling/inherit-types && node tooling/format-schemas && node tooling/format-file-header && node tooling/compile-to-definitions",
"special-lint-fix": "node tooling/inherit-types --write --override && node tooling/format-schemas --write && node tooling/format-file-header --write && node tooling/compile-to-definitions --write",
"special-lint": "node node_modules/tooling/lockfile-lint && node node_modules/tooling/schemas-lint && node node_modules/tooling/inherit-types && node node_modules/tooling/format-schemas && node node_modules/tooling/format-file-header && node node_modules/tooling/compile-to-definitions && node node_modules/tooling/generate-types",
"special-lint-fix": "node node_modules/tooling/inherit-types --write && node node_modules/tooling/format-schemas --write && node node_modules/tooling/format-file-header --write && node node_modules/tooling/compile-to-definitions --write && node node_modules/tooling/generate-types --write",
"fix": "yarn code-lint --fix && yarn special-lint-fix && yarn pretty-lint-fix",
"pretty-lint-base": "prettier \"*.{ts,json,yml,yaml,md}\" \"{setup,lib,bin,hot,benchmark,tooling,schemas}/**/*.json\" \"examples/*.md\"",
"pretty-lint-base-all": "yarn pretty-lint-base \"*.js\" \"{setup,lib,bin,hot,benchmark,tooling,schemas}/**/*.js\" \"test/*.js\" \"test/helpers/*.js\" \"test/{configCases,watchCases,statsCases,hotCases,benchmarkCases}/**/webpack.config.js\" \"examples/**/webpack.config.js\"",
"pretty-lint-fix": "yarn pretty-lint-base-all --loglevel warn --write",
"pretty-lint": "yarn pretty-lint-base --check",
"jest-lint": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.lint.js\" --no-verbose",
"benchmark": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.benchmark.js\" --runInBand",
"cover": "yarn cover:all && yarn cover:report",
"cover:all": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --coverage",
"cover:basic": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/te{st/TestCasesNormal,st/StatsTestCases,st/ConfigTestCases}.test.js\" --coverage",
"cover:integration": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.test.js\" --coverage",
"cover:unit": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.unittest.js\" --coverage",
"cover:types": "node tooling/type-coverage.js",
"cover:types": "node node_modules/tooling/type-coverage",
"cover:report": "istanbul report"
},
"husky": {

View File

@ -42,7 +42,7 @@
"description": "Report the first error as a hard error instead of tolerating it.",
"type": "boolean"
},
"Cache": {
"CacheOptions": {
"description": "Cache generated modules and chunks to improve performance for multiple incremental builds.",
"anyOf": [
{
@ -50,11 +50,11 @@
"enum": [true]
},
{
"$ref": "#/definitions/CacheNormalized"
"$ref": "#/definitions/CacheOptionsNormalized"
}
]
},
"CacheNormalized": {
"CacheOptionsNormalized": {
"description": "Cache generated modules and chunks to improve performance for multiple incremental builds.",
"anyOf": [
{
@ -878,7 +878,7 @@
"description": "Enable production optimizations or development hints.",
"enum": ["development", "production", "none"]
},
"Module": {
"ModuleOptions": {
"description": "Options affecting the normal modules (`NormalModuleFactory`).",
"type": "object",
"additionalProperties": false,
@ -2626,28 +2626,6 @@
"description": "Prefixes every line of the source in the bundle with this string.",
"type": "string"
},
"Stats": {
"description": "Stats options object or preset name.",
"anyOf": [
{
"enum": [
"none",
"errors-only",
"minimal",
"normal",
"detailed",
"verbose",
"errors-warnings"
]
},
{
"type": "boolean"
},
{
"$ref": "#/definitions/StatsOptions"
}
]
},
"StatsOptions": {
"description": "Stats options object.",
"type": "object",
@ -2944,6 +2922,28 @@
}
}
},
"StatsValue": {
"description": "Stats options object or preset name.",
"anyOf": [
{
"enum": [
"none",
"errors-only",
"minimal",
"normal",
"detailed",
"verbose",
"errors-warnings"
]
},
{
"type": "boolean"
},
{
"$ref": "#/definitions/StatsOptions"
}
]
},
"StrictModuleExceptionHandling": {
"description": "Handles exceptions in module loading correctly at a performance cost.",
"type": "boolean"
@ -3045,7 +3045,7 @@
"$ref": "#/definitions/Bail"
},
"cache": {
"$ref": "#/definitions/CacheNormalized"
"$ref": "#/definitions/CacheOptionsNormalized"
},
"context": {
"$ref": "#/definitions/Context"
@ -3081,7 +3081,7 @@
"$ref": "#/definitions/Mode"
},
"module": {
"$ref": "#/definitions/Module"
"$ref": "#/definitions/ModuleOptions"
},
"name": {
"$ref": "#/definitions/Name"
@ -3120,7 +3120,7 @@
"$ref": "#/definitions/ResolveLoader"
},
"stats": {
"$ref": "#/definitions/Stats"
"$ref": "#/definitions/StatsValue"
},
"target": {
"$ref": "#/definitions/Target"
@ -3179,7 +3179,7 @@
"$ref": "#/definitions/Bail"
},
"cache": {
"$ref": "#/definitions/Cache"
"$ref": "#/definitions/CacheOptions"
},
"context": {
"$ref": "#/definitions/Context"
@ -3215,7 +3215,7 @@
"$ref": "#/definitions/Mode"
},
"module": {
"$ref": "#/definitions/Module"
"$ref": "#/definitions/ModuleOptions"
},
"name": {
"$ref": "#/definitions/Name"
@ -3257,7 +3257,7 @@
"$ref": "#/definitions/ResolveLoader"
},
"stats": {
"$ref": "#/definitions/Stats"
"$ref": "#/definitions/StatsValue"
},
"target": {
"$ref": "#/definitions/Target"

View File

@ -1,27 +0,0 @@
const fs = require("graceful-fs");
const path = require("path");
const lockfile = require("@yarnpkg/lockfile");
const file = fs.readFileSync(path.resolve(__dirname, "../yarn.lock"), "utf-8");
const result = lockfile.parse(file);
describe("Dependencies", () => {
it("should parse fine", () => {
expect(result.type).toBe("success");
});
if (result.type === "success") {
const content = result.object;
for (const dep of Object.keys(content)) {
describe(dep, () => {
const info = content[dep];
it("should resolve to an npm package", () => {
expect(info.resolved).toMatch(/^https:\/\/registry\.yarnpkg\.com\//);
});
it("should have an integrity hash", () => {
expect(info.integrity).toMatch(/^(sha1|sha512)-/);
});
});
}
}
});

View File

@ -1,209 +0,0 @@
"use strict";
const fs = require("graceful-fs");
const path = require("path");
const glob = require("glob");
const rootDir = path.resolve(__dirname, "..");
describe("Schemas", () => {
const schemas = glob.sync("schemas/**/*.json", {
cwd: rootDir
});
schemas.forEach(filename => {
describe(filename, () => {
let content;
let fileContent;
let errorWhileParsing;
try {
fileContent = fs.readFileSync(path.resolve(rootDir, filename), "utf-8");
content = JSON.parse(fileContent);
} catch (e) {
errorWhileParsing = e;
}
it("should be parse-able", () => {
if (errorWhileParsing) throw errorWhileParsing;
});
if (content) {
const arrayProperties = ["oneOf", "anyOf", "allOf"];
const allowedProperties = [
"definitions",
"$ref",
"$id",
"title",
"cli",
"items",
"properties",
"additionalProperties",
"type",
"oneOf",
"anyOf",
"absolutePath",
"description",
"enum",
"minLength",
"pattern",
"minimum",
"maximum",
"required",
"uniqueItems",
"minItems",
"minProperties",
"instanceof",
"tsType",
"not"
];
const isReference = schema => {
return (
"$ref" in schema ||
("oneOf" in schema &&
schema.oneOf.length === 1 &&
"$ref" in schema.oneOf[0])
);
};
const validateProperty = property => {
if (isReference(property)) return;
it("should have description set", () => {
expect(typeof property.description).toBe("string");
expect(property.description.length).toBeGreaterThan(1);
expect(property.description).toMatch(/^[A-Z`]/);
expect(property.description).toEndWith(".");
expect(property.description).not.toEndWith("..");
});
};
const walker = item => {
it("should only use allowed schema properties", () => {
const otherProperties = Object.keys(item).filter(
p => allowedProperties.indexOf(p) < 0
);
if (otherProperties.length > 0) {
throw new Error(
`The properties ${otherProperties.join(
", "
)} are not allowed to use`
);
// When allowing more properties make sure to add nice error messages for them in WebpackOptionsValidationError
}
});
if ("$ref" in item) {
it("should not have other properties next to $ref", () => {
const otherProperties = Object.keys(item).filter(
p => p !== "$ref"
);
if (otherProperties.length > 0) {
throw new Error(
`When using $ref other properties are not possible (${otherProperties.join(
", "
)})`
);
}
});
}
if ("type" in item) {
it("should have a single type", () => {
expect(item.type).toBeTypeOf("string");
});
}
if ("instanceof" in item) {
it("should have tsType specified when using instanceof", () => {
if (!("tsType" in item)) {
throw new Error("When using instanceof, tsType is required");
}
});
}
if ("absolutePath" in item) {
it("should have type: 'string' specified when using absolutePath", () => {
if (item.type !== "string") {
throw new Error(
"When using absolutePath, type must be 'string'"
);
}
});
}
if ("properties" in item || "additionalProperties" in item) {
it("should have type: 'object' specified when using properties or additionalProperties", () => {
if (item.type !== "object") {
throw new Error(
"When using properties or additionalProperties, type must be 'object'"
);
}
});
}
arrayProperties.forEach(prop => {
if (prop in item) {
describe(prop, () => {
it("should not double nest array properties", () => {
for (const nestedProp of arrayProperties) {
for (const value of item[prop])
expect(value).not.toHaveProperty(nestedProp);
}
});
if (prop === "oneOf") {
it("should have only one item which is a $ref", () => {
expect(item[prop].length).toBe(1);
expect(Object.keys(item[prop][0])).toEqual(["$ref"]);
});
} else {
it("should have multiple items", () => {
expect(item[prop].length).toBeGreaterThan(1);
});
}
item[prop].forEach(walker);
});
}
});
if ("items" in item) {
describe("items", () => {
validateProperty(item.items);
walker(item.items);
});
}
if ("definitions" in item) {
Object.keys(item.definitions).forEach(name => {
describe(`#${name}`, () => {
const def = item.definitions[name];
it("should have description set", () => {
expect(typeof def.description).toBe("string");
expect(def.description.length).toBeGreaterThan(1);
});
walker(def);
});
});
}
if ("properties" in item) {
it("should have additionalProperties set to some value when describing properties", () => {
expect(item.additionalProperties).toBeDefined();
});
Object.keys(item.properties).forEach(name => {
describe(`> '${name}'`, () => {
const property = item.properties[name];
validateProperty(property);
walker(property);
});
});
}
if (typeof item.additionalProperties === "object") {
describe("properties", () => {
validateProperty(item.additionalProperties);
walker(item.additionalProperties);
});
}
};
walker(content);
}
});
});
});

View File

@ -1,5 +1,5 @@
const path = require("path");
const NormalModule = require("../../../../lib/NormalModule");
const NormalModule = require("../../../../").NormalModule;
module.exports = {
mode: "development",

View File

@ -1,5 +1,5 @@
/** @typedef {import("../../../../lib/Compilation")} Compilation */
/** @typedef {import("../../../../lib/Module")} Module */
/** @typedef {import("../../../../").Compilation} Compilation */
/** @typedef {import("../../../../").Module} Module */
module.exports = {
entry: {

View File

@ -5,7 +5,7 @@ const RuntimeGlobals = require("../../../../").RuntimeGlobals;
const Parser = require("../../../../").Parser;
const webpack = require("../../../../");
/** @typedef {import("../../../../lib/Compiler")} Compiler */
/** @typedef {import("../../../../").Compiler} Compiler */
class LocalizationParser extends Parser {
parse(source, { module }) {

View File

@ -1,4 +1,4 @@
/** @typedef {import("../../../../lib/Compilation")} Compilation */
/** @typedef {import("../../../../").Compilation} Compilation */
module.exports = {
optimization: {

View File

@ -1,4 +1,4 @@
/** @typedef {import("../../../../lib/Compilation")} Compilation */
/** @typedef {import("../../../../").Compilation} Compilation */
module.exports = {
optimization: {

View File

@ -1,3 +1,8 @@
/** @typedef {import("../../../../").Compiler} Compiler */
/** @typedef {import("../../../../").Compilation} Compilation */
/** @typedef {import("../../../../").Configuration} Configuration */
/** @type {Configuration} */
module.exports = {
entry() {
return Promise.resolve({
@ -15,6 +20,9 @@ module.exports = {
filename: "[name].js"
},
plugins: [
/**
* @this {Compiler} compiler
*/
function () {
/**
* @param {Compilation} compilation compilation

View File

@ -1,3 +1,6 @@
/** @typedef {import("../../../../").Compiler} Compiler */
/** @typedef {import("../../../../").Compilation} Compilation */
module.exports = {
entry: {
app: { import: "./app.js", dependOn: "react-vendors" },
@ -8,6 +11,9 @@ module.exports = {
filename: "[name].js"
},
plugins: [
/**
* @this {Compiler} compiler
*/
function () {
/**
* @param {Compilation} compilation compilation

View File

@ -1,3 +1,6 @@
/**
* @this {import("../../../../").Compiler} the compiler
*/
var testPlugin = function () {
this.hooks.compilation.tap("TestPlugin", compilation => {
compilation.hooks.finishModules.tapAsync("TestPlugin", function (

View File

@ -5,10 +5,17 @@ module.exports = {
minimize: true,
minimizer: [
{
/**
* @param {Compiler} compiler the compiler
*/
apply(compiler) {
expect(compiler).toBeInstanceOf(Compiler);
}
},
/**
* @this {Compiler} the compiler
* @param {Compiler} compiler the compiler
*/
function (compiler) {
expect(compiler).toBe(this);
expect(compiler).toBeInstanceOf(Compiler);

View File

@ -1,3 +1,4 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
entry: {
vendor: ["external0", "./a"],

View File

@ -1,7 +1,7 @@
const { CachedSource } = require("webpack-sources");
const { AsyncWebAssemblyModulesPlugin } = require("../../../../").wasm;
/** @typedef {import("../../../../lib/Compilation")} Compilation */
/** @typedef {import("../../../../").Compiler} Compiler */
module.exports = {
module: {
@ -18,22 +18,18 @@ module.exports = {
importAwait: true
},
plugins: [
/**
* @this {Compiler} compiler
*/
function () {
this.hooks.compilation.tap(
"Test",
/**
* @param {Compilation} compilation Compilation
* @returns {void}
*/
compilation => {
AsyncWebAssemblyModulesPlugin.getCompilationHooks(
compilation
).renderModuleContent.tap("Test", source => {
// this is important to make each returned value a new instance
return new CachedSource(source);
});
}
);
this.hooks.compilation.tap("Test", compilation => {
AsyncWebAssemblyModulesPlugin.getCompilationHooks(
compilation
).renderModuleContent.tap("Test", source => {
// this is important to make each returned value a new instance
return new CachedSource(source);
});
});
}
]
};

View File

@ -1,142 +0,0 @@
const fs = require("fs");
const path = require("path");
const prettierrc = require("../.prettierrc.js"); // eslint-disable-line
const { compile } = require("json-schema-to-typescript");
const schemasDir = path.resolve(__dirname, "../schemas");
const style = {
printWidth: prettierrc.printWidth,
useTabs: prettierrc.useTabs,
tabWidth: prettierrc.tabWidth
};
// When --write is set, files will be written in place
// Otherwise it only prints outdated files
const doWrite = process.argv.includes("--write");
const makeSchemas = () => {
// include the top level folder "./schemas" by default
const dirs = new Set([schemasDir]);
// search for all nestedDirs inside of this folder
for (let dirWithSchemas of dirs) {
for (let item of fs.readdirSync(dirWithSchemas)) {
const absPath = path.resolve(dirWithSchemas, item);
if (fs.statSync(absPath).isDirectory()) {
dirs.add(absPath);
} else if (item.endsWith(".json")) {
makeDefinitionsForSchema(absPath);
}
}
}
};
const makeDefinitionsForSchema = absSchemaPath => {
const relPath = path
.relative(schemasDir, absSchemaPath)
.replace(/\.json$/i, "");
const basename = path.basename(relPath);
const filename = path.resolve(__dirname, `../declarations/${relPath}.d.ts`);
const schema = JSON.parse(fs.readFileSync(absSchemaPath, "utf-8"));
preprocessSchema(schema);
compile(schema, basename, {
bannerComment:
"/**\n * This file was automatically generated.\n * DO NOT MODIFY BY HAND.\n * Run `yarn special-lint-fix` to update\n */",
unreachableDefinitions: true,
style
}).then(
ts => {
ts = ts.replace(
/\s+\*\s+\* This interface was referenced by `.+`'s JSON-Schema\s+\* via the `definition` ".+"\./g,
""
);
let normalizedContent = "";
try {
const content = fs.readFileSync(filename, "utf-8");
normalizedContent = content.replace(/\r\n?/g, "\n");
} catch (e) {
// ignore
}
if (normalizedContent.trim() !== ts.trim()) {
if (doWrite) {
fs.mkdirSync(path.dirname(filename), { recursive: true });
fs.writeFileSync(filename, ts, "utf-8");
console.error(
`declarations/${relPath.replace(/\\/g, "/")}.d.ts updated`
);
} else {
console.error(
`declarations/${relPath.replace(
/\\/g,
"/"
)}.d.ts need to be updated`
);
process.exitCode = 1;
}
}
},
err => {
console.error(err);
process.exitCode = 1;
}
);
};
const resolvePath = (root, ref) => {
const parts = ref.split("/");
if (parts[0] !== "#") throw new Error("Unexpected ref");
let current = root;
for (const p of parts.slice(1)) {
current = current[p];
}
return current;
};
const preprocessSchema = (schema, root = schema) => {
if ("definitions" in schema) {
for (const key of Object.keys(schema.definitions)) {
preprocessSchema(schema.definitions[key], root);
}
}
if ("properties" in schema) {
for (const key of Object.keys(schema.properties)) {
const property = schema.properties[key];
if ("$ref" in property) {
const result = resolvePath(root, property.$ref);
schema.properties[key] = {
description: result.description,
anyOf: [property]
};
} else if (
"oneOf" in property &&
property.oneOf.length === 1 &&
"$ref" in property.oneOf[0]
) {
const result = resolvePath(root, property.oneOf[0].$ref);
schema.properties[key] = {
description: property.description || result.description,
anyOf: property.oneOf
};
preprocessSchema(schema.properties[key], root);
} else {
preprocessSchema(property, root);
}
}
}
if ("items" in schema) {
preprocessSchema(schema.items, root);
}
if (typeof schema.additionalProperties === "object") {
preprocessSchema(schema.additionalProperties, root);
}
const arrayProperties = ["oneOf", "anyOf", "allOf"];
for (const prop of arrayProperties) {
if (Array.isArray(schema[prop])) {
for (const item of schema[prop]) {
preprocessSchema(item, root);
}
}
}
};
makeSchemas();

View File

@ -1,212 +0,0 @@
const path = require("path");
const fs = require("fs");
// When --write is set, files will be written in place
// Otherwise it only prints outdated files
const doWrite = process.argv.includes("--write");
const allFiles = new Set();
const findFiles = p => {
const s = fs.statSync(p);
if (s.isDirectory()) {
for (const name of fs.readdirSync(p)) {
if (name.startsWith(".")) continue;
findFiles(path.join(p, name));
}
} else if (s.isFile()) {
allFiles.add(p);
}
};
findFiles(path.resolve(__dirname, "../lib"));
let canUpdateWithWrite = false;
const sortImport = (a, b) => {
if (!a.key.startsWith(".") && b.key.startsWith(".")) return -1;
if (a.key.startsWith(".") && !b.key.startsWith(".")) return 1;
if (a.key < b.key) return -1;
if (a.key > b.key) return 1;
return 0;
};
const execToArray = (content, regexp) => {
const items = [];
let match = regexp.exec(content);
while (match) {
items.push({
content: match[0],
key: match[1] + match[2]
});
match = regexp.exec(content);
}
return items;
};
const schema = [
{
title: "license comment",
regexp: /\/\*\n\s*MIT License http:\/\/www\.opensource\.org\/licenses\/mit-license\.php\n\s*(?:(Authors? .+)\n)?\s*\*\/\n/g,
updateMessage: "update the license comment",
update(content, author) {
return (
[
"/*",
"\tMIT License http://www.opensource.org/licenses/mit-license.php",
author && `\t${author}`,
"*/"
]
.filter(Boolean)
.join("\n") + "\n"
);
}
},
{
title: "new line after license comment",
regexp: /\n?/g,
updateMessage: "insert a new line after the license comment",
update() {
return "\n";
}
},
{
title: "strict mode",
regexp: /"use strict";\n/g
},
{
title: "new line after strict mode",
regexp: /\n?/g,
updateMessage: 'insert a new line after "use strict"',
update() {
return "\n";
}
},
{
title: "imports",
regexp: /(const (\{\s+\w+(?::\s+\w+)?(,\s+\w+(?::\s+\w+)?)*\s+\}|\w+) = (\/\*\* @type \{TODO\} \*\/\s\()?require\("[^"]+"\)\)?(\.\w+)*;\n)+\n/g,
updateMessage: "sort imports alphabetically",
update(content) {
const items = execToArray(
content,
/const (?:\{\s+\w+(?::\s+\w+)?(?:,\s+\w+(?::\s+\w+)?)*\s+\}|\w+) = (?:\/\*\* @type \{TODO\} \*\/\s\()?require\("([^"]+)"\)\)?((?:\.\w+)*);\n/g
);
items.sort(sortImport);
return items.map(item => item.content).join("") + "\n";
},
optional: true,
repeat: true
},
{
title: "type imports",
regexp: /(\/\*\* (?:@template \w+ )*@typedef \{import\("[^"]+"\)(\.\w+)*(?:<(?:(?:\w\.)*\w+, )*(?:\w\.)*\w+>)?\} \w+(?:<(?:(?:\w\.)*\w+, )*(?:\w\.)*\w+>)? \*\/\n)+\n/g,
updateMessage: "sort type imports alphabetically",
update(content) {
const items = execToArray(
content,
/\/\*\* (?:@template \w+ )*@typedef \{import\("([^"]+)"\)((?:\.\w+)*(?:<(?:(?:\w\.)*\w+, )*(?:\w\.)*\w+>)?)\} \w+(?:<(?:(?:\w\.)*\w+, )*(?:\w\.)*\w+>)? \*\/\n/g
);
items.sort(sortImport);
return items.map(item => item.content).join("") + "\n";
},
optional: true,
repeat: true
}
];
const allSerializables = new Set();
for (const filePath of allFiles) {
let content = fs.readFileSync(filePath, "utf-8");
const nl = /(\r?\n)/.exec(content);
content = content.replace(/\r?\n/g, "\n");
let newContent = content;
let state = 0;
let pos = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
const current = schema[state];
if (!current) break;
current.regexp.lastIndex = pos;
const match = current.regexp.exec(newContent);
if (!match) {
if (current.optional) {
state++;
continue;
}
console.log(`${filePath}: Missing ${current.title} at ${pos}`);
process.exitCode = 1;
break;
}
if (match.index !== pos) {
console.log(
`${filePath}: Unexpected code at ${pos}-${match.index}, expected ${current.title}`
);
process.exitCode = 1;
pos = match.index;
}
if (!current.repeat) {
state++;
}
if (current.update) {
const update = current.update(...match);
if (update !== match[0]) {
newContent =
newContent.substr(0, pos) +
update +
newContent.slice(pos + match[0].length);
pos += update.length;
if (!doWrite) {
const updateMessage =
current.updateMessage || `${current.title} need to be updated`;
console.log(`${filePath}: ${updateMessage}`);
}
continue;
}
}
pos += match[0].length;
}
if (newContent !== content) {
if (doWrite) {
if (nl) {
newContent = newContent.replace(/\n/g, nl[0]);
}
fs.writeFileSync(filePath, newContent, "utf-8");
console.log(filePath);
} else {
canUpdateWithWrite = true;
process.exitCode = 1;
}
}
const matches = content.match(
/makeSerializable\(\s*[^,]+,\s*"webpack\/lib\/[^"]+"\s*(?:,[^)]+)?\)/g
);
if (matches) {
for (const match of matches) {
const str = /makeSerializable\(\s*[^,]+,\s*"webpack\/lib\/([^"]+)"/.exec(
match
)[1];
allSerializables.add(str);
}
}
}
// Check if lib/util/internalSerializables.js includes all serializables in webpack
{
const content = fs.readFileSync(
path.resolve(__dirname, "../lib/util/internalSerializables.js")
);
for (const serializable of allSerializables) {
if (!content.includes(`"../${serializable}"`)) {
console.log(
`lib/util/internalSerializables.js: must include static require to ../${serializable}`
);
process.exitCode = 1;
}
}
}
if (canUpdateWithWrite) {
console.log("Run 'yarn fix' to try to fix the problem automatically");
}

View File

@ -1,174 +0,0 @@
const fs = require("fs");
const path = require("path");
const prettier = require("prettier");
const schemasDir = path.resolve(__dirname, "../schemas");
// When --write is set, files will be written in place
// Otherwise it only prints outdated files
const doWrite = process.argv.includes("--write");
const sortObjectAlphabetically = obj => {
const keys = Object.keys(obj).sort();
const newObj = {};
for (const key of keys) {
newObj[key] = obj[key];
}
return newObj;
};
const typeOrder = [
"array",
"enum",
"RegExp",
"number",
"boolean",
"string",
"object",
"Function",
undefined
];
const sortArrayByType = array => {
array.sort((a, b) => {
const aType = a.type || a.instanceof || (a.enum && "enum");
const bType = b.type || b.instanceof || (b.enum && "enum");
const aPos = typeOrder.indexOf(aType);
const bPos = typeOrder.indexOf(bType);
if (aPos === bPos) {
return array.indexOf(a) - array.indexOf(b);
}
return aPos - bPos;
});
};
const sortObjectWithList = (obj, props) => {
const keys = Object.keys(obj)
.filter(p => !props.includes(p))
.sort();
const newObj = {};
for (const key of props) {
if (key in obj) {
newObj[key] = obj[key];
}
}
for (const key of keys) {
newObj[key] = obj[key];
}
return newObj;
};
const PROPERTIES = [
"$ref",
"definitions",
"$id",
"id",
"title",
"description",
"type",
"cli",
"items",
"minItems",
"uniqueItems",
"additionalProperties",
"properties",
"required",
"minProperties",
"oneOf",
"anyOf",
"allOf",
"enum",
"absolutePath",
"minLength",
"minimum",
"instanceof",
"tsType"
];
const NESTED_WITH_NAME = ["definitions", "properties"];
const NESTED_DIRECT = ["items", "additionalProperties"];
const NESTED_ARRAY = ["oneOf", "anyOf", "allOf"];
const processJson = json => {
json = sortObjectWithList(json, PROPERTIES);
for (const name of NESTED_WITH_NAME) {
if (name in json && json[name] && typeof json[name] === "object") {
json[name] = sortObjectAlphabetically(json[name]);
for (const key in json[name]) {
json[name][key] = processJson(json[name][key]);
}
}
}
for (const name of NESTED_DIRECT) {
if (name in json && json[name] && typeof json[name] === "object") {
json[name] = processJson(json[name]);
}
}
for (const name of NESTED_ARRAY) {
if (name in json && Array.isArray(json[name])) {
for (let i = 0; i < json[name].length; i++) {
json[name][i] = processJson(json[name][i]);
}
sortArrayByType(json[name]);
}
}
return json;
};
const formatSchema = schemaPath => {
const json = require(schemaPath);
const processedJson = processJson(json);
const rawString = JSON.stringify(processedJson, null, 2);
prettier.resolveConfig(schemaPath).then(config => {
config.filepath = schemaPath;
config.parser = "json";
const prettyString = prettier.format(rawString, config);
let normalizedContent = "";
try {
const content = fs.readFileSync(schemaPath, "utf-8");
normalizedContent = content.replace(/\r\n?/g, "\n");
} catch (e) {
// ignore
}
if (normalizedContent.trim() !== prettyString.trim()) {
const basename = path.relative(schemasDir, schemaPath);
if (doWrite) {
fs.writeFileSync(schemaPath, prettyString, "utf-8");
console.error(`schemas/${basename.replace(/\\/g, "/")} updated`);
} else {
console.error(
`schemas/${basename.replace(/\\/g, "/")} need to be updated`
);
process.exitCode = 1;
}
}
});
};
// include the top level folder "./schemas" by default
const dirs = new Set([schemasDir]);
// search for all nestedDirs inside of this folder
for (let dirWithSchemas of dirs) {
for (let item of fs.readdirSync(dirWithSchemas)) {
const absPath = path.resolve(dirWithSchemas, item);
if (fs.statSync(absPath).isDirectory()) {
dirs.add(absPath);
} else if (item.endsWith(".json")) {
formatSchema(absPath);
}
}
}

View File

@ -1,176 +0,0 @@
const path = require("path");
const fs = require("fs");
const ts = require("typescript");
const program = require("./typescript-program");
// When --override is set, base jsdoc will override sub class jsdoc
// Otherwise on a conflict it will create a merge conflict in the file
const override = process.argv.includes("--override");
// When --write is set, files will be written in place
// Otherwise it only prints outdated files
const doWrite = process.argv.includes("--write");
const typeChecker = program.getTypeChecker();
/**
* @param {ts.ClassDeclaration | ts.ClassExpression} node the class declaration
* @returns {Set<ts.ClassDeclaration | ts.ClassExpression>} the base class declarations
*/
const getBaseClasses = node => {
try {
/** @type {Set<ts.ClassDeclaration | ts.ClassExpression>} */
const decls = new Set();
if (node.heritageClauses) {
for (const clause of node.heritageClauses) {
for (const clauseType of clause.types) {
const type = typeChecker.getTypeAtLocation(clauseType);
if (type.symbol) {
const decl = type.symbol.valueDeclaration;
if (ts.isClassDeclaration(decl) || ts.isClassExpression(decl))
decls.add(decl);
}
}
}
}
return decls;
} catch (e) {
e.message += ` while getting the base class of ${node.name}`;
throw e;
}
};
/**
* @param {ts.ClassDeclaration | ts.ClassExpression} classNode the class declaration
* @param {string} memberName name of the member
* @returns {ts.MethodDeclaration | null} base class member declaration when found
*/
const findDeclarationInBaseClass = (classNode, memberName) => {
for (const baseClass of getBaseClasses(classNode)) {
for (const node of baseClass.members) {
if (ts.isMethodDeclaration(node)) {
if (node.name.getText() === memberName) {
return node;
}
}
}
const result = findDeclarationInBaseClass(baseClass, memberName);
if (result) return result;
}
return null;
};
const libPath = path.resolve(__dirname, "../lib");
for (const sourceFile of program.getSourceFiles()) {
let file = sourceFile.fileName;
if (
file.toLowerCase().startsWith(libPath.replace(/\\/g, "/").toLowerCase())
) {
const updates = [];
/**
* @param {ts.Node} node the traversed node
* @returns {void}
*/
const nodeHandler = node => {
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
for (const member of node.members) {
if (
ts.isMethodDeclaration(member) &&
!(ts.getCombinedModifierFlags(member) & ts.ModifierFlags.Static)
) {
const baseDecl = findDeclarationInBaseClass(
node,
member.name.getText()
);
if (baseDecl) {
const memberAsAny = /** @type {TODO} */ (member);
const baseDeclAsAny = /** @type {TODO} */ (baseDecl);
const currentJsDoc = memberAsAny.jsDoc && memberAsAny.jsDoc[0];
const baseJsDoc = baseDeclAsAny.jsDoc && baseDeclAsAny.jsDoc[0];
const currentJsDocText =
currentJsDoc && currentJsDoc.getText().replace(/\r\n?/g, "\n");
let baseJsDocText =
baseJsDoc && baseJsDoc.getText().replace(/\r\n?/g, "\n");
if (baseJsDocText) {
baseJsDocText = baseJsDocText.replace(
/\t \* @abstract\r?\n/g,
""
);
if (!currentJsDocText) {
// add js doc
updates.push({
member: member.name.getText(),
start: member.getStart(),
end: member.getStart(),
content: baseJsDocText + "\n\t",
oldContent: ""
});
} else if (
baseJsDocText &&
currentJsDocText !== baseJsDocText
) {
// update js doc
if (override || !doWrite) {
updates.push({
member: member.name.getText(),
start: currentJsDoc.getStart(),
end: currentJsDoc.getEnd(),
content: baseJsDocText,
oldContent: currentJsDocText
});
} else {
updates.push({
member: member.name.getText(),
start: currentJsDoc.getStart() - 1,
end: currentJsDoc.getEnd(),
content: `<<<<<<< original comment\n\t${currentJsDocText}\n=======\n\t${baseJsDocText}\n>>>>>>> comment from base class`
});
}
}
}
}
}
}
} else {
node.forEachChild(nodeHandler);
}
};
try {
sourceFile.forEachChild(nodeHandler);
} catch (e) {
e.message += ` while processing ${file}`;
throw e;
}
if (updates.length > 0) {
if (doWrite) {
let fileContent = fs.readFileSync(file, "utf-8");
updates.sort((a, b) => {
return b.start - a.start;
});
for (const update of updates) {
fileContent =
fileContent.substr(0, update.start) +
update.content +
fileContent.substr(update.end);
}
console.log(`${file} ${updates.length} JSDoc comments added/updated`);
fs.writeFileSync(file, fileContent, "utf-8");
} else {
console.log(file);
for (const update of updates) {
console.log(
`* ${update.member} should have this JSDoc:\n\t${update.content}`
);
if (update.oldContent) {
console.log(`instead of\n\t${update.oldContent}`);
}
}
console.log();
process.exitCode = 1;
}
}
}
}

View File

@ -1,132 +0,0 @@
// loosely based on https://github.com/plantain-00/type-coverage
const path = require("path");
const fs = require("fs");
const ts = require("typescript");
const program = require("./typescript-program");
const typeChecker = program.getTypeChecker();
const projectPaths = [
path.resolve(__dirname, "../lib"),
path.resolve(__dirname, "../bin"),
path.resolve(__dirname, "../tooling"),
path.resolve(__dirname, "../declarations.d.ts")
];
/**
* @param {string} file filename
* @returns {boolean} true, when file is part of the project
*/
const isProjectFile = file => {
return projectPaths.some(p =>
file.toLowerCase().startsWith(p.replace(/\\/g, "/").toLowerCase())
);
};
/**
* @typedef {Object} Location
* @property {number} line
* @property {number} column
*/
/**
* @typedef {Object} FileReport
* @property {string} path
* @property {Record<number, { start: Location, end: Location }>} statementMap
* @property {{}} fnMap
* @property {{}} branchMap
* @property {Record<number, number>} s
* @property {{}} f
* @property {{}} b
*/
/** @type {Record<string, FileReport>} */
const coverageReport = Object.create(null);
for (const sourceFile of program.getSourceFiles()) {
let file = sourceFile.fileName;
if (isProjectFile(file)) {
/** @type {FileReport} */
const rep = {
path: path.sep !== "/" ? file.replace(/\//g, path.sep) : file,
statementMap: {},
fnMap: {},
branchMap: {},
s: {},
f: {},
b: {}
};
coverageReport[rep.path] = rep;
let statementIndex = 0;
/**
* @param {ts.Node} node the node to be walked
* @returns {void}
*/
const walkNode = node => {
if (ts.isIdentifier(node) || node.kind === ts.SyntaxKind.ThisKeyword) {
const type = typeChecker.getTypeAtLocation(node);
if (type) {
const { line, character } = ts.getLineAndCharacterOfPosition(
sourceFile,
node.getStart()
);
const {
line: lineEnd,
character: characterEnd
} = ts.getLineAndCharacterOfPosition(sourceFile, node.getEnd());
const typeText = typeChecker.typeToString(type);
let isExternal = false;
/**
* @param {ts.Type} type the type to be checked
* @returns {void}
*/
const checkDecls = type => {
if (!type.symbol) return;
for (const decl of type.symbol.getDeclarations()) {
const sourceFile = decl.getSourceFile();
if (sourceFile && !isProjectFile(sourceFile.fileName))
isExternal = true;
}
};
if (node.parent && ts.isPropertyAccessExpression(node.parent)) {
const expressionType = typeChecker.getTypeAtLocation(
node.parent.expression
);
checkDecls(expressionType);
}
if (/^(<.*>)?\(/.test(typeText)) {
checkDecls(type);
}
const isTyped =
isExternal ||
(!(type.flags & ts.TypeFlags.Any) && !/\bany\b/.test(typeText));
rep.statementMap[statementIndex] = {
start: {
line: line + 1,
column: character
},
end: {
line: lineEnd + 1,
column: characterEnd - 1
}
};
rep.s[statementIndex] = isTyped ? typeText.length : 0;
statementIndex++;
}
}
node.forEachChild(walkNode);
};
sourceFile.forEachChild(walkNode);
}
}
const outputDirectory = path.resolve(__dirname, "../coverage");
fs.mkdirSync(outputDirectory, { recursive: true });
fs.writeFileSync(
path.resolve(outputDirectory, "coverage-types.json"),
JSON.stringify(coverageReport),
"utf-8"
);

View File

@ -1,17 +0,0 @@
const path = require("path");
const fs = require("fs");
const ts = require("typescript");
const rootPath = path.resolve(__dirname, "..");
const configPath = path.resolve(__dirname, "../tsconfig.json");
const configContent = fs.readFileSync(configPath, "utf-8");
const configJsonFile = ts.parseJsonText(configPath, configContent);
const parsedConfig = ts.parseJsonSourceFileConfigFileContent(
configJsonFile,
ts.sys,
rootPath,
{ noEmit: true }
);
const { fileNames, options } = parsedConfig;
module.exports = ts.createProgram(fileNames, options);

16
tsconfig.test.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"lib": ["es2017", "dom"],
"allowJs": true,
"checkJs": true,
"noEmit": true,
"strict": false,
"noImplicitThis": true,
"alwaysStrict": true,
"types": ["node", "jest"],
"esModuleInterop": true
},
"include": ["test/**/webpack.config.js", "types.d.ts"]
}

16
tsconfig.types.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"lib": ["es2017", "dom"],
"allowJs": true,
"checkJs": true,
"noEmit": true,
"strict": false,
"noImplicitThis": true,
"alwaysStrict": true,
"types": ["node"],
"esModuleInterop": true
},
"include": ["declarations.d.ts", "declarations/*.d.ts", "lib/**/*.js"]
}

9627
types.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -448,7 +448,7 @@
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^13.0.0"
"@jest/types@^25.4.0":
"@jest/types@^25.1.0", "@jest/types@^25.4.0":
version "25.4.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.4.0.tgz#5afeb8f7e1cba153a28e5ac3c9fe3eede7206d59"
integrity sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==
@ -552,6 +552,14 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/jest@^25.1.5":
version "25.1.5"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.1.5.tgz#3c3c078b3cd19c6403e21277f1cfdc0ce5ebf9a9"
integrity sha512-FBmb9YZHoEOH56Xo/PIYtfuyTL0IzJLM3Hy0Sqc82nn5eqqXgefKcl/eMgChM8eSGVfoDee8cdlj7K74T8a6Yg==
dependencies:
jest-diff "25.1.0"
pretty-format "25.1.0"
"@types/json-schema@^7.0.3":
version "7.0.3"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
@ -2205,7 +2213,7 @@ detect-newline@^3.0.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
diff-sequences@^25.2.6:
diff-sequences@^25.1.0, diff-sequences@^25.2.6:
version "25.2.6"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==
@ -3722,6 +3730,16 @@ jest-config@^25.4.0:
pretty-format "^25.4.0"
realpath-native "^2.0.0"
jest-diff@25.1.0:
version "25.1.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.1.0.tgz#58b827e63edea1bc80c1de952b80cec9ac50e1ad"
integrity sha512-nepXgajT+h017APJTreSieh4zCqnSHEJ1iT8HDlewu630lSJ4Kjjr9KNzm+kzGwwcpsDE6Snx1GJGzzsefaEHw==
dependencies:
chalk "^3.0.0"
diff-sequences "^25.1.0"
jest-get-type "^25.1.0"
pretty-format "^25.1.0"
jest-diff@^25.1.0, jest-diff@^25.4.0:
version "25.4.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.4.0.tgz#260b70f19a46c283adcad7f081cae71eb784a634"
@ -3779,7 +3797,7 @@ jest-get-type@^24.9.0:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
jest-get-type@^25.2.6:
jest-get-type@^25.1.0, jest-get-type@^25.2.6:
version "25.2.6"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877"
integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==
@ -4156,7 +4174,7 @@ json-schema-ref-parser@^6.1.0:
js-yaml "^3.12.1"
ono "^4.0.11"
json-schema-to-typescript@^8.1.0:
json-schema-to-typescript@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/json-schema-to-typescript/-/json-schema-to-typescript-8.2.0.tgz#a859f836df89db63c5f17a6c9c2f1dea93e8dd9b"
integrity sha512-yvi4v9oLeJzJCktt+Zta6kOgEu8R93gNMZUJYo83aAPxoG0qB+cXIxVg5xa6gmdNkyffjH9Ebw1rvyaJKIor5A==
@ -5434,6 +5452,16 @@ prettier@^1.19.1:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
pretty-format@25.1.0:
version "25.1.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.1.0.tgz#ed869bdaec1356fc5ae45de045e2c8ec7b07b0c8"
integrity sha512-46zLRSGLd02Rp+Lhad9zzuNZ+swunitn8zIpfD2B4OPCRLXbM87RJT2aBLBWYOznNUML/2l/ReMyWNC80PJBUQ==
dependencies:
"@jest/types" "^25.1.0"
ansi-regex "^5.0.0"
ansi-styles "^4.0.0"
react-is "^16.12.0"
pretty-format@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
@ -6737,6 +6765,16 @@ toml@^3.0.0:
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
tooling@webpack/tooling:
version "1.0.0"
resolved "https://codeload.github.com/webpack/tooling/tar.gz/c960d3590c197b9a68a17c5f0ca4896623c6c0d6"
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
commondir "^1.0.1"
glob "^7.1.6"
json-schema-to-typescript "^8.2.0"
yargs "^15.3.1"
tough-cookie@^2.3.3:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"