Skip to content

Commit

Permalink
Initial shape.
Browse files Browse the repository at this point in the history
  • Loading branch information
Anna Bocharova committed Aug 6, 2024
0 parents commit 40c2977
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
.idea
.DS_Store
node_modules
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# eslint-plugin-allowed-dependencies

11 changes: 11 additions & 0 deletions build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
await Bun.build({
entrypoints: ["src/index.ts"],
outdir: "dist",
/** @link https://github.com/oven-sh/bun/issues/159 */
format: "esm",
splitting: false,
sourcemap: "none",
minify: true,
target: "node",
external: ["*"],
});
Binary file added bun.lockb
Binary file not shown.
35 changes: 35 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "eslint-plugin-allowed-dependencies",
"version": "0.0.1",
"module": "src/index.ts",
"type": "module",
"main": "dist/index.cjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"files": ["dist", "*.md"],
"scripts": {
"build:cjs": "tsc -p tsconfig.cjs.json && uglifyjs dist/index.js -c -m -o dist/index.cjs",
"build": "bun run build:cjs && bun run build.ts"
},
"dependencies": {
"ramda": "^0.30.1"
},
"devDependencies": {
"@types/bun": "latest",
"@types/ramda": "^0.30.1",
"@tsconfig/node18": "^18.2.4",
"@tsconfig/bun": "^1.0.7",
"typescript": "^5.5.4",
"type-fest": "^4.23.0",
"uglify-js": "^3.19.1"
},
"peerDependencies": {
"eslint": "^9.0.0",
"@typescript-eslint/utils": "^8.0.0"
}
}
76 changes: 76 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ESLintUtils, TSESLint } from "@typescript-eslint/utils";
import { flip, partition, path, reject, startsWith } from "ramda";
import type { PackageJson } from "type-fest";

const messages = {
prohibited: "Importing {{name}} is not allowed.",
typeOnly: "Only 'import type' syntax is allowed for {{name}}.",
};

const createRule = ESLintUtils.RuleCreator.withoutDocs;

const allowedDeps = createRule<
[
{
manifest: PackageJson.PackageJsonStandard;
typeOnly?: string[];
},
],
keyof typeof messages
>({
meta: {
messages,
type: "problem",
fixable: "code",
schema: [
{
type: "object",
properties: {
manifest: { type: "object" }, // @todo use settings
typeOnly: { type: "array", items: { type: "string" } },
},
},
],
},
defaultOptions: [{ manifest: {}, typeOnly: [] }],
create: (ctx, [{ manifest, typeOnly: userTypeOnly = [] }]) => {
const lookup = flip(path)(manifest);
const excludeTypes = reject(startsWith("@types/"));
const isOptional = (name: string) =>
lookup(["peerDependenciesMeta", name, "optional"]) as boolean;

const allPeers = excludeTypes(Object.keys(manifest.peerDependencies || {}));
const [optPeers, reqPeers] = partition(isOptional, allPeers);
const production = Object.keys(manifest.dependencies || {});

const allowed = production.concat(reqPeers);
const typeOnly = optPeers.concat(userTypeOnly);

return {
ImportDeclaration: ({ source, importKind }) => {
const isTypeImport = importKind === "type";
if (
!source.value.startsWith(".") &&
!source.value.startsWith("node:")
) {
const name = source.value
.split("/")
.slice(0, source.value.startsWith("@") ? 2 : 1)
.join("/");
const commons = { node: source, data: { name } };
if (!allowed.includes(name) && !isTypeImport) {
if (isTypeImport && !typeOnly.includes(name)) {
ctx.report({ ...commons, messageId: "typeOnly" });
} else {
ctx.report({ ...commons, messageId: "prohibited" });
}
}
}
},
};
},
});

export default {
rules: { "allowed-dependencies": allowedDeps },
} satisfies TSESLint.Linter.Plugin;
10 changes: 10 additions & 0 deletions tsconfig.cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "@tsconfig/node18/tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"moduleResolution": "node",
"target": "ES6"
},
"include": ["src/index.ts"]
}
5 changes: 5 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "@tsconfig/bun/tsconfig.json",
"compilerOptions": {},
"include": ["src"]
}

0 comments on commit 40c2977

Please sign in to comment.