@blumintinc/eslint-plugin-blumint 1.7.2 → 1.7.3

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
@@ -73,7 +73,7 @@ const prefer_fragment_component_1 = require("./rules/prefer-fragment-component")
73
73
  module.exports = {
74
74
  meta: {
75
75
  name: '@blumintinc/eslint-plugin-blumint',
76
- version: '1.7.2',
76
+ version: '1.7.3',
77
77
  },
78
78
  parseOptions: {
79
79
  ecmaVersion: 2020,
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.enforceCentralizedMockFirestore = void 0;
4
4
  const utils_1 = require("@typescript-eslint/utils");
5
5
  const createRule_1 = require("../utils/createRule");
6
- const MOCK_FIRESTORE_PATH = '../../../../../__mocks__/functions/src/config/mockFirestore';
6
+ const MOCK_FIRESTORE_PATH = '../../../../../__test-utils__/mockFirestore';
7
7
  exports.enforceCentralizedMockFirestore = (0, createRule_1.createRule)({
8
8
  name: 'enforce-centralized-mock-firestore',
9
9
  meta: {
@@ -18,8 +18,8 @@ exports.enforceFirestoreMock = (0, createRule_1.createRule)({
18
18
  },
19
19
  schema: [],
20
20
  messages: {
21
- noManualFirestoreMock: 'Use mockFirestore from __mocks__/functions/src/config/mockFirestore instead of manually mocking Firestore. Replace `jest.mock("firebase-admin", () => ({ firestore: () => ({ /* mock */ }) }))` with `import { mockFirestore } from "__mocks__/functions/src/config/mockFirestore"; jest.mock("firebase-admin", () => mockFirestore)`.',
22
- noMockFirebase: 'Use mockFirestore from __mocks__/functions/src/config/mockFirestore instead of mockFirebase. Replace `import { mockFirebase } from "firestore-jest-mock"` with `import { mockFirestore } from "__mocks__/functions/src/config/mockFirestore"`.',
21
+ noManualFirestoreMock: 'Use mockFirestore from __test-utils__/mockFirestore instead of manually mocking Firestore. Replace `jest.mock("firebase-admin", () => ({ firestore: () => ({ /* mock */ }) }))` with `import { mockFirestore } from "__test-utils__/mockFirestore"; jest.mock("firebase-admin", () => mockFirestore)`.',
22
+ noMockFirebase: 'Use mockFirestore from __test-utils__/mockFirestore instead of mockFirebase. Replace `import { mockFirebase } from "firestore-jest-mock"` with `import { mockFirestore } from "__test-utils__/mockFirestore"`.',
23
23
  },
24
24
  },
25
25
  defaultOptions: [],
@@ -35,7 +35,27 @@ exports.enforceRenderHitsMemoization = (0, createRule_1.createRule)({
35
35
  const name = node.name;
36
36
  return /^[A-Z]/.test(name);
37
37
  };
38
+ const isMemoizedVariable = (node) => {
39
+ if (node.type !== utils_1.AST_NODE_TYPES.Identifier)
40
+ return false;
41
+ // Get the variable declaration for this identifier
42
+ const variable = context.getScope().variables.find(v => v.name === node.name);
43
+ if (!variable)
44
+ return false;
45
+ // Check if the variable is initialized with a memoized call
46
+ const def = variable.defs[0];
47
+ if (!def || !def.node)
48
+ return false;
49
+ if (def.node.type === utils_1.AST_NODE_TYPES.VariableDeclarator && def.node.init) {
50
+ return isMemoizedCall(def.node.init);
51
+ }
52
+ return false;
53
+ };
38
54
  const isInsideMemoizedCall = (node) => {
55
+ // Check if the node is a reference to a memoized variable
56
+ if (isMemoizedVariable(node))
57
+ return true;
58
+ // Check if the node is inside a memoization hook call
39
59
  let current = node;
40
60
  while (current?.parent) {
41
61
  if (isMemoizedCall(current.parent))
@@ -10,6 +10,7 @@ const compromise_1 = __importDefault(require("compromise"));
10
10
  const PREPOSITIONS = new Set(['to', 'from', 'with', 'by', 'at', 'of']);
11
11
  // Create a Set from the verbs list for O(1) lookup
12
12
  const VERBS_SET = new Set([
13
+ 'clean',
13
14
  'abbreviate',
14
15
  'abort',
15
16
  'abstract',
@@ -32,7 +32,7 @@ exports.noFirestoreJestMock = (0, createRule_1.createRule)({
32
32
  messageId: 'noFirestoreJestMock',
33
33
  fix(fixer) {
34
34
  // Replace with mockFirestore import
35
- return fixer.replaceText(node, "import { mockFirestore } from '../../../../../__mocks__/functions/src/config/mockFirestore';");
35
+ return fixer.replaceText(node, "import { mockFirestore } from '../../../../../__test-utils__/mockFirestore';");
36
36
  },
37
37
  });
38
38
  }
@@ -19,7 +19,7 @@ exports.noMockFirebaseAdmin = (0, createRule_1.createRule)({
19
19
  },
20
20
  schema: [],
21
21
  messages: {
22
- noMockFirebaseAdmin: 'Do not mock firebaseAdmin directly. Use mockFirestore from __mocks__/functions/src/config/mockFirestore instead.',
22
+ noMockFirebaseAdmin: 'Do not mock firebaseAdmin directly. Use mockFirestore from __test-utils__/mockFirestore instead.',
23
23
  },
24
24
  },
25
25
  defaultOptions: [],
@@ -36,7 +36,53 @@ exports.noUnusedProps = (0, createRule_1.createRule)({
36
36
  });
37
37
  }
38
38
  else if (typeNode.type === utils_1.AST_NODE_TYPES.TSIntersectionType) {
39
- typeNode.types.forEach(extractProps);
39
+ typeNode.types.forEach((type) => {
40
+ if (type.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
41
+ const typeName = type.typeName;
42
+ if (typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
43
+ if (typeName.name === 'Pick' && type.typeParameters) {
44
+ // Handle Pick utility type in intersection
45
+ const [baseType, pickedProps] = type.typeParameters.params;
46
+ if (baseType.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
47
+ baseType.typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
48
+ // Extract the picked properties from the union type
49
+ if (pickedProps.type === utils_1.AST_NODE_TYPES.TSUnionType) {
50
+ pickedProps.types.forEach((t) => {
51
+ if (t.type === utils_1.AST_NODE_TYPES.TSLiteralType &&
52
+ t.literal.type === utils_1.AST_NODE_TYPES.Literal &&
53
+ typeof t.literal.value === 'string') {
54
+ // Add each picked property as a regular prop
55
+ props[t.literal.value] = t.literal;
56
+ }
57
+ });
58
+ }
59
+ else if (pickedProps.type === utils_1.AST_NODE_TYPES.TSLiteralType &&
60
+ pickedProps.literal.type === utils_1.AST_NODE_TYPES.Literal &&
61
+ typeof pickedProps.literal.value === 'string') {
62
+ // Single property pick
63
+ props[pickedProps.literal.value] = pickedProps.literal;
64
+ }
65
+ }
66
+ }
67
+ else {
68
+ // For referenced types in intersections, we need to find their type declaration
69
+ const scope = context.getScope();
70
+ const variable = scope.variables.find(v => v.name === typeName.name);
71
+ if (variable && variable.defs[0]?.node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
72
+ extractProps(variable.defs[0].node.typeAnnotation);
73
+ }
74
+ else {
75
+ // If we can't find the type declaration, it's likely an imported type
76
+ // Mark it as a forwarded prop
77
+ props[`...${typeName.name}`] = typeName;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ else {
83
+ extractProps(type);
84
+ }
85
+ });
40
86
  }
41
87
  else if (typeNode.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
42
88
  if (typeNode.typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.7.2",
3
+ "version": "1.7.3",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",