@blumintinc/eslint-plugin-blumint 1.20.128 → 1.20.129

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
@@ -223,7 +223,7 @@ function noFrontendImportsFromFunctionsPatterns(pattern) {
223
223
  module.exports = {
224
224
  meta: {
225
225
  name: '@blumintinc/eslint-plugin-blumint',
226
- version: '1.20.128',
226
+ version: '1.20.129',
227
227
  },
228
228
  parseOptions: {
229
229
  ecmaVersion: 2020,
@@ -37,6 +37,28 @@ exports.noCircularReferences = (0, createRule_1.createRule)({
37
37
  ? current
38
38
  : null;
39
39
  }
40
+ /**
41
+ * The expression a runtime-transparent wrapper stands in for.
42
+ *
43
+ * `a?.b` parses as a `ChainExpression` around the member read, and
44
+ * resolution has to see through it: the optional link records that the
45
+ * access short-circuits, not that it names something else. Whenever the
46
+ * receiver is non-nullish — and an object literal bound to a `const` always
47
+ * is — `cfg?.node` evaluates to exactly `cfg.node`, so it aliases the same
48
+ * object and belongs to the same cycle. Stopping at the wrapper drops the
49
+ * alias, and a real cycle goes unreported.
50
+ *
51
+ * Local rather than folded into `ASTHelpers.unwrapTSAssertions`, because
52
+ * that helper answers "which assertions restate this expression" for five
53
+ * other rules, and a chain is a different question for each of them.
54
+ */
55
+ function unwrapTransparent(node) {
56
+ let current = ASTHelpers_1.ASTHelpers.unwrapTSAssertions(node);
57
+ while (current.type === utils_1.AST_NODE_TYPES.ChainExpression) {
58
+ current = ASTHelpers_1.ASTHelpers.unwrapTSAssertions(current.expression);
59
+ }
60
+ return current;
61
+ }
40
62
  function isIdentifier(node) {
41
63
  return node.type === utils_1.AST_NODE_TYPES.Identifier;
42
64
  }
@@ -66,7 +88,7 @@ exports.noCircularReferences = (0, createRule_1.createRule)({
66
88
  return null;
67
89
  }
68
90
  function getReferencedObject(node, visitedVariables = new Set(), visitedNodes = new Set()) {
69
- const current = ASTHelpers_1.ASTHelpers.unwrapTSAssertions(node);
91
+ const current = unwrapTransparent(node);
70
92
  if (visitedNodes.has(current))
71
93
  return null;
72
94
  visitedNodes.add(current);
@@ -129,14 +151,19 @@ exports.noCircularReferences = (0, createRule_1.createRule)({
129
151
  }
130
152
  }
131
153
  if (propValue) {
132
- const unwrappedValue = getUnwrappedObjectOrArray(propValue);
154
+ // The stored value keeps whatever notation it was written with, so
155
+ // the dispatch below asks its question of the expression that
156
+ // notation stands for — `{ b: level1?.a }` reaches here as a
157
+ // ChainExpression and would otherwise match no arm at all.
158
+ const resolvedValue = unwrapTransparent(propValue);
159
+ const unwrappedValue = getUnwrappedObjectOrArray(resolvedValue);
133
160
  if (unwrappedValue)
134
161
  return unwrappedValue;
135
- if (isIdentifier(propValue) ||
136
- propValue.type === utils_1.AST_NODE_TYPES.MemberExpression) {
137
- return getReferencedObject(propValue, visitedVariables, visitedNodes);
162
+ if (isIdentifier(resolvedValue) ||
163
+ resolvedValue.type === utils_1.AST_NODE_TYPES.MemberExpression) {
164
+ return getReferencedObject(resolvedValue, visitedVariables, visitedNodes);
138
165
  }
139
- if (isFunction(propValue) || isPrimitive(propValue)) {
166
+ if (isFunction(resolvedValue) || isPrimitive(resolvedValue)) {
140
167
  return null;
141
168
  }
142
169
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.20.128",
3
+ "version": "1.20.129",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "version": "1.20.129",
4
+ "date": "2026-08-07T06:47:26.731Z",
5
+ "rules": [
6
+ {
7
+ "name": "no-circular-references",
8
+ "changeType": "fix",
9
+ "issues": [
10
+ 1838
11
+ ],
12
+ "summary": "resolve an alias through an optional chain (closes #1838)"
13
+ }
14
+ ]
15
+ },
2
16
  {
3
17
  "version": "1.20.128",
4
18
  "date": "2026-08-07T05:47:06.312Z",