eslint-plugin-esm 0.0.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +60 -0
  3. package/dist/common.d.ts +24 -0
  4. package/dist/common.d.ts.map +1 -0
  5. package/dist/common.js +65 -0
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +23 -2
  9. package/dist/rules/nearest-relative-path.d.ts +5 -0
  10. package/dist/rules/nearest-relative-path.d.ts.map +1 -0
  11. package/dist/rules/nearest-relative-path.js +25 -0
  12. package/dist/rules/no-directory-imports.d.ts +5 -0
  13. package/dist/rules/no-directory-imports.d.ts.map +1 -0
  14. package/dist/rules/no-directory-imports.js +31 -0
  15. package/dist/rules/no-dynamic-imports.d.ts +5 -0
  16. package/dist/rules/no-dynamic-imports.d.ts.map +1 -0
  17. package/dist/rules/no-dynamic-imports.js +14 -0
  18. package/dist/rules/no-git-ignored-imports.d.ts +5 -0
  19. package/dist/rules/no-git-ignored-imports.d.ts.map +1 -0
  20. package/dist/rules/no-git-ignored-imports.js +46 -0
  21. package/dist/rules/no-phantom-dep-imports.d.ts +5 -0
  22. package/dist/rules/no-phantom-dep-imports.d.ts.map +1 -0
  23. package/dist/rules/no-phantom-dep-imports.js +73 -0
  24. package/dist/rules/no-relative-parent-imports.d.ts +5 -0
  25. package/dist/rules/no-relative-parent-imports.d.ts.map +1 -0
  26. package/dist/rules/no-relative-parent-imports.js +11 -0
  27. package/dist/rules/no-rename-exports.d.ts +5 -0
  28. package/dist/rules/no-rename-exports.d.ts.map +1 -0
  29. package/dist/rules/no-rename-exports.js +15 -0
  30. package/dist/rules/no-rename-imports.d.ts +5 -0
  31. package/dist/rules/no-rename-imports.d.ts.map +1 -0
  32. package/dist/rules/no-rename-imports.js +14 -0
  33. package/dist/rules/no-side-effect-imports.d.ts +5 -0
  34. package/dist/rules/no-side-effect-imports.d.ts.map +1 -0
  35. package/dist/rules/no-side-effect-imports.js +33 -0
  36. package/dist/rules/no-ts-file-imports.d.ts +5 -0
  37. package/dist/rules/no-ts-file-imports.d.ts.map +1 -0
  38. package/dist/rules/no-ts-file-imports.js +18 -0
  39. package/dist/utils.d.ts +5 -0
  40. package/dist/utils.d.ts.map +1 -0
  41. package/dist/utils.js +16 -0
  42. package/doc/rules/nearest-relative-path.md +48 -0
  43. package/doc/rules/no-directory-imports.md +30 -0
  44. package/doc/rules/no-dynamic-imports.md +30 -0
  45. package/doc/rules/no-git-ignored-imports.md +36 -0
  46. package/doc/rules/no-phantom-dep-imports.md +26 -0
  47. package/doc/rules/no-relative-parent-imports.md +33 -0
  48. package/doc/rules/no-rename-exports.md +29 -0
  49. package/doc/rules/no-rename-imports.md +28 -0
  50. package/doc/rules/no-side-effect-imports.md +31 -0
  51. package/doc/rules/no-ts-file-imports.md +119 -0
  52. package/package.json +7 -5
  53. package/src/common.ts +96 -0
  54. package/src/index.ts +23 -0
  55. package/src/rules/nearest-relative-path.spec.ts +44 -0
  56. package/src/rules/nearest-relative-path.ts +28 -0
  57. package/src/rules/no-directory-imports.spec.ts +31 -0
  58. package/src/rules/no-directory-imports.ts +34 -0
  59. package/src/rules/no-dynamic-imports.spec.ts +27 -0
  60. package/src/rules/no-dynamic-imports.ts +15 -0
  61. package/src/rules/no-git-ignored-imports.spec.ts +40 -0
  62. package/src/rules/no-git-ignored-imports.ts +53 -0
  63. package/src/rules/no-phantom-dep-imports.spec.ts +28 -0
  64. package/src/rules/no-phantom-dep-imports.ts +90 -0
  65. package/src/rules/no-relative-parent-imports.spec.ts +28 -0
  66. package/src/rules/no-relative-parent-imports.ts +13 -0
  67. package/src/rules/no-rename-exports.spec.ts +22 -0
  68. package/src/rules/no-rename-exports.ts +17 -0
  69. package/src/rules/no-rename-imports.spec.ts +22 -0
  70. package/src/rules/no-rename-imports.ts +16 -0
  71. package/src/rules/no-side-effect-imports.spec.ts +25 -0
  72. package/src/rules/no-side-effect-imports.ts +44 -0
  73. package/src/rules/no-ts-file-imports.spec.ts +39 -0
  74. package/src/rules/no-ts-file-imports.ts +23 -0
  75. package/src/test.spec.ts +110 -0
  76. package/src/utils.ts +15 -0
@@ -0,0 +1,33 @@
1
+ import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.js";
2
+ const ignores = [
3
+ "^reflect-metadata$",
4
+ // https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts
5
+ "(?<!\\.module)\\.css$",
6
+ "(?<!\\.module)\\.scss$",
7
+ "(?<!\\.module)\\.sass$",
8
+ "(?<!\\.module)\\.less$",
9
+ "(?<!\\.module)\\.styl$",
10
+ "(?<!\\.module)\\.stylus$",
11
+ "(?<!\\.module)\\.pcss$",
12
+ "(?<!\\.module)\\.sss$",
13
+ ];
14
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
15
+ export const noSideEffectImports = createRule({
16
+ name: getRuleName(import.meta.url),
17
+ message: "Side effect import is often used for polyfills and css. It's unsafe to use it.",
18
+ create: (context) => {
19
+ if ([".d.ts", ".d.cts", ".d.mts", ".d.tsx"].some((ext) => context.filename.endsWith(ext))) {
20
+ return {};
21
+ }
22
+ const ignoreExps = ignores.map((ignore) => new RegExp(ignore));
23
+ return {
24
+ "ImportDeclaration[specifiers.length=0]": (node) => {
25
+ if (ignoreExps.some((exp) => exp.test(node.source.value?.toString() ?? ""))) {
26
+ return;
27
+ }
28
+ context.report({ node, messageId: DEFAULT_MESSAGE_ID });
29
+ },
30
+ };
31
+ },
32
+ });
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tc2lkZS1lZmZlY3QtaW1wb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby1zaWRlLWVmZmVjdC1pbXBvcnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTNFLE1BQU0sT0FBTyxHQUFHO0lBQ2Qsb0JBQW9CO0lBQ3BCLHFFQUFxRTtJQUNyRSx1QkFBdUI7SUFDdkIsd0JBQXdCO0lBQ3hCLHdCQUF3QjtJQUN4Qix3QkFBd0I7SUFDeEIsd0JBQXdCO0lBQ3hCLDBCQUEwQjtJQUMxQix3QkFBd0I7SUFDeEIsdUJBQXVCO0NBQ3hCLENBQUM7QUFFRixzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsVUFBVSxDQUFDO0lBQzVDLElBQUksRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDbEMsT0FBTyxFQUNMLGdGQUFnRjtJQUNsRixNQUFNLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUNsQixJQUNFLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FDbkQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQy9CLEVBQ0QsQ0FBQztZQUNELE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDL0QsT0FBTztZQUNMLHdDQUF3QyxFQUFFLENBQUMsSUFBdUIsRUFBRSxFQUFFO2dCQUNwRSxJQUNFLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUN0QixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUM5QyxFQUNELENBQUM7b0JBQ0QsT0FBTztnQkFDVCxDQUFDO2dCQUNELE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztZQUMxRCxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7Q0FDRixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEltcG9ydERlY2xhcmF0aW9uIH0gZnJvbSBcImVzdHJlZVwiO1xuaW1wb3J0IHsgY3JlYXRlUnVsZSwgREVGQVVMVF9NRVNTQUdFX0lELCBnZXRSdWxlTmFtZSB9IGZyb20gXCIuLi9jb21tb24uanNcIjtcblxuY29uc3QgaWdub3JlcyA9IFtcbiAgXCJecmVmbGVjdC1tZXRhZGF0YSRcIixcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3ZpdGVqcy92aXRlL2Jsb2IvbWFpbi9wYWNrYWdlcy92aXRlL2NsaWVudC5kLnRzXG4gIFwiKD88IVxcXFwubW9kdWxlKVxcXFwuY3NzJFwiLFxuICBcIig/PCFcXFxcLm1vZHVsZSlcXFxcLnNjc3MkXCIsXG4gIFwiKD88IVxcXFwubW9kdWxlKVxcXFwuc2FzcyRcIixcbiAgXCIoPzwhXFxcXC5tb2R1bGUpXFxcXC5sZXNzJFwiLFxuICBcIig/PCFcXFxcLm1vZHVsZSlcXFxcLnN0eWwkXCIsXG4gIFwiKD88IVxcXFwubW9kdWxlKVxcXFwuc3R5bHVzJFwiLFxuICBcIig/PCFcXFxcLm1vZHVsZSlcXFxcLnBjc3MkXCIsXG4gIFwiKD88IVxcXFwubW9kdWxlKVxcXFwuc3NzJFwiLFxuXTtcblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvU3RhdGVtZW50cy9pbXBvcnRcbmV4cG9ydCBjb25zdCBub1NpZGVFZmZlY3RJbXBvcnRzID0gY3JlYXRlUnVsZSh7XG4gIG5hbWU6IGdldFJ1bGVOYW1lKGltcG9ydC5tZXRhLnVybCksXG4gIG1lc3NhZ2U6XG4gICAgXCJTaWRlIGVmZmVjdCBpbXBvcnQgaXMgb2Z0ZW4gdXNlZCBmb3IgcG9seWZpbGxzIGFuZCBjc3MuIEl0J3MgdW5zYWZlIHRvIHVzZSBpdC5cIixcbiAgY3JlYXRlOiAoY29udGV4dCkgPT4ge1xuICAgIGlmIChcbiAgICAgIFtcIi5kLnRzXCIsIFwiLmQuY3RzXCIsIFwiLmQubXRzXCIsIFwiLmQudHN4XCJdLnNvbWUoKGV4dCkgPT5cbiAgICAgICAgY29udGV4dC5maWxlbmFtZS5lbmRzV2l0aChleHQpLFxuICAgICAgKVxuICAgICkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zdCBpZ25vcmVFeHBzID0gaWdub3Jlcy5tYXAoKGlnbm9yZSkgPT4gbmV3IFJlZ0V4cChpZ25vcmUpKTtcbiAgICByZXR1cm4ge1xuICAgICAgXCJJbXBvcnREZWNsYXJhdGlvbltzcGVjaWZpZXJzLmxlbmd0aD0wXVwiOiAobm9kZTogSW1wb3J0RGVjbGFyYXRpb24pID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGlnbm9yZUV4cHMuc29tZSgoZXhwKSA9PlxuICAgICAgICAgICAgZXhwLnRlc3Qobm9kZS5zb3VyY2UudmFsdWU/LnRvU3RyaW5nKCkgPz8gXCJcIiksXG4gICAgICAgICAgKVxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29udGV4dC5yZXBvcnQoeyBub2RlLCBtZXNzYWdlSWQ6IERFRkFVTFRfTUVTU0FHRV9JRCB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfSxcbn0pO1xuIl19
@@ -0,0 +1,5 @@
1
+ export declare const noTsFileImports: {
2
+ name: string;
3
+ rule: import("eslint").Rule.RuleModule;
4
+ };
5
+ //# sourceMappingURL=no-ts-file-imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-ts-file-imports.d.ts","sourceRoot":"","sources":["../../src/rules/no-ts-file-imports.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;CAI1B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { create, createRule, getRuleName } from "../common.js";
2
+ export const noTsFileImports = createRule({
3
+ name: getRuleName(import.meta.url),
4
+ message: "Disallow importing from a declaration style file or a ts file",
5
+ create: (context) => create(context, check),
6
+ });
7
+ function check(filename, source) {
8
+ // disabled this rule in declaration files
9
+ if ([".d.ts", ".d.cts", ".d.mts", ".d.tsx"].some((ext) => filename.endsWith(ext))) {
10
+ return false;
11
+ }
12
+ const file = source.split("/").at(-1);
13
+ if (!file || file.includes(".d.")) {
14
+ return true;
15
+ }
16
+ return [".ts", ".cts", ".mts", ".tsx"].some((ext) => file.endsWith(ext));
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdHMtZmlsZS1pbXBvcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bGVzL25vLXRzLWZpbGUtaW1wb3J0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFL0QsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztJQUN4QyxJQUFJLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ2xDLE9BQU8sRUFBRSwrREFBK0Q7SUFDeEUsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQztDQUM1QyxDQUFDLENBQUM7QUFFSCxTQUFTLEtBQUssQ0FBQyxRQUFnQixFQUFFLE1BQWM7SUFDN0MsMENBQTBDO0lBQzFDLElBQ0UsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUNuRCxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUN2QixFQUNELENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2xDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUMzRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlLCBjcmVhdGVSdWxlLCBnZXRSdWxlTmFtZSB9IGZyb20gXCIuLi9jb21tb24uanNcIjtcblxuZXhwb3J0IGNvbnN0IG5vVHNGaWxlSW1wb3J0cyA9IGNyZWF0ZVJ1bGUoe1xuICBuYW1lOiBnZXRSdWxlTmFtZShpbXBvcnQubWV0YS51cmwpLFxuICBtZXNzYWdlOiBcIkRpc2FsbG93IGltcG9ydGluZyBmcm9tIGEgZGVjbGFyYXRpb24gc3R5bGUgZmlsZSBvciBhIHRzIGZpbGVcIixcbiAgY3JlYXRlOiAoY29udGV4dCkgPT4gY3JlYXRlKGNvbnRleHQsIGNoZWNrKSxcbn0pO1xuXG5mdW5jdGlvbiBjaGVjayhmaWxlbmFtZTogc3RyaW5nLCBzb3VyY2U6IHN0cmluZykge1xuICAvLyBkaXNhYmxlZCB0aGlzIHJ1bGUgaW4gZGVjbGFyYXRpb24gZmlsZXNcbiAgaWYgKFxuICAgIFtcIi5kLnRzXCIsIFwiLmQuY3RzXCIsIFwiLmQubXRzXCIsIFwiLmQudHN4XCJdLnNvbWUoKGV4dCkgPT5cbiAgICAgIGZpbGVuYW1lLmVuZHNXaXRoKGV4dCksXG4gICAgKVxuICApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgZmlsZSA9IHNvdXJjZS5zcGxpdChcIi9cIikuYXQoLTEpO1xuICBpZiAoIWZpbGUgfHwgZmlsZS5pbmNsdWRlcyhcIi5kLlwiKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBbXCIudHNcIiwgXCIuY3RzXCIsIFwiLm10c1wiLCBcIi50c3hcIl0uc29tZSgoZXh0KSA9PiBmaWxlLmVuZHNXaXRoKGV4dCkpO1xufVxuIl19
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Like [lodash.memoize](https://lodash.com/docs/4.17.15#memoize)
3
+ */
4
+ export declare function memoize<Arg, Res>(fn: (arg: Arg) => Res): (arg: Arg) => Res;
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAW1E"}
package/dist/utils.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Like [lodash.memoize](https://lodash.com/docs/4.17.15#memoize)
3
+ */
4
+ export function memoize(fn) {
5
+ const cache = new Map(); // memory leak
6
+ return (arg) => {
7
+ if (cache.has(arg)) {
8
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
9
+ return cache.get(arg);
10
+ }
11
+ const result = fn(arg);
12
+ cache.set(arg, result);
13
+ return result;
14
+ };
15
+ }
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFDSCxNQUFNLFVBQVUsT0FBTyxDQUFXLEVBQXFCO0lBQ3JELE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxFQUFZLENBQUMsQ0FBQyxjQUFjO0lBQ2pELE9BQU8sQ0FBQyxHQUFRLEVBQUUsRUFBRTtRQUNsQixJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNuQixvRUFBb0U7WUFDcEUsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBRSxDQUFDO1FBQ3pCLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDdkIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGlrZSBbbG9kYXNoLm1lbW9pemVdKGh0dHBzOi8vbG9kYXNoLmNvbS9kb2NzLzQuMTcuMTUjbWVtb2l6ZSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lbW9pemU8QXJnLCBSZXM+KGZuOiAoYXJnOiBBcmcpID0+IFJlcyk6IChhcmc6IEFyZykgPT4gUmVzIHtcbiAgY29uc3QgY2FjaGUgPSBuZXcgTWFwPEFyZywgUmVzPigpOyAvLyBtZW1vcnkgbGVha1xuICByZXR1cm4gKGFyZzogQXJnKSA9PiB7XG4gICAgaWYgKGNhY2hlLmhhcyhhcmcpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgcmV0dXJuIGNhY2hlLmdldChhcmcpITtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0ID0gZm4oYXJnKTtcbiAgICBjYWNoZS5zZXQoYXJnLCByZXN1bHQpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG4iXX0=
@@ -0,0 +1,48 @@
1
+ <!-- prettier-ignore-start -->
2
+ # nearest-relative-path
3
+
4
+ The relative source path should be a nearest relative path.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import xxx from ".././../a" // filename: /a/b/c/d/e.js
12
+ import ".././../a" // filename: /a/b/c/d/e.js
13
+ import(".././../a") // filename: /a/b/c/d/e.js
14
+ export * from ".././../a" // filename: /a/b/c/d/e.js
15
+ export {a} from ".././../a" // filename: /a/b/c/d/e.js
16
+ import xxx from "./../a" // filename: /a/b/c/d/e.js
17
+ import "./../a" // filename: /a/b/c/d/e.js
18
+ import("./../a") // filename: /a/b/c/d/e.js
19
+ export * from "./../a" // filename: /a/b/c/d/e.js
20
+ export {a} from "./../a" // filename: /a/b/c/d/e.js
21
+ import "././foo" // filename: /a/b/c/d/e.js
22
+ import "./../.././foo" // filename: /a/b/c/d/e.js
23
+ import("./../.././foo") // filename: /a/b/c/d/e.js
24
+ export * from "./../.././foo" // filename: /a/b/c/d/e.js
25
+ export {a} from "./../.././foo" // filename: /a/b/c/d/e.js
26
+ import "./../foo" // filename: /a/b/c/d/e.js
27
+ import("./../foo") // filename: /a/b/c/d/e.js
28
+ export * from "./../foo" // filename: /a/b/c/d/e.js
29
+ export {a} from "./../foo" // filename: /a/b/c/d/e.js
30
+ ```
31
+
32
+ ### Pass
33
+
34
+ ```ts
35
+ import xxx from "../a" // filename: /a/b/c/d/e.js
36
+ import "../a" // filename: /a/b/c/d/e.js
37
+ import("../a") // filename: /a/b/c/d/e.js
38
+ require("../a") // filename: /a/b/c/d/e.js
39
+ import xxx from "./a" // filename: /a/b/c/d/e.js
40
+ import xxx from "a" // filename: /a/b/c/d/e.js
41
+ import xxx from ".a" // filename: /a/b/c/d/e.js
42
+ export * from "a" // filename: /a/b/c/d/e.js
43
+ export * from "./a" // filename: /a/b/c/d/e.js
44
+ export {a} from "a" // filename: /a/b/c/d/e.js
45
+ export {a} from "./a" // filename: /a/b/c/d/e.js
46
+ import foo from "." // filename: /a/b/c/d/e.js
47
+ ```
48
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,30 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-directory-imports
3
+
4
+ Disallow importing from a directory.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import foo from '.' // filename: /foo/src/rules/no-directory-imports.spec.ts
12
+ import foo from './' // filename: /foo/src/rules/no-directory-imports.spec.ts
13
+ import foo from '..' // filename: /foo/src/rules/no-directory-imports.spec.ts
14
+ import foo from '../' // filename: /foo/src/rules/no-directory-imports.spec.ts
15
+ import foo from '../rules' // filename: /foo/src/rules/no-directory-imports.spec.ts
16
+ import foo from '../rules/' // filename: /foo/src/rules/no-directory-imports.spec.ts
17
+ import foo from '../../src' // filename: /foo/src/rules/no-directory-imports.spec.ts
18
+ import foo from '/foo' // filename: /foo/src/rules/no-directory-imports.spec.ts
19
+ ```
20
+
21
+ ### Pass
22
+
23
+ ```ts
24
+ import foo from 'foo' // filename: /foo/src/rules/no-directory-imports.spec.ts
25
+ import foo from './foo' // filename: /foo/src/rules/no-directory-imports.spec.ts
26
+ import foo from '/foo/index.js' // filename: /foo/src/rules/no-directory-imports.spec.ts
27
+ import foo from '/foo/index.ts' // filename: /foo/src/rules/no-directory-imports.spec.ts
28
+ import foo from '/foo/package.json' // filename: /foo/src/rules/no-directory-imports.spec.ts
29
+ ```
30
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,30 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-dynamic-imports
3
+
4
+ `import()` should be called with string literal.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import(false)
12
+ import(123)
13
+ await import(123)
14
+ import(`foo`)
15
+ import(foo)
16
+ import({})
17
+ import([])
18
+ const foo = await import(foo)
19
+ ```
20
+
21
+ ### Pass
22
+
23
+ ```ts
24
+ import('foo')
25
+ import("foo")
26
+ import("./foo")
27
+ await import("foo")
28
+ const foo = await import("foo")
29
+ ```
30
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,36 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-git-ignored-imports
3
+
4
+ Disallow to import module from a git-ignored path.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import foo from './dist/foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
12
+ import './dist/foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
13
+ import('./dist/foo') // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
14
+ export * from './dist/foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
15
+ export {name} from './dist/foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
16
+ import foo from '../dist/index.js' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
17
+ import foo from '../../node_modules/foo/bar.js' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
18
+ import foo from '/foo/tmp' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
19
+ import foo from '/foo/tmp' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
20
+ import foo from '../../test/for-test' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
21
+ import foo from '../../../../../for-test' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
22
+ ```
23
+
24
+ ### Pass
25
+
26
+ ```ts
27
+ import foo from 'foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
28
+ import 'foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
29
+ require('foo') // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
30
+ import('foo') // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
31
+ export * from 'foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
32
+ export {name} from 'foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
33
+ import foo from '.foo' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
34
+ import foo from '../../../../for-test' // filename: /foo/src/rules/no-git-ignored-imports.spec.ts
35
+ ```
36
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,26 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-phantom-dep-imports
3
+
4
+ Disallow importing from a module which the nearest `package.json` doesn't include it.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import {type Foo} from 'foo'
12
+ import foo from 'foo' // filename: /foo/src/rules/no-phantom-dep-imports.spec.ts
13
+ import eslint from 'eslint' // filename: /foo/foo.js
14
+ ```
15
+
16
+ ### Pass
17
+
18
+ ```ts
19
+ import foo from '/foo'
20
+ import foo from './foo'
21
+ import foo from '../foo'
22
+ import foo from 'node:foo'
23
+ import type {Foo} from 'foo'
24
+ import eslint from 'eslint' // filename: /foo/src/rules/no-phantom-dep-imports.spec.ts
25
+ ```
26
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,33 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-relative-parent-imports
3
+
4
+ Disallow importing module from a relative parent path too deeply.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import foo from '../../../foo'
12
+ import '../../../foo'
13
+ import('../../../foo')
14
+ export * from '../../../foo'
15
+ export {name} from '../../../foo'
16
+ import foo from '../../../../foo'
17
+ ```
18
+
19
+ ### Pass
20
+
21
+ ```ts
22
+ import foo from 'foo'
23
+ import 'foo'
24
+ require('foo')
25
+ import('foo')
26
+ export * from 'foo'
27
+ export {name} from 'foo'
28
+ import foo from '.foo'
29
+ import foo from './foo'
30
+ import foo from '../foo'
31
+ import foo from '../../foo'
32
+ ```
33
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,29 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-rename-exports
3
+
4
+ Disallow renaming the named-exports.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ let foo=1; export {foo as bar}
12
+ let foo=1; export {foo as default}
13
+ export {foo as bar} from './foo'
14
+ export {default as foo} from './foo'
15
+ export {type Foo as Bar}
16
+ export type {Foo as Bar}
17
+ ```
18
+
19
+ ### Pass
20
+
21
+ ```ts
22
+ let foo=1; export {foo}
23
+ export let foo
24
+ export const foo = bar
25
+ export default foo
26
+ export default {}
27
+ export {}
28
+ ```
29
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,28 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-rename-imports
3
+
4
+ Disallow renaming the named-imports.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import {foo as bar} from 'foo'
12
+ import {default as foo} from 'foo'
13
+ import type {foo as bar} from 'foo'
14
+ import {type foo as bar} from 'foo'
15
+ import type {default as foo} from 'foo'
16
+ import {type default as foo} from 'foo'
17
+ ```
18
+
19
+ ### Pass
20
+
21
+ ```ts
22
+ import Foo from 'foo'
23
+ import {foo, bar} from 'foo'
24
+ import {type foo} from 'foo'
25
+ import type {foo} from 'foo'
26
+ import type Foo from 'foo'
27
+ ```
28
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,31 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-side-effect-imports
3
+
4
+ Side effect import is often used for polyfills and css. It's unsafe to use it.
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import 'foo' // filename: foo.ts
12
+ import './foo' // filename: foo.ts
13
+ import {} from 'foo' // filename: foo.ts
14
+ import {} from './foo' // filename: foo.ts
15
+ import './reflect-metadata' // filename: foo.ts
16
+ import './foo.module.css' // filename: foo.ts
17
+ import 'foo.module.css' // filename: foo.ts
18
+ ```
19
+
20
+ ### Pass
21
+
22
+ ```ts
23
+ import 'reflect-metadata' // filename: foo.ts
24
+ import {} from 'reflect-metadata' // filename: foo.ts
25
+ import 'foo.css' // filename: foo.ts
26
+ import './foo.css' // filename: foo.ts
27
+ import 'module.css' // filename: foo.ts
28
+ import {foo} from 'foo' // filename: foo.ts
29
+ import 'foo' // filename: foo.d.ts
30
+ ```
31
+ <!-- prettier-ignore-end -->
@@ -0,0 +1,119 @@
1
+ <!-- prettier-ignore-start -->
2
+ # no-ts-file-imports
3
+
4
+ Disallow importing from a declaration style file or a ts file
5
+
6
+ ## Rule Details
7
+
8
+ ### Fail
9
+
10
+ ```ts
11
+ import foo from './foo.ts' // filename: bar.js
12
+ import foo from './foo.ts' // filename: bar
13
+ import foo from './foo.ts' // filename: bar.ts
14
+ import foo from './foo.ts' // filename: bar.tsx
15
+ import foo from './foo.cts' // filename: bar.js
16
+ import foo from './foo.cts' // filename: bar
17
+ import foo from './foo.cts' // filename: bar.ts
18
+ import foo from './foo.cts' // filename: bar.tsx
19
+ import foo from './foo.mts' // filename: bar.js
20
+ import foo from './foo.mts' // filename: bar
21
+ import foo from './foo.mts' // filename: bar.ts
22
+ import foo from './foo.mts' // filename: bar.tsx
23
+ import foo from './foo.tsx' // filename: bar.js
24
+ import foo from './foo.tsx' // filename: bar
25
+ import foo from './foo.tsx' // filename: bar.ts
26
+ import foo from './foo.tsx' // filename: bar.tsx
27
+ import foo from 'foo.d.bar' // filename: bar.js
28
+ import foo from 'foo.d.bar' // filename: bar
29
+ import foo from 'foo.d.bar' // filename: bar.ts
30
+ import foo from 'foo.d.bar' // filename: bar.tsx
31
+ import foo from './foo.d.bar' // filename: bar.js
32
+ import foo from './foo.d.bar' // filename: bar
33
+ import foo from './foo.d.bar' // filename: bar.ts
34
+ import foo from './foo.d.bar' // filename: bar.tsx
35
+ import foo from './foo/foo.d.bar' // filename: bar.js
36
+ import foo from './foo/foo.d.bar' // filename: bar
37
+ import foo from './foo/foo.d.bar' // filename: bar.ts
38
+ import foo from './foo/foo.d.bar' // filename: bar.tsx
39
+ import foo from './foo.d.ts' // filename: bar.js
40
+ import foo from './foo.d.ts' // filename: bar
41
+ import foo from './foo.d.ts' // filename: bar.ts
42
+ import foo from './foo.d.ts' // filename: bar.tsx
43
+ import foo from './foo.d.cts' // filename: bar.js
44
+ import foo from './foo.d.cts' // filename: bar
45
+ import foo from './foo.d.cts' // filename: bar.ts
46
+ import foo from './foo.d.cts' // filename: bar.tsx
47
+ import foo from './foo.d.mts' // filename: bar.js
48
+ import foo from './foo.d.mts' // filename: bar
49
+ import foo from './foo.d.mts' // filename: bar.ts
50
+ import foo from './foo.d.mts' // filename: bar.tsx
51
+ import foo from './foo.d.tsx' // filename: bar.js
52
+ import foo from './foo.d.tsx' // filename: bar
53
+ import foo from './foo.d.tsx' // filename: bar.ts
54
+ import foo from './foo.d.tsx' // filename: bar.tsx
55
+ import foo from './foo.d.js' // filename: bar.js
56
+ import foo from './foo.d.js' // filename: bar
57
+ import foo from './foo.d.js' // filename: bar.ts
58
+ import foo from './foo.d.js' // filename: bar.tsx
59
+ import foo from './foo.d.cjs' // filename: bar.js
60
+ import foo from './foo.d.cjs' // filename: bar
61
+ import foo from './foo.d.cjs' // filename: bar.ts
62
+ import foo from './foo.d.cjs' // filename: bar.tsx
63
+ import foo from './foo.d.mjs' // filename: bar.js
64
+ import foo from './foo.d.mjs' // filename: bar
65
+ import foo from './foo.d.mjs' // filename: bar.ts
66
+ import foo from './foo.d.mjs' // filename: bar.tsx
67
+ import foo from './foo.d.jsx' // filename: bar.js
68
+ import foo from './foo.d.jsx' // filename: bar
69
+ import foo from './foo.d.jsx' // filename: bar.ts
70
+ import foo from './foo.d.jsx' // filename: bar.tsx
71
+ import foo from '/foo.ts' // filename: bar.js
72
+ import foo from '/foo.ts' // filename: bar
73
+ import foo from '/foo.ts' // filename: bar.ts
74
+ import foo from '/foo.ts' // filename: bar.tsx
75
+ import foo from '/foo.d.js' // filename: bar.js
76
+ import foo from '/foo.d.js' // filename: bar
77
+ import foo from '/foo.d.js' // filename: bar.ts
78
+ import foo from '/foo.d.js' // filename: bar.tsx
79
+ ```
80
+
81
+ ### Pass
82
+
83
+ ```ts
84
+ import foo from './foo.ts' // filename: bar.d.ts
85
+ import foo from './foo.ts' // filename: bar.d.tsx
86
+ import foo from './foo.cts' // filename: bar.d.ts
87
+ import foo from './foo.cts' // filename: bar.d.tsx
88
+ import foo from './foo.mts' // filename: bar.d.ts
89
+ import foo from './foo.mts' // filename: bar.d.tsx
90
+ import foo from './foo.tsx' // filename: bar.d.ts
91
+ import foo from './foo.tsx' // filename: bar.d.tsx
92
+ import foo from 'foo.d.bar' // filename: bar.d.ts
93
+ import foo from 'foo.d.bar' // filename: bar.d.tsx
94
+ import foo from './foo.d.bar' // filename: bar.d.ts
95
+ import foo from './foo.d.bar' // filename: bar.d.tsx
96
+ import foo from './foo/foo.d.bar' // filename: bar.d.ts
97
+ import foo from './foo/foo.d.bar' // filename: bar.d.tsx
98
+ import foo from './foo.d.ts' // filename: bar.d.ts
99
+ import foo from './foo.d.ts' // filename: bar.d.tsx
100
+ import foo from './foo.d.cts' // filename: bar.d.ts
101
+ import foo from './foo.d.cts' // filename: bar.d.tsx
102
+ import foo from './foo.d.mts' // filename: bar.d.ts
103
+ import foo from './foo.d.mts' // filename: bar.d.tsx
104
+ import foo from './foo.d.tsx' // filename: bar.d.ts
105
+ import foo from './foo.d.tsx' // filename: bar.d.tsx
106
+ import foo from './foo.d.js' // filename: bar.d.ts
107
+ import foo from './foo.d.js' // filename: bar.d.tsx
108
+ import foo from './foo.d.cjs' // filename: bar.d.ts
109
+ import foo from './foo.d.cjs' // filename: bar.d.tsx
110
+ import foo from './foo.d.mjs' // filename: bar.d.ts
111
+ import foo from './foo.d.mjs' // filename: bar.d.tsx
112
+ import foo from './foo.d.jsx' // filename: bar.d.ts
113
+ import foo from './foo.d.jsx' // filename: bar.d.tsx
114
+ import foo from '/foo.ts' // filename: bar.d.ts
115
+ import foo from '/foo.ts' // filename: bar.d.tsx
116
+ import foo from '/foo.d.js' // filename: bar.d.ts
117
+ import foo from '/foo.d.js' // filename: bar.d.tsx
118
+ ```
119
+ <!-- prettier-ignore-end -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-esm",
3
- "version": "0.0.0",
3
+ "version": "0.1.1",
4
4
  "description": "ESLint plugin for linting ESM (import/export syntax)",
5
5
  "keywords": [
6
6
  "eslint",
@@ -27,13 +27,15 @@
27
27
  "devDependencies": {
28
28
  "@swc-node/register": "1.10.0",
29
29
  "@types/eslint": "8.56.11",
30
- "@types/estree": "1.0.5",
30
+ "@types/estree": "1.0.6",
31
31
  "@types/json-schema": "7.0.15",
32
- "@types/node": "22.5.4",
32
+ "@types/node": "22.5.5",
33
33
  "@typescript-eslint/parser": "7.16.1",
34
- "eslint": "8.57.0"
34
+ "eslint": "8.57.0",
35
+ "outdent": "0.8.0"
35
36
  },
36
37
  "scripts": {
37
- "build": "tsc -p tsconfig.build.json"
38
+ "build": "tsc -p tsconfig.build.json",
39
+ "test": "globstar -- node --test --import @swc-node/register/esm-register src/**/*.spec.ts"
38
40
  }
39
41
  }
package/src/common.ts ADDED
@@ -0,0 +1,96 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import type { Rule } from "eslint";
4
+ import type {
5
+ ExportAllDeclaration,
6
+ ExportNamedDeclaration,
7
+ ImportDeclaration,
8
+ ImportExpression,
9
+ } from "estree";
10
+
11
+ export const DEFAULT_MESSAGE_ID = "default";
12
+
13
+ export function createRule({
14
+ name,
15
+ message,
16
+ // schema,
17
+ fixable,
18
+ type = "suggestion",
19
+ create,
20
+ }: {
21
+ name: string;
22
+ message: string;
23
+ // schema?: JSONSchema4[];
24
+ fixable?: Rule.RuleMetaData["fixable"];
25
+ type?: Rule.RuleMetaData["type"];
26
+ create: (context: Rule.RuleContext) => Rule.RuleListener;
27
+ }): { name: string; rule: Rule.RuleModule } {
28
+ const rule: Rule.RuleModule = {
29
+ meta: {
30
+ // ...(schema && { schema }),
31
+ ...(fixable && { fixable }),
32
+ messages: {
33
+ [DEFAULT_MESSAGE_ID]: message,
34
+ },
35
+ type,
36
+ docs: {
37
+ // TODO: add url
38
+ description: message,
39
+ },
40
+ },
41
+ create,
42
+ };
43
+ return { name, rule };
44
+ }
45
+
46
+ export function getRuleName(importMetaUrl: string) {
47
+ // remove '.js' extension
48
+ return path.basename(fileURLToPath(importMetaUrl)).slice(0, -3);
49
+ }
50
+
51
+ export type ImportationNode =
52
+ | ImportDeclaration
53
+ | ImportExpression
54
+ | ExportAllDeclaration
55
+ | ExportNamedDeclaration;
56
+
57
+ /**
58
+ * Create ESLint RuleListener to check string importation source.
59
+ * @param context ESLint RuleContext
60
+ * @param check the check logic
61
+ * @returns ESLint RuleListener
62
+ */
63
+ export const create = (
64
+ context: Rule.RuleContext,
65
+ check: (filename: string, source: string, node: ImportationNode) => boolean,
66
+ ): Rule.RuleListener => {
67
+ const handle = (node: ImportationNode) => {
68
+ if (!node.source) return;
69
+ if (!("value" in node.source)) return;
70
+ if (typeof node.source.value !== "string") return;
71
+ if (check(context.filename, node.source.value, node))
72
+ context.report({ node: node.source, messageId: DEFAULT_MESSAGE_ID });
73
+ };
74
+ return {
75
+ ImportDeclaration: handle,
76
+ ImportExpression: handle,
77
+ ExportAllDeclaration: handle,
78
+ ExportNamedDeclaration: handle,
79
+ };
80
+ };
81
+
82
+ export function getSourceType(source: string) {
83
+ if (
84
+ source.startsWith("/") ||
85
+ source.startsWith("./") ||
86
+ source.startsWith("../") ||
87
+ source === "." ||
88
+ source === ".."
89
+ ) {
90
+ return "local";
91
+ }
92
+ if (source.startsWith("node:")) {
93
+ return "builtin";
94
+ }
95
+ return "module";
96
+ }