diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b23234..ac6d093 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [#51](https://github.com/green-code-initiative/creedengo-javascript/pull/51) Add ESLint v9 and flat config support
+- [#90](https://github.com/green-code-initiative/creedengo-javascript/pull/90) Add avoid using resource-hungry libs rule
### Changed
diff --git a/eslint-plugin/docs/rules/avoid-using-resource-hungry-libs.md b/eslint-plugin/docs/rules/avoid-using-resource-hungry-libs.md
new file mode 100644
index 0000000..706ed2a
--- /dev/null
+++ b/eslint-plugin/docs/rules/avoid-using-resource-hungry-libs.md
@@ -0,0 +1,30 @@
+# Avoid using resource hungry libraries(`@creedengo/avoid-using-resource-hungry-libs`)
+
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
+
+
+
+## Why is this an issue?
+
+Avoid imports of known resource-hungry or deprecated libraries and suggest lighter alternatives.
+
+This rule flags any import, require or dynamic import of libraries listed in the project’s deprecation dictionary (`moment`, `iconsax`, etc.), because these libraries
+1. Inflate your bundle size
+2. Slow parsing & compilation
+3. Often lack tree-shaking support
+4. May be unmaintained
+
+```js
+import moment from "moment";
+const age = moment().diff(birthday, "years");
+```
+
+```js
+import differenceInYears from "date-fns/differenceInYears";
+
+const age = differenceInYears(new Date(), birthday);
+```
+
+## Resources
+
+### Documentation
diff --git a/eslint-plugin/lib/rules/avoid-using-resource-hungry-libs.js b/eslint-plugin/lib/rules/avoid-using-resource-hungry-libs.js
new file mode 100644
index 0000000..cb76b99
--- /dev/null
+++ b/eslint-plugin/lib/rules/avoid-using-resource-hungry-libs.js
@@ -0,0 +1,112 @@
+/*
+ * creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+/**
+ * List of deprecated libraries and their suggested replacements.
+ *
+ * Key = package name to forbid
+ * Value = { reason: string, alternatives: string[] }
+ */
+const DEPRECATED_LIBS = {
+ moment: {
+ reason: "deprecated and heavy to load",
+ alternatives: ["date-fns", "dayjs"],
+ },
+ iconsax: {
+ reason: "does not support tree-shaking and adds large bundle size",
+ alternatives: ["@mui/icons-material", "lucide-react"],
+ },
+ lodash: {
+ reason: "too large, prefer modular imports or native methods",
+ alternatives: ["lodash.get", "Array.prototype.map", "Object.assign"],
+ },
+ // add more entries here as needed
+};
+
+module.exports = {
+ meta: {
+ type: "suggestion",
+ docs: {
+ description:
+ "Disallow importing deprecated libraries and suggest lighter alternatives",
+ category: "best-practice",
+ recommended: "warn",
+ },
+ messages: {
+ noDeprecatedLib:
+ "Library '{{name}}' is {{reason}}. Consider using {{alternatives}}.",
+ },
+ schema: [],
+ },
+
+ create(context) {
+ /**
+ * Report a deprecation warning on the given node.
+ */
+ function reportDeprecation(node, libName) {
+ const { reason, alternatives } = DEPRECATED_LIBS[libName];
+ context.report({
+ node,
+ messageId: "noDeprecatedLib",
+ data: {
+ name: libName,
+ reason,
+ alternatives: alternatives.join(", "),
+ },
+ });
+ }
+
+ return {
+ // import moment from "moment";
+ ImportDeclaration(node) {
+ const pkg = node.source.value;
+ if (DEPRECATED_LIBS[pkg]) {
+ reportDeprecation(node.source, pkg);
+ }
+ },
+
+ // const moment = require("moment");
+ CallExpression(node) {
+ if (
+ node.callee.type === "Identifier" &&
+ node.callee.name === "require" &&
+ node.arguments.length === 1
+ ) {
+ const arg = node.arguments[0];
+ if (
+ arg.type === "Literal" &&
+ typeof arg.value === "string" &&
+ DEPRECATED_LIBS[arg.value]
+ ) {
+ reportDeprecation(arg, arg.value);
+ }
+ }
+ },
+
+ // import("moment").then(...)
+ ImportExpression(node) {
+ const src = node.source;
+ if (src.type === "Literal" && DEPRECATED_LIBS[src.value]) {
+ reportDeprecation(src, src.value);
+ }
+ },
+ };
+ },
+};
diff --git a/eslint-plugin/tests/lib/rules/avoid-using-resource-hungry-libs.js b/eslint-plugin/tests/lib/rules/avoid-using-resource-hungry-libs.js
new file mode 100644
index 0000000..8a7ef02
--- /dev/null
+++ b/eslint-plugin/tests/lib/rules/avoid-using-resource-hungry-libs.js
@@ -0,0 +1,87 @@
+/*
+ * creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/avoid-using-resource-hungry-libs");
+const { RuleTester } = require("eslint");
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+});
+
+const momentError = {
+ messageId: "noDeprecatedLib",
+ data: {
+ name: "moment",
+ reason: "deprecated and heavy to load",
+ alternatives: "date-fns, dayjs",
+ },
+ type: "Literal",
+};
+
+const iconsaxError = {
+ messageId: "noDeprecatedLib",
+ data: {
+ name: "iconsax",
+ reason: "does not support tree-shaking and adds large bundle size",
+ alternatives: "@mui/icons-material, lucide-react",
+ },
+ type: "Literal",
+};
+
+ruleTester.run("no-deprecated-libs", rule, {
+ valid: [
+ // imports of non-deprecated libraries
+ `import dayjs from "dayjs";`,
+ `const { format } = require("date-fns");`,
+ `const moment = require("luxon");`,
+ `import HomeIcon from "@mui/icons-material/Home";`,
+ `import { ReactComponent as Icon } from "some-svg";`,
+ `import("dayjs").then(d => console.log(d));`,
+ // dynamic import of non-deprecated
+ `import("lucide-react").then(l => console.log(l));`,
+ ],
+ invalid: [
+ // -- moment cases --
+ { code: `import moment from "moment";`, errors: [momentError] },
+ { code: `import { duration } from "moment";`, errors: [momentError] },
+ { code: `import "moment";`, errors: [momentError] },
+ { code: `const moment = require("moment");`, errors: [momentError] },
+ { code: `require("moment");`, errors: [momentError] },
+ {
+ code: `import("moment").then(m => console.log(m));`,
+ errors: [momentError],
+ },
+
+ // -- iconsax cases --
+ { code: `import iconsax from "iconsax";`, errors: [iconsaxError] },
+ { code: `import { IconHome } from "iconsax";`, errors: [iconsaxError] },
+ { code: `import "iconsax";`, errors: [iconsaxError] },
+ { code: `const iconsax = require("iconsax");`, errors: [iconsaxError] },
+ { code: `require("iconsax");`, errors: [iconsaxError] },
+ {
+ code: `import("iconsax").then(i => console.log(i));`,
+ errors: [iconsaxError],
+ },
+ ],
+});
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/CheckList.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/CheckList.java
index 8ed5b81..5fa8b79 100644
--- a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/CheckList.java
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/CheckList.java
@@ -48,7 +48,8 @@ public static List> getAllChecks() {
PreferCollectionsWithPagination.class,
PreferLighterFormatsForImageFiles.class,
PreferShorthandCSSNotations.class,
- ProvidePrintCSS.class
+ ProvidePrintCSS.class,
+ AvoidUsingResourceHungryLibs.class
);
}
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/checks/AvoidUsingResourceHungryLibs.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/checks/AvoidUsingResourceHungryLibs.java
new file mode 100644
index 0000000..97aa616
--- /dev/null
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/checks/AvoidUsingResourceHungryLibs.java
@@ -0,0 +1,37 @@
+/*
+ * Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.javascript.checks;
+
+import org.sonar.check.Rule;
+import org.sonar.plugins.javascript.api.EslintBasedCheck;
+import org.sonar.plugins.javascript.api.JavaScriptRule;
+import org.sonar.plugins.javascript.api.TypeScriptRule;
+
+@JavaScriptRule
+@TypeScriptRule
+@Rule(key = AvoidUsingResourceHungryLibs.RULE_KEY)
+public class AvoidUsingResourceHungryLibs implements EslintBasedCheck {
+
+ public static final String RULE_KEY = "GCI36";
+
+ @Override
+ public String eslintKey() {
+ return "@creedengo/avoid-autoplay";
+ }
+
+}