@blumintinc/eslint-plugin-blumint 1.20.197 → 1.20.198

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.197',
226
+ version: '1.20.198',
227
227
  },
228
228
  parseOptions: {
229
229
  ecmaVersion: 2020,
@@ -109,6 +109,51 @@ function readExhaustiveDepsDisable(comment) {
109
109
  }
110
110
  return comment.type === utils_1.AST_TOKEN_TYPES.Block ? 'file' : null;
111
111
  }
112
+ /**
113
+ * Whether a dependency's type is a primitive, so that narrowing it into member
114
+ * paths is meaningless and an unread entry is a deliberate recompute trigger
115
+ * rather than a stale object.
116
+ *
117
+ * why the `*Like` flags, never the bare ones: each `*Like` is the union of a
118
+ * primitive and its LITERAL form, and a literal type is what this repo's own
119
+ * fixers produce. `global-const-style` appends `as const`, which turns `0` into
120
+ * the numeric literal type `0`. The list used to name `StringLiteral`
121
+ * explicitly but `Number` and `Boolean` bare, so a string literal was primitive
122
+ * while `0 as const` and `true as const` were not — the same value lost its
123
+ * exemption the moment a sibling fixer froze it, which made this an exemption
124
+ * destroyed by COMPOSITION rather than a latent gap (#2238).
125
+ *
126
+ * why unions are walked: a union carries `TypeFlags.Union` and none of the
127
+ * flags above, so a bitmask test on the union ITSELF answers no for
128
+ * `'compact' | 'full'` — a string at runtime, and the shape
129
+ * `prefer-union-from-const-array` leaves behind. A union is primitive exactly
130
+ * when every constituent is, which also keeps `string | { a: number }` an
131
+ * object.
132
+ */
133
+ function isPrimitiveType(type) {
134
+ // why the mask is built HERE and not hoisted to module scope: this module is
135
+ // imported by `src/index.ts`, so a module-scope `TypeFlags.X` is read the
136
+ // moment the plugin loads. Against a compiler that does not root-export the
137
+ // API, `TypeFlags` is `undefined` and the read throws — taking down every
138
+ // rule in the plugin, not just this one. `plugin-load-without-compiler-api`
139
+ // is the guard that says so.
140
+ const primitiveFlags = typescript_1.TypeFlags.StringLike |
141
+ typescript_1.TypeFlags.NumberLike |
142
+ typescript_1.TypeFlags.BooleanLike |
143
+ typescript_1.TypeFlags.BigIntLike |
144
+ typescript_1.TypeFlags.ESSymbolLike |
145
+ typescript_1.TypeFlags.Null |
146
+ typescript_1.TypeFlags.Undefined |
147
+ typescript_1.TypeFlags.Void |
148
+ typescript_1.TypeFlags.Never;
149
+ if (type.flags & primitiveFlags)
150
+ return true;
151
+ if (type.flags & typescript_1.TypeFlags.Union) {
152
+ const constituents = type.types;
153
+ return constituents.length > 0 && constituents.every(isPrimitiveType);
154
+ }
155
+ return false;
156
+ }
112
157
  /** `channelGroupActive` -> `setChannelGroupActive`, `a` -> `setA`. */
113
158
  function toSetterName(dependencyName) {
114
159
  return `set${dependencyName.charAt(0).toUpperCase()}${dependencyName.slice(1)}`;
@@ -119,19 +164,16 @@ function isArrayOrPrimitive(checker, esTreeNode, nodeMap) {
119
164
  if (!tsNode)
120
165
  return false;
121
166
  const type = checker.getTypeAtLocation(tsNode);
122
- // Check if it's a primitive type
123
- if (type.flags &
124
- (typescript_1.TypeFlags.String |
125
- typescript_1.TypeFlags.StringLike |
126
- typescript_1.TypeFlags.StringLiteral |
127
- typescript_1.TypeFlags.Number |
128
- typescript_1.TypeFlags.Boolean |
129
- typescript_1.TypeFlags.Null |
130
- typescript_1.TypeFlags.Undefined |
131
- typescript_1.TypeFlags.Void |
132
- typescript_1.TypeFlags.Never |
133
- typescript_1.TypeFlags.BigInt |
134
- typescript_1.TypeFlags.ESSymbol)) {
167
+ // why: the `*Like` flags, never the bare ones. Each `*Like` is the union of
168
+ // a primitive and its LITERAL form, and a literal type is what this repo's
169
+ // own `global-const-style` produces — it appends `as const`, which turns
170
+ // `0` into the numeric literal type `0`. The list used to name
171
+ // `StringLiteral` explicitly but `Number` and `Boolean` bare, so a string
172
+ // literal was primitive while `0 as const` and `true as const` were not:
173
+ // the same value lost the exemption the moment a sibling fixer froze it
174
+ // (#2238). Enum members come in through `NumberLike`/`StringLike` for the
175
+ // same reason — an enum member is a primitive at runtime.
176
+ if (isPrimitiveType(type)) {
135
177
  return true;
136
178
  }
137
179
  // Check if it's an array type
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.20.197",
3
+ "version": "1.20.198",
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.198",
4
+ "date": "2026-08-31T11:06:34.784Z",
5
+ "rules": [
6
+ {
7
+ "name": "no-entire-object-hook-deps",
8
+ "changeType": "fix",
9
+ "issues": [
10
+ 2238
11
+ ],
12
+ "summary": "treat a literal type as the primitive it is (closes #2238)"
13
+ }
14
+ ]
15
+ },
2
16
  {
3
17
  "version": "1.20.197",
4
18
  "date": "2026-08-31T08:50:13.198Z",