restrict-imports-loader
Version:
A Webpack loader to restrict imports in ES and TypeScript
137 lines • 5.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const loader_utils_1 = require("loader-utils");
const schema_utils_1 = __importDefault(require("schema-utils"));
const core = __importStar(require("./core"));
const deciders = __importStar(require("./deciders"));
const text_1 = require("./text");
const utilities_1 = require("./utilities");
const DEFAULT = {
info: `Found restricted imports:`,
detailedErrorMessages: true,
};
const CONFIG = {
name: "restrict-imports-loader",
};
const SEVERITIES = ["fatal", "error", "warning"];
const SCHEMA = {
type: "object",
required: ["rules", "severity"],
properties: {
detailedErrorMessages: {
description: `Include the faulty import statement when printing an error message (default: ${text_1.quote(DEFAULT.detailedErrorMessages.toString())}). If disabled, only the import path (e.g. "typescript") is included.`,
type: "boolean",
},
rules: {
description: "List of rules to check against.",
items: {
type: "object",
required: ["restricted"],
properties: {
restricted: {
description: `Regular expression or function (of type (string, webpack.loader.LoaderContext) => Promise<boolean>) specifying which imports should be restricted.`,
anyOf: [
{ instanceof: "RegExp" },
{ instanceof: "Function" },
],
},
severity: {
description: `Severity for this specific rule.`,
anyOf: [
{ enum: SEVERITIES },
],
},
info: {
description: `An informational message to show to the user (default: ${text_1.quote(DEFAULT.info)})`,
type: "string",
},
},
},
},
severity: {
description: `Controls what happens if a restricted import is detected. Can be overridden for individual rules.`,
anyOf: [
{ enum: SEVERITIES },
],
},
},
additionalProperties: false,
};
function run(loaderContext, source) {
const callback = loaderContext.async();
if (callback === undefined)
throw new Error(`Webpack did not provide an async callback.`);
const options = loader_utils_1.getOptions(loaderContext);
schema_utils_1.default(SCHEMA, options, CONFIG);
const rules = options.rules;
const detailedErrorMessages = utilities_1.defaultTo(DEFAULT.detailedErrorMessages, options.detailedErrorMessages);
core.checkAsync({
source: source,
deciders: rules.map(r => r.restricted).map(deciderFunction(loaderContext)),
fileName: loaderContext.resourcePath,
setParentNodes: detailedErrorMessages,
}).then(badImportMatrix => {
rules.forEach((rule, i) => {
const badImports = badImportMatrix[i];
if (badImports.length > 0) {
const severity = utilities_1.defaultTo(options.severity, rule.severity);
const info = utilities_1.defaultTo(DEFAULT.info, rule.info);
const err = new Error(errorMessageForAll(badImports, info, detailedErrorMessages));
switch (severity) {
case "fatal":
throw err;
case "error":
loaderContext.emitError(err);
break;
case "warning":
loaderContext.emitWarning(err);
break;
default:
const _ = severity;
throw _;
}
}
});
callback(null, source);
}).catch(err => {
callback(err, source);
});
}
exports.run = run;
function deciderFunction(loaderContext) {
return decider => (decider instanceof RegExp
? deciders.matchedBy(decider)
: importPath => decider(importPath, loaderContext));
}
function errorMessageForAll(imports, info, setParentNodesWasUsed) {
return [
info,
"",
text_1.indentBy(2)(imports.map(errorMessage(setParentNodesWasUsed)).join("")).trimRight(),
"",
"",
].join("\n");
}
function errorMessage(setParentNodesWasUsed) {
const details = (i) => (setParentNodesWasUsed
? [
`:`,
``,
text_1.indentBy(6)(i.node.getText()),
``,
i.info ? text_1.indentBy(2)(i.info) + "\n\n" : "",
].join("\n")
: "");
return i => `• ` + text_1.quote(i.path) + `, imported on line ${i.line}` + details(i) + `\n`;
}
//# sourceMappingURL=loader.js.map