@blumintinc/eslint-plugin-blumint 1.12.3 → 1.12.5

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.
package/lib/index.js CHANGED
@@ -105,10 +105,11 @@ const no_margin_properties_1 = require("./rules/no-margin-properties");
105
105
  const enforce_boolean_naming_prefixes_1 = require("./rules/enforce-boolean-naming-prefixes");
106
106
  const prefer_block_comments_for_declarations_1 = require("./rules/prefer-block-comments-for-declarations");
107
107
  const no_undefined_null_passthrough_1 = require("./rules/no-undefined-null-passthrough");
108
+ const no_restricted_imports_dynamic_1 = __importDefault(require("./rules/no-restricted-imports-dynamic"));
108
109
  module.exports = {
109
110
  meta: {
110
111
  name: '@blumintinc/eslint-plugin-blumint',
111
- version: '1.12.3',
112
+ version: '1.12.5',
112
113
  },
113
114
  parseOptions: {
114
115
  ecmaVersion: 2020,
@@ -225,6 +226,7 @@ module.exports = {
225
226
  '@blumintinc/blumint/no-margin-properties': 'error',
226
227
  '@blumintinc/blumint/enforce-boolean-naming-prefixes': 'error',
227
228
  '@blumintinc/blumint/no-undefined-null-passthrough': 'error',
229
+ '@blumintinc/blumint/no-restricted-imports-dynamic': 'error',
228
230
  },
229
231
  },
230
232
  },
@@ -331,6 +333,7 @@ module.exports = {
331
333
  'no-margin-properties': no_margin_properties_1.noMarginProperties,
332
334
  'enforce-boolean-naming-prefixes': enforce_boolean_naming_prefixes_1.enforceBooleanNamingPrefixes,
333
335
  'no-undefined-null-passthrough': no_undefined_null_passthrough_1.noUndefinedNullPassthrough,
336
+ 'no-restricted-imports-dynamic': no_restricted_imports_dynamic_1.default,
334
337
  },
335
338
  };
336
339
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,25 @@
1
+ export declare const RULE_NAME = "no-restricted-imports-dynamic";
2
+ type Options = [
3
+ {
4
+ paths?: (string | {
5
+ name: string;
6
+ message?: string;
7
+ allowTypeImports?: boolean;
8
+ allowDynamicImports?: boolean;
9
+ })[];
10
+ patterns?: (string | {
11
+ group: string[];
12
+ message?: string;
13
+ caseSensitive?: boolean;
14
+ allowTypeImports?: boolean;
15
+ allowDynamicImports?: boolean;
16
+ })[];
17
+ } | (string | {
18
+ name: string;
19
+ message?: string;
20
+ allowTypeImports?: boolean;
21
+ allowDynamicImports?: boolean;
22
+ })[]
23
+ ];
24
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"restrictedImport" | "restrictedImportPattern", Options, import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
25
+ export default _default;
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RULE_NAME = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const createRule_1 = require("../utils/createRule");
9
+ exports.RULE_NAME = 'no-restricted-imports-dynamic';
10
+ exports.default = (0, createRule_1.createRule)({
11
+ name: exports.RULE_NAME,
12
+ meta: {
13
+ type: 'suggestion',
14
+ docs: {
15
+ description: 'Disallow specified modules when loaded by `import`, with special handling for .dynamic.tsx files',
16
+ recommended: 'error',
17
+ },
18
+ schema: [
19
+ {
20
+ oneOf: [
21
+ {
22
+ type: 'object',
23
+ properties: {
24
+ paths: {
25
+ type: 'array',
26
+ items: {
27
+ oneOf: [
28
+ { type: 'string' },
29
+ {
30
+ type: 'object',
31
+ properties: {
32
+ name: { type: 'string' },
33
+ message: { type: 'string' },
34
+ allowTypeImports: { type: 'boolean' },
35
+ allowDynamicImports: { type: 'boolean' },
36
+ },
37
+ additionalProperties: false,
38
+ required: ['name'],
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ patterns: {
44
+ type: 'array',
45
+ items: {
46
+ oneOf: [
47
+ { type: 'string' },
48
+ {
49
+ type: 'object',
50
+ properties: {
51
+ group: {
52
+ type: 'array',
53
+ items: { type: 'string' },
54
+ minItems: 1,
55
+ },
56
+ message: { type: 'string' },
57
+ caseSensitive: { type: 'boolean' },
58
+ allowTypeImports: { type: 'boolean' },
59
+ allowDynamicImports: { type: 'boolean' },
60
+ },
61
+ additionalProperties: false,
62
+ required: ['group'],
63
+ },
64
+ ],
65
+ },
66
+ },
67
+ },
68
+ additionalProperties: false,
69
+ },
70
+ {
71
+ type: 'array',
72
+ items: {
73
+ oneOf: [
74
+ { type: 'string' },
75
+ {
76
+ type: 'object',
77
+ properties: {
78
+ name: { type: 'string' },
79
+ message: { type: 'string' },
80
+ allowTypeImports: { type: 'boolean' },
81
+ allowDynamicImports: { type: 'boolean' },
82
+ },
83
+ additionalProperties: false,
84
+ required: ['name'],
85
+ },
86
+ ],
87
+ },
88
+ },
89
+ ],
90
+ },
91
+ ],
92
+ messages: {
93
+ restrictedImport: "import '{{importSource}}' is restricted from being used{{customMessage}}",
94
+ restrictedImportPattern: "import '{{importSource}}' is restricted from being used by a pattern{{customMessage}}",
95
+ },
96
+ },
97
+ defaultOptions: [{ paths: [], patterns: [] }],
98
+ create(context, [options]) {
99
+ // Get the file path and name
100
+ const filePath = context.getFilename();
101
+ const fileName = path_1.default.basename(filePath);
102
+ // Check if the file has .dynamic.ts or .dynamic.tsx extension
103
+ const isDynamicFile = /\.dynamic\.tsx?$/.test(fileName);
104
+ // If this is a dynamic file, we'll allow imports from other dynamic files
105
+ if (isDynamicFile) {
106
+ return {};
107
+ }
108
+ // Process options
109
+ const restrictedPaths = [];
110
+ const restrictedPatterns = [];
111
+ if (Array.isArray(options)) {
112
+ // Handle array format
113
+ for (const item of options) {
114
+ if (typeof item === 'string') {
115
+ restrictedPaths.push({ name: item });
116
+ }
117
+ else {
118
+ restrictedPaths.push(item);
119
+ }
120
+ }
121
+ }
122
+ else if (options && typeof options === 'object') {
123
+ // Handle object format
124
+ if (options.paths) {
125
+ for (const item of options.paths) {
126
+ if (typeof item === 'string') {
127
+ restrictedPaths.push({ name: item });
128
+ }
129
+ else {
130
+ restrictedPaths.push(item);
131
+ }
132
+ }
133
+ }
134
+ if (options.patterns) {
135
+ for (const item of options.patterns) {
136
+ if (typeof item === 'string') {
137
+ restrictedPatterns.push({ group: [item] });
138
+ }
139
+ else {
140
+ restrictedPatterns.push(item);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return {
146
+ ImportDeclaration(node) {
147
+ const importSource = node.source.value;
148
+ const importKind = node.importKind;
149
+ // Check against restricted paths
150
+ for (const restrictedPath of restrictedPaths) {
151
+ if (importSource === restrictedPath.name) {
152
+ // Skip if it's a type import and type imports are allowed
153
+ if (importKind === 'type' &&
154
+ restrictedPath.allowTypeImports === true) {
155
+ continue;
156
+ }
157
+ // Skip if it's a dynamic import and dynamic imports are allowed
158
+ if (importSource.endsWith('.dynamic') &&
159
+ restrictedPath.allowDynamicImports === true) {
160
+ continue;
161
+ }
162
+ context.report({
163
+ node,
164
+ messageId: 'restrictedImport',
165
+ data: {
166
+ importSource,
167
+ customMessage: restrictedPath.message
168
+ ? `: ${restrictedPath.message}`
169
+ : '',
170
+ },
171
+ });
172
+ }
173
+ }
174
+ // Check against restricted patterns
175
+ for (const restrictedPattern of restrictedPatterns) {
176
+ const { group, caseSensitive = false } = restrictedPattern;
177
+ const matched = group.some((pattern) => {
178
+ if (pattern.includes('*')) {
179
+ const regex = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`, caseSensitive ? '' : 'i');
180
+ return regex.test(importSource);
181
+ }
182
+ return caseSensitive
183
+ ? importSource === pattern
184
+ : importSource.toLowerCase() === pattern.toLowerCase();
185
+ });
186
+ if (matched) {
187
+ // Skip if it's a type import and type imports are allowed
188
+ if (importKind === 'type' &&
189
+ restrictedPattern.allowTypeImports === true) {
190
+ continue;
191
+ }
192
+ // Skip if it's a dynamic import and dynamic imports are allowed
193
+ if (importSource.endsWith('.dynamic') &&
194
+ restrictedPattern.allowDynamicImports === true) {
195
+ continue;
196
+ }
197
+ context.report({
198
+ node,
199
+ messageId: 'restrictedImportPattern',
200
+ data: {
201
+ importSource,
202
+ customMessage: restrictedPattern.message
203
+ ? `: ${restrictedPattern.message}`
204
+ : '',
205
+ },
206
+ });
207
+ }
208
+ }
209
+ },
210
+ };
211
+ },
212
+ });
213
+ //# sourceMappingURL=no-restricted-imports-dynamic.js.map
@@ -28,6 +28,12 @@ function isTypePredicate(node) {
28
28
  function isInsideReturnStatement(node) {
29
29
  let current = node;
30
30
  while (current?.parent) {
31
+ // If we encounter a variable declaration before a return statement,
32
+ // then the node is not directly inside a return statement
33
+ if (current.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator ||
34
+ current.parent.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
35
+ return false;
36
+ }
31
37
  if (current.parent.type === utils_1.AST_NODE_TYPES.ReturnStatement) {
32
38
  return true;
33
39
  }
@@ -16,6 +16,15 @@ exports.preferBlockCommentsForDeclarations = (0, createRule_1.createRule)({
16
16
  if (comment.type !== 'Line') {
17
17
  return false;
18
18
  }
19
+ // Ignore ESLint directive comments
20
+ const commentText = comment.value.trim();
21
+ if (commentText.startsWith('eslint-disable') ||
22
+ commentText.startsWith('eslint-enable') ||
23
+ commentText.startsWith('eslint-env') ||
24
+ commentText.startsWith('global ') ||
25
+ commentText.startsWith('globals ')) {
26
+ return false;
27
+ }
19
28
  // Check if the comment is directly before the node
20
29
  const commentLine = comment.loc.end.line;
21
30
  const nodeLine = node.loc.start.line;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.12.3",
3
+ "version": "1.12.5",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",